直接看代码
需要注意的是,IIC的时序需要根据实际的设备配置
#define I2C_CLK_OUTPUT GPIO_PinModeSet(GPIO_SCL_PORT, GPIO_SCL_PIN, gpioModePushPull, 0)
#define I2C_DATA_OUTPUT GPIO_PinModeSet(GPIO_SDA_PORT, GPIO_SDA_PIN, gpioModePushPull, 0)
#define I2C_DATA_INPUT GPIO_PinModeSet(GPIO_SDA_PORT,GPIO_SDA_PIN, gpioModeInput, 0)
#define I2C_CLK_HIGH GPIO_PinOutSet(GPIO_SCL_PORT, GPIO_SCL_PIN)
#define I2C_CLK_LOW GPIO_PinOutClear(GPIO_SCL_PORT, GPIO_SCL_PIN)
#define I2C_DATA_HIGH GPIO_PinOutSet(GPIO_SDA_PORT, GPIO_SDA_PIN)
#define I2C_DATA_LOW GPIO_PinOutClear(GPIO_SDA_PORT, GPIO_SDA_PIN)
#define I2C_GET_BIT GPIO_PinInGet(GPIO_SDA_PORT, GPIO_SDA_PIN)
void SDA_Out(void)
{
GPIO_PinModeSet(GPIO_SDA_PORT, GPIO_SDA_PIN, gpioModePushPull, 0);
}
void SDA_In(void)
{
GPIO_PinModeSet(GPIO_SDA_PORT, GPIO_SDA_PIN, gpioModeInput, 1);
}
void SCL_Out(void)
{
GPIO_PinModeSet(GPIO_SCL_PORT, GPIO_SCL_PIN, gpioModePushPull, 0);
}
void SCL_In(void)
{
GPIO_PinModeSet(GPIO_SCL_PORT, GPIO_SCL_PIN, gpioModeInput, 1);
}
/******************************************
us delay for software I2C
uint:us
*******************************************/
void I2C_udelay(uint32_t delay)
{
/*
下方的延时函数是通过SysTick时钟实现的,不同的MCU、不同的主频需要不同的配置,此处不再细述方法;
由于函数内部还会进行us与tick的换算以及参数的出栈入栈等操作,
*/
delay_us(delay);
}
/******************************************
software I2C start bit
*******************************************/
void I2C_start(void)
{
SCL_Out();
SDA_Out();
I2C_DATA_HIGH;
I2C_CLK_HIGH;
I2C_udelay(3);
I2C_DATA_LOW;
I2C_udelay(3);
I2C_CLK_LOW;
I2C_udelay(3);
}
/******************************************
software I2C stop bit
*******************************************/
void I2C_stop(void)
{
SCL_Out();
SDA_Out();
I2C_DATA_LOW;
I2C_udelay(3);
I2C_CLK_HIGH;
I2C_udelay(3);
I2C_DATA_HIGH;
I2C_udelay(3);
}
/******************************************
software I2C one clock
*******************************************/
void I2C_one_clk(void)
{
I2C_udelay(2);
I2C_CLK_HIGH;
I2C_udelay(3);
I2C_CLK_LOW;
I2C_udelay(2);
}
/******************************************
software I2C read byte with ack
*******************************************/
uint8_t ReadByteAck(void)
{
int8_t i;
uint8_t data = 0;
I2C_CLK_LOW;
SDA_In();
I2C_udelay(3);
for (i=7; i>=0; i--)
{
I2C_CLK_HIGH;
I2C_udelay(3);
if (I2C_GET_BIT)
{
data |= (0x01<<i);
}
I2C_CLK_LOW;
I2C_udelay(3);
}
SDA_Out();
I2C_DATA_LOW;
I2C_one_clk();
return data;
}
/******************************************
software I2C read byte without ack
*******************************************/
uint8_t ReadByteNAck(void)
{
int8_t i = 0;
uint8_t data = 0;
I2C_CLK_LOW;
SDA_In();
I2C_udelay(3);
for (i=7; i>=0; i--)
{
I2C_CLK_HIGH;
I2C_udelay(3);
if (I2C_GET_BIT)
{
data |= (0x01<<i);
}
I2C_CLK_LOW;
I2C_udelay(3);
}
SDA_Out();
I2C_DATA_HIGH;
I2C_one_clk();
return data;
}
/******************************************
software I2C send byte
*******************************************/
void SendByte(uint8_t sData)
{
int8_t i;
for (i=7; i>=0; i--)
{
if ((sData>>i)&0x01)
{
I2C_DATA_HIGH;
}
else
{
I2C_DATA_LOW;
}
I2C_one_clk();
}
}
/******************************************
software I2C check ack bit
*******************************************/
bool ChkAck(void)
{
bool ack = false;
I2C_CLK_LOW;
SDA_In();
I2C_udelay(3);
I2C_CLK_HIGH;
I2C_udelay(3);
if( !(I2C_GET_BIT) ) ack = true;
I2C_CLK_LOW;
I2C_udelay(3);
SDA_Out();
return ack;
}
/******************************************
software I2C restart bit
*******************************************/
void Restart(void)
{
SCL_Out();
SDA_Out();
I2C_udelay(4);
I2C_DATA_HIGH;
I2C_udelay(4);
I2C_CLK_HIGH;
I2C_udelay(4);
I2C_DATA_LOW;
I2C_udelay(4);
I2C_CLK_LOW;
I2C_udelay(4);
}
void DelayMS(uint16_t delay)
{
uint16_t i=0;
for(i=0; i<delay; i++)
{
I2C_udelay(1000);
}
}
/******************************************
msa read bytes
*******************************************/
bool ReadBytes(uint8_t* Data, uint8_t RegAddr)
{
I2C_start(); //start bit
SendByte(I2C_addr << 1); //slave address|write bit
if(false == ChkAck()) //check Ack bit
{
I2C_stop();
return false;
}
SendByte(RegAddr); //send RegAddr
if(false == ChkAck()) //check Ack bit
{
I2C_stop();
return false;
}
Restart();
SendByte(I2C_addr<<1 | READ);
if(false == ChkAck())
{
I2C_stop();
return false;
}
*Data = ReadByteNAck();
I2C_stop(); //stop bit
return true;
}
bool WriteBytes(uint8_t RegAddr, uint8_t Data)
{
I2C_start(); //start bit
SendByte(I2C_addr<<1 | WRITE); //slave address|write bit
if(false == ChkAck()) //check Ack bit
{
I2C_stop();
return false;
}
SendByte(RegAddr); //send RegAddr
if(false == ChkAck()) //check Ack bit
{
I2C_stop();
return false;
}
SendByte(Data); //send parameter
if(false == ChkAck())
{
I2C_stop();
return false;
}
I2C_stop(); //stop bit
return true;
}
/*return value: 0: is ok other: is failed*/
int32_t I2C_read_byte_data( uint8_t addr, uint8_t *data)
{
int32_t ret = 0;
ret = ReadBytes(data,addr);
return (!ret);
}
/*return value: 0: is ok other: is failed*/
int32_t I2C_write_byte_data( uint8_t addr, uint8_t data)
{
int32_t ret = 0;
ret = WriteBytes(addr,data);
return (!ret);
}
/*return value: 0: is count other: is failed*/
int32_t I2C_read_block_data( uint8_t base_addr, uint8_t count, uint8_t *data)
{
int32_t i = 0;
for(i = 0; i < count;i++)
{
if(I2C_read_byte_data(base_addr+i,(data+i)))
{
return -1;
}
}
return count;
}
int32_t register_read( uint8_t addr, uint8_t *data)
{
int32_t res = 0;
res = I2C_read_byte_data(addr, data);
if(res != 0) {
return res;
}
return res;
}
int32_t register_write( uint8_t addr, uint8_t data)
{
int32_t res = 0;
res = I2C_write_byte_data(addr, data);
if(res != 0) {
return res;
}
return res;
}