ls1x-master-v0.4/private/ls1c102/ls1c102_i2c.c

560 lines
14 KiB
C
Raw Normal View History

2024-11-27 15:39:05 +08:00
//#include "Main.h"
#include "ls1c102_i2c.h"
#include "ls1x_latimer.h"
#include "Config.h"
/* I2C START mask */
#define I2C_START_Set ((uint8_t)0x80)
#define I2C_START_Reset ((uint8_t)0x7F)
/* I2C STOP mask */
#define I2C_STOP_Set ((uint8_t)0x40)
#define I2C_STOP_Reset ((uint8_t)0xBF)
/* I2C ACK mask */
#define I2C_ACK_Set ((uint8_t)0x08)
#define I2C_ACK_Reset ((uint8_t)0xF7)
/* I2C ADD0 mask */
#define I2C_ADD0_Set ((uint8_t)0x01)
#define I2C_ADD0_Reset ((uint8_t)0xFE)
#define FLAG_Mask ((uint8_t)0xFF)
#define ITEN_Mask ((uint8_t)0x40)
BOOL STS;
/**
* @brief Initializes the I2C peripheral according to the specified
* parameters in the I2C_InitStruct .
* @param I2Cx: select the I2Cx peripheral.
* This parameter can be I2C.
* @param I2C_InitStruct: pointer to an I2C_InitTypeDef structure
* that contains the configuration information for the specified I2C peripheral.
* @retval None
*/
void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct)
{
uint32_t tmp = 0;
// uint32_t result = 0x04;
uint32_t pclk1 = 8000000;
/* Check the parameters */
/*---------------------------- I2Cx Configuration ------------------------*/
I2Cx->CTRL = 0x20; //访问分频寄存器
tmp=pclk1 / I2C_InitStruct->I2C_ClockSpeed;
tmp=(tmp >> 2) -1;
I2Cx->PRERL = tmp;
/* Enable the selected I2C peripheral */
I2Cx->PRERH = tmp >> 8;
I2Cx->CTRL = 0x80 | (I2C_InitStruct->I2C_Mode)| (I2C_InitStruct->I2C_BuslockCheckEn)| (I2C_InitStruct->I2C_SlvAutoresetEn) ;
if (I2C_InitStruct->I2C_BuslockCheckEn)
{
I2Cx->CR_SR = 0x04;
}
I2Cx->SADDR = I2C_InitStruct->I2C_OwnAddress1;
I2C_wait(I2C);
}
/**
* @brief Fills each I2C_InitStruct member with its default value.
* @param I2C_InitStruct: pointer to an I2C_InitTypeDef structure which will be initialized.
* @retval None
*/
void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct)
{
/*---------------- Reset I2C init structure parameters values ----------------*/
/* initialize the I2C_ClockSpeed member */
I2C_InitStruct->I2C_ClockSpeed = 100000;
/* Initialize the I2C_Mode member */
I2C_InitStruct->I2C_Mode = I2C_Mode_Master;
// I2C_InitStruct->I2C_Mode = I2C_Mode_Slave;
/* Initialize the I2C_OwnAddress1 member */
I2C_InitStruct->I2C_OwnAddress1 = 0x2A;
/* Initialize the I2C_Buslock Check */
I2C_InitStruct->I2C_BuslockCheckEn = I2C_Buslock_Check_Enable;
/* Initialize the I2C_Slave_Autoreset */
I2C_InitStruct->I2C_SlvAutoresetEn = I2C_Slv_Autoreset_Disable;
}
/**
* brief Enables or disables the specified I2c interrupts.
* @param I2Cx: Select the I2c peripheral.
* This parameter can be I2C.
* @param NewState: new state of the specified I2Cx interrupt.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_ITConfig(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
if (NewState != DISABLE)
{
/* Enable the selected I2C interrupts */
I2Cx->CTRL |= 0X40;
}
else
{
/* Disable the selected I2C interrupts */
I2Cx->CTRL &= (uint8_t)~0X40;
}
}
/**
* brief Enables or disables the specified I2c interrupts.
* @param I2Cx: Select the I2c peripheral.
* This parameter can be I2C.
* @param NewState: new state of the specified I2Cx interrupt.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_ITCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* set the interrupt*/
INT_POL |= IRQ_I2C;
(NewState != DISABLE)? (INT_EN |= IRQ_I2C) : (INT_EN &= ~(IRQ_I2C));
}
/**
* @brief Generates I2Cx communication START condition.
* @param I2Cx: select the I2C peripheral.
* This parameter can be I2C.
* @param NewState: new state of the I2C START condition generation.
* This parameter can be: ENABLE or DISABLE.
* @retval None.
*/
void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
if (NewState != DISABLE)
{
/* Generate a START condition */
I2Cx->CR_SR |= I2C_START_Set;
}
else
{
/* Disable the START condition generation */
I2Cx->CR_SR &= I2C_START_Reset;
}
}
/**
* @brief Generates I2Cx communication STOP condition.
* @param I2Cx: select the I2C peripheral.
* This parameter can be I2C.
* @param NewState: new state of the I2C STOP condition generation.
* This parameter can be: ENABLE or DISABLE.
* @retval None.
*/
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
if (NewState != DISABLE)
{
/* Generate a STOP condition */
I2Cx->CR_SR |= I2C_STOP_Set;
}
else
{
/* Disable the STOP condition generation */
I2Cx->CR_SR &= I2C_STOP_Reset;
}
}
/**
* @brief Enables or disables the specified I2C acknowledge feature.
* @param I2Cx: select the I2C peripheral.
* This parameter can be I2C.
* @param NewState: new state of the I2C Acknowledgement.
* This parameter can be: ENABLE or DISABLE.
* @retval None.
*/
void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
if (NewState != DISABLE)
{
/* Enable the acknowledgement */
I2Cx->CR_SR |= I2C_ACK_Set;
}
else
{
/* Disable the acknowledgement */
I2Cx->CR_SR &= I2C_ACK_Reset;
}
}
/**
* @brief Sends a data byte through the I2Cx peripheral.
* @param I2Cx: select the I2C peripheral.
* This parameter can be I2C.
* @param Data: Byte to be transmitted.
* @retval None
*/
void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data)
{
/* Write in the DR register the data to be sent */
// I2Cx->CR_SR |= 0x04;
I2C_Unlock(I2Cx);
I2Cx->DR = Data;
I2C->CR_SR = 0x10;
}
/**
* @brief Returns the most recent received data by the I2Cx peripheral.
* @param I2Cx: select the I2C peripheral.
* This parameter can be I2C.
* @retval The value of the received data.
*/
void I2C_ReceiveData(I2C_TypeDef* I2Cx, FunctionalState ACK, FunctionalState STOP)
{
I2C_Unlock(I2Cx);
/* Return the data in the DR register */
I2Cx->CR_SR = 0x20 | ACK | STOP;
return ;
}
/**
* @brief Sends a Address byte through the I2Cx peripheral.
* @param I2Cx: select the I2C peripheral.
* This parameter can be I2C.
* @param Address: Address to be transmitted.
* @param I2C_Direction: set the direction of the I2Cx next byte transfer.
* This parameter can be I2C_Direction_Transmitter or I2C_Direction_Receiver.
* @retval None
*/
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction)
{
/* Test on the direction to set/reset the read/write bit */
// I2Cx->CR_SR |= 0x04;
I2C_Unlock(I2Cx);
if (I2C_Direction != I2C_Direction_Transmitter) //
{
/* Set the address bit0 for read */
Address |= I2C_ADD0_Set;
printf("\r\n receive addr 0x%02x\r\n", Address);
}
else
{
/* Reset the address bit0 for write */
Address &= I2C_ADD0_Reset;
printf("\r\n trans addr 0x%02x\r\n", Address);
}
I2Cx->DR = Address;
I2C->CR_SR = 0x90;
/* Send the address */
}
/**
* @brief Reads the specified I2C register and returns its value.
* @param I2Cx: select the I2C peripheral.
* This parameter can be I2C.
* @param I2C_Register: specifies the register to read.
* This parameter can be one of the following values:
* @arg I2C_Register_PRERL: PRERL register.
* @arg I2C_Register_PRERH: PRERH register.
* @arg I2C_Register_CTRL: CTR register.
* @arg I2C_Register_DR: DR register.
* @arg I2C_Register_SR: SR register.
* @arg I2C_Register_BLTOP: BLTOP register.
* @arg I2C_Register_SADDR: SADDR register.
* @retval The value of the read register.
*/
uint8_t I2C_ReadRegister(I2C_TypeDef* I2Cx, uint8_t I2C_Register)
{
__IO uint32_t tmp = 0;
tmp = (uint32_t) I2Cx;
tmp += I2C_Register;
/* Return the selected register value */
return (*(__IO uint8_t *) tmp);
}
/**
* @brief Clears the I2Cx's flags.
* @param I2Cx: select the I2C peripheral.
* This parameter can be I2C.
* @param I2C_FLAG: specifies the flag to clear.
* This parameter can be any combination of the following values:
* @arg I2C_FLAG_IT: SMBus Alert flag
* @retval None
*/
void I2C_ClearFlag(I2C_TypeDef* I2Cx, uint8_t I2C_FLAG)
{
uint8_t flagpos = 0;
/* Get the I2C flag position */
flagpos = I2C_FLAG & FLAG_Mask;
/* Clear the selected I2C flag */
I2Cx->CR_SR = (uint8_t)~flagpos;
}
/**
* @brief GET the I2C Status.
* @param I2Cx: select the I2C peripheral.
* This parameter can be I2C.
* @param I2C_IT: check the interrupt flag.
* This parameter can be I2C_STATE_IF.
* @retval The new state of I2C_IT (SET or RESET).
*/
ITStatus I2C_GetStatus(I2C_TypeDef* I2Cx, uint8_t I2C_STATUS)
{
ITStatus bitstatus = RESET;
/* Get bit[7:0] of the flag */
I2C_STATUS &= FLAG_Mask;
/* Check the status of the I2C interrupt flag */
if (((I2Cx->CR_SR & I2C_STATUS) != (uint8_t)RESET))
{
/* I2C_IT is set */
bitstatus = SET;
}
else
{
/* I2C_IT is reset */
bitstatus = RESET;
}
/* Return the I2C_IT status */
return bitstatus;
}
/**
*@brief Clears the I2C's interrupt pending bits.
* @param I2Cx: select the I2C peripheral.
* This parameter can be I2C.
*retval None
*/
void I2C_ClearIT(I2C_TypeDef* I2Cx)
{
I2Cx->CR_SR = 0x01;
SET_BIT(INT_CLR,IRQ_I2C);
}
/**
*@brief Wait for the Master's transmission is completed.
* @param I2Cx: select the I2C peripheral.
* This parameter can be I2C.
*retval None
*/
void I2C_wait(I2C_TypeDef* I2Cx)
{
uint8_t temp;
temp =I2Cx->CR_SR;
while (temp & 0x02) //等待传输完毕
{
temp =I2Cx->CR_SR;
}
}
/**
*@brief Wait for the bus until it is idle.
* @param I2Cx: select the I2C peripheral.
* This parameter can be I2C.
*retval None
*/
void I2C_BUSY(I2C_TypeDef* I2Cx)
{
uint8_t temp;
temp =I2Cx->CR_SR;
while (temp & 0x40) //等待总线空闲
{
temp =I2Cx->CR_SR;
}
}
/**
*@brief Check for buslock and recover it if so.
* @param I2Cx: select the I2C peripheral.
* This parameter can be I2C.
*retval None
*/
void I2C_Unlock(I2C_TypeDef* I2Cx)
{
uint8_t temp;
temp =I2Cx->CR_SR;
if (temp & 0x04) //等待空闲
{
I2Cx->CR_SR |= 0x04;
}
}
/**
*@brief Example of writing data to EEPROM via I2C bus with query mode.
* @param Waddr: The operating address.
* This parameter can be 0~127. 131072(16Kb/slice)/8(b/BYTE)/16(BYTE/page)=128page
* @param Tdata: The data to be written.
* This parameter can be uint8 format.
*retval None
*/
void CAT24_Write(uint16_t Waddr,uint8_t Tdata)
{
uint8_t Device_Addr;
Waddr = Waddr & 0x7FF;
Device_Addr=0xA0 + (Waddr>>7);
printf("\r\n Device_Addr=0x%2x , Tdata = 0x%2x",Device_Addr,Tdata);
I2C_Send7bitAddress(I2C, Device_Addr, I2C_Direction_Transmitter);
I2C_wait(I2C);
if(I2C->CR_SR & 0x80) {
printf("-----no ack-----\r\n");
}
Waddr = Waddr & 0xFF;
printf("Waddr=0x%x",Waddr);
I2C_SendData(I2C, Waddr);
I2C_wait(I2C);
if(I2C->CR_SR & 0x80) {
printf("-----no ack-----\r\n");
}
I2C_SendData(I2C, Tdata);
I2C_wait(I2C);
if(I2C->CR_SR & 0x80) {
printf("-----no ack-----\r\n");
}
I2C_GenerateSTOP(I2C,ENABLE);
I2C_wait(I2C);
}
/**
*@brief Example of writing data to EEPROM via I2C bus with query mode.
* @param Raddr: The operating address.
* This parameter can be 0~127. 131072(16Kb/slice)/8(b/BYTE)/16(BYTE/page)=128page
*retval The value of the read data.
*/
uint8_t CAT24_Read(uint16_t Raddr)
{
uint8_t tmp;
uint8_t Device_Addr;
Raddr = Raddr & 0x7FF;
Device_Addr=0xA0 + (Raddr>>7);
printf("\r\n read Device_Addr=0x%2x ",Device_Addr);
I2C_Send7bitAddress(I2C, Device_Addr, I2C_Direction_Transmitter);
I2C_wait(I2C);
if(I2C->CR_SR & 0x80) {
printf("\n no ack \n");
}
printf("Raddr=0x%x",Raddr);
Raddr = Raddr & 0xFF;
I2C_SendData(I2C, Raddr);
I2C_wait(I2C);
if(I2C->CR_SR & 0x80) {
printf("\n no ack \n");
}
I2C_Send7bitAddress(I2C, Device_Addr, I2C_Direction_Receiver);
I2C_wait(I2C);
if(I2C->CR_SR & 0x80) {
printf("\n no ack \n");
}
I2C_ReceiveData(I2C,I2C_NACK,I2C_STOP);
I2C_wait(I2C);
tmp=(uint8_t)I2C->DR;
return tmp;
}
/**
*@brief Example of writing data to EEPROM via I2C bus with interrupt mode.
* @param Waddr: The operating address.
* This parameter can be 0~127. 131072(16Kb/slice)/8(b/BYTE)/16(BYTE/page)=128page
* @param Tdata: The data to be written.
* This parameter can be uint8 format.
*retval None
*/
void CAT24_Write_Int(uint16_t Waddr,uint8_t Tdata)
{
uint8_t Device_Addr;
Waddr = Waddr & 0x7FF;
Device_Addr=0xA0 + (Waddr>>7);
I2C_BUSY(I2C);
STS=0;
I2C_Send7bitAddress(I2C, Device_Addr, I2C_Direction_Transmitter);
while(!STS)//等待从设备地址发送完毕
{
delay_us(1);
}
STS=0;
Waddr = Waddr & 0xFF;
I2C_SendData(I2C, Waddr);
while(!STS)//等待写入地址发送完毕
{
delay_us(1);
}
STS=0;
I2C_SendData(I2C, Tdata);
while(!STS)//等待数据发送完毕
{
delay_us(1);
}
STS=0;
I2C_GenerateSTOP(I2C,ENABLE);
I2C_wait(I2C);
}
/**
*@brief Example of writing data to EEPROM via I2C bus with interrupt mode.
* @param Raddr: The operating address.
* This parameter can be 0~127. 131072(16Kb/slice)/8(b/BYTE)/16(BYTE/page)=128page
*retval The value of the read data.
*/
uint8_t CAT24_Read_Int(uint16_t Raddr)
{
uint8_t tmp;
uint8_t Device_Addr;
STS=0;
I2C_BUSY(I2C);
STS=0;
Raddr = Raddr & 0x7FF;
Device_Addr=0xA0 + (Raddr>>7);
I2C_Send7bitAddress(I2C, Device_Addr, I2C_Direction_Transmitter);
while(!STS)//等待从设备地址发送完毕
{
delay_us(1);
}
STS=0;
Raddr = Raddr & 0xFF;
I2C_SendData(I2C, Raddr);
while(!STS)//等待读取地址发送完毕
{
delay_us(1);
}
STS=0;
I2C_Send7bitAddress(I2C, Device_Addr, I2C_Direction_Receiver);
while(!STS)//等待从设备地址发送完毕
{
delay_us(1);
}
STS=0;
I2C_ReceiveData(I2C,I2C_ACK_Set,I2C_STOP_Set);
while(!STS)//等待数据接收完毕
{
delay_us(1);
}
tmp=(uint8_t)I2C->DR;
return tmp;
}