这是一个通用的模拟I2C协议,理论上可以在任何具有GPIO接口的MCU上移植。原理是利用GPIO的输入和输出功能实现I2C的协议模拟。
把代码加进工程里
填写与机器和操作系统相关的宏定义及函数
以下为步骤的详细内容
把工程里SoftI2C下的五个文件包含进工程里
└─SoftI2C
i2c_platform.c
i2c_platform.h
i2c_sw.c
i2c_sw.h
typedef.h
移植的过程只需要根据自己的平台(特定的机器和操作系统)修改i2c_platform.c和i2c_platform.h两个文件。
首先是修改i2c_platform.h文件。通常情况下,只需要分别针对I/O模式,时钟线, 数据线这三处地方,添加宏定义的实现代码即可。
即如下代码处。
//i/o mode
#define SCL_MOD_OUT
#define SDA_MOD_OUT
#define SDA_MOD_IN
//clock
#define SCL //P01
#define SCL_H 1//P01 = 1
#define SCL_L 0//P01 = 0
//data
#define SDA 0 //P00
#define SDA_H 1//P00 = 1
#define SDA_H_IN //P00 = 1
#define SDA_L 0//P00 = 0
#define SDA_L_IN //P00 = 0
如下是针对STC15系列的51 CPU架构的MCU的示例代码
//i/o mode
#define SCL_MOD_OUT SETBITFIELD(P3M1, 5, 0); \
SETBITFIELD(P3M0, 5, 1)
#define SDA_MOD_OUT SETBITFIELD(P3M1, 4, 0); \
SETBITFIELD(P3M0, 4, 1)
#define SDA_MOD_IN SETBITFIELD(P3M1, 4, 0); \
SETBITFIELD(P3M0, 4, 0)
//clock
#define SCL P35//P01
#define SCL_H SCL = 1//P01 = 1
#define SCL_L SCL = 0//P01 = 0
//data
#define SDA P34 //P00
#define SDA_H SDA = 1//P00 = 1
#define SDA_H_IN SDA = 1//P00 = 1
#define SDA_L SDA = 0//P00 = 0
#define SDA_L_IN SDA = 0//P00 = 0
其实是修改i2c_platform.c, 这里有一个依赖于当前嵌入式系统(RTOS or Supper Loop)的函数I2CDelay( ),如下
void I2CDelay(uint8_t us)
{
//with us delay function of your flatform
/*
while(us--)
{
delay_us(1);
}
*/
}
如下是一个具体的实现示例
void I2CDelay(uint8_t us)
{
//with us delay function of your flatform
while(us--)
{
delay_us(5);
}
}
另一个就是依赖于当前嵌入式系统实现的延时函数ReadTsu( )
void ReadTsu(void)
{
//according to the actual situation, this time is generally not required, that is, set to 0.
/*
delay_us(time to set-up);
*/
}
如下是两个具体的实现示例
示例一
void ReadTsu(void)
{
//according to the actual situation, this time is generally not required, that is, set to 0.
//delay_ms(time to set-up);
return;
}
示例二
void ReadTsu(void)
{
//according to the actual situation, this time is generally not required, that is, set to 0.
//delay_ms(time to set-up);
delay_us(10);
}
以上就是移植需要做的所有工作了,正常情况下,已经可以使用该驱动了。
使用时,只需要在写的地方调用
WriteRegWithDataLen(uint8_t chip_addr, uint8_t* reg_addr, uint8_t addr_size, uint8_t* Data, uint8_t size)
而在需要读的地方调用
ReadRegWithDataLen(uint8_t chip_addr, uint8_t* reg_addr, uint8_t addr_size, uint8_t *pData, uint8_t size)
就可以了。
chip_addr,是芯片的I2C的带写bit的地址,比如一个芯片的地址是0x60,一般在规格书里描述如下
1100 000 w/r
则此处应该取0xC0,即0x60左移1bit得到的地址。
reg_addr,是芯片内部寄存器地址。
addr_size,是芯片内部寄存器地址的大小,按字节计算。
Data or pData, 是打算写进去或者读出来的数据。
size,是读或写的数据的长度。
如下,是一个简单的示例代码
int main(int argc, char *argv[])
{
unsigned char data[1] = {1};
WriteRegWithDataLen(0x96, NULL, 0, data, 1);
ReadRegWithDataLen(0x96, NULL, 0, data, 1);
system("PAUSE");
return 0;
}
I2C模块或者芯片在发送了读指令后,返回数据有个建立时间(Time for data set-up),这个时间在某些非标准的模块或者芯片里会有一个比较长的延时,需要加上这个延时函数,来完成正常通讯。
大多数没有带寄存器地址的读方式,是不发送Re-Start的,如果你的芯片或者模块需要这个状态时序,请写信给我,我会实现它。同样,大多数带寄存器地址的读方式,是有Re-Start的,如果你遇到不带这个状态的芯片或者模块,也请写信给我,我会实现它。
如果还有其他的疑问或者好的建议,请发送到zhengjianhua@cdtech.cn,我会尽量回复您。
SimulateI2C is released under the MIT license.
hengJH &
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。