一个灵活的软件I2C总线库函数,支持8/16位寄存器,支持一些非标准读写时序的I2C设备操作
原作者:https://schkorea.tistory.com/437 Forked from:https://github.com/liyanboy74/soft-i2c
- 7位设备地址,库内自动管理读写位
- 寄存器地址模式统一为枚举参数:
SI2C_NO_REG/SI2C_REG8/SI2C_REG16 - 支持从机时钟拉伸(SCL建议配置为开漏+上拉,并实现
SI2C_GET_SCL()宏) - 总线卡死自动恢复:事务前检测SDA卡低,自动执行9时钟脉冲+STOP恢复;也可手动调用
Si2c_Bus_Recover() - 返回值统一为
si2c_status_t:SI2C_OK为成功,负值为具体错误(参数/无应答/超时) len=0可用于设备探测或设定寄存器指针;len>0时pdata不可为NULL- 总线锁抽象:默认空锁(裸机最简),可选关中断强互斥或RTOS互斥锁
//引用头文件
//根据项目硬件具体情况,修改si2c_port.h内定义的宏
#include "si2c.h"
#include "si2c_port.h"
//应用层定义I2C句柄实例(支持多路总线,每路一个实例)
si2c_t si2c;
//初始化软件I2C接口(delay_us需为忙等实现,不得依赖中断/调度器)
void Bsp_Si2c_Init(void)
{
Si2c_Init(&si2c, Si2c_Port_Ioctl, Si2c_Port_Delay_Us, Si2c_Port_Lock);
}
// 初始化传感器
uint8_t Bsp_Opt4001_Init(void)
{
uint8_t chip_id[2] = {0};
uint8_t opt4001_config[2] = {0x32, 0xF0};
//复位全局I2C芯片
Si2c_General_Call_Reset(&si2c);
HAL_Delay(20);
//读取并检查芯片ID
if(Si2c_Read(&si2c, OPT4001_I2C_ADDR, OPT4001_DEVICE_ID_REG, chip_id, 2, SI2C_REG8) != SI2C_OK)
return OPT4001_ERROR_CHIPID;
if((chip_id[0] != 0x01) || (chip_id[1] != 0x21))
return OPT4001_ERROR_CHIPID;
//写入传感器配置
if(Si2c_Write(&si2c, OPT4001_I2C_ADDR, OPT4001_CONFIG_REG, opt4001_config, 2, SI2C_REG8) != SI2C_OK)
return OPT4001_ERROR_WRITE;
HAL_Delay(20);
return OPT4001_SUCCESS;
}- 将
si2c.c与si2c_port.c加入编译,include path 指向本目录 hal_delay_us必须为忙等实现(不得依赖中断/调度器,否则延时失效)- 总线锁在
si2c_port.c的Si2c_Port_Lock内三选一:默认空锁(裸机单上下文,最简单)/SI2C_LOCK_IRQ(关中断强互斥,ISR与主循环共用总线时)/SI2C_LOCK_RTOS(RTOS互斥锁) - 如需支持从机时钟拉伸,SCL 配置为开漏+上拉并实现
SI2C_GET_SCL()宏(未实现时等效直通)