560 lines
14 KiB
C
560 lines
14 KiB
C
//#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;
|
||
}
|
||
|