7 I2C相关¶
7.1 I2C正确的初始化方式¶
The use of I2C requires strict adherence to the following three steps for initialization and usage, otherwise there may be issues with I2C recovery after sleep wake-up;:
rt_i2c_bus_device_find /*The first step is to find the I2C device;*/
rt_device_open /*The second step is to open the I2C device;*/
rt_i2c_configure /*The third step is to configure the I2C device;*/
static struct rt_i2c_bus_device *i2c_bus = RT_NULL; /* I2C总线设备句柄 */
int sc7a20_i2c_init()
{
/*The first step is to find the I2C device;*/
i2c_bus = rt_i2c_bus_device_find("i2c4");
if (i2c_bus)
{
LOG_D("Find i2c bus device I2C4\n");
/*The second step is to open the I2C device;*/
rt_device_open((rt_device_t)i2c_bus, RT_DEVICE_FLAG_RDWR);
/* 或者采用rt_i2c_open函数,但是list_device时I2C不会显示open状态 */
//rt_i2c_open(i2c_bus, RT_DEVICE_FLAG_RDWR);
struct rt_i2c_configuration configuration =
{
.mode = 0,
.addr = 0,
.timeout = 500, //超时时间(ms)
.max_hz = 400000, //I2C速率(hz)
};
/*The third step is to configure the I2C device;*/
rt_i2c_configure(i2c_bus, &configuration);
}
else
{
LOG_E("Can not found i2c bus I2C4, init fail\n");
return -1;
}
return 0;
}
7.2 I2C4进入睡眠standby醒来后I2C通讯错误¶
Root cause: When operating the I2C device, only rt_i2c_bus_device_find was used to find the I2C4 device, without using rt_device_open on this device;,
Our software architecture, upon waking up from standby, checks if the I2C device is in the open state to decide whether to restore the I2C configuration. Since I2C4 was not opened, its configuration was not restored after waking up from standby, causing I2C4 to be unavailable;.
如下图:
解决方案:
添加如下open i2c4操作后,问题解决.
7.3 I2C概率性出错¶
1,The timeout time set by rt_i2c_configure is relatively short. Due to thread switching, the I2C thread may not be executed, easily leading to a timeout. It is recommended that 150ms is appropriate. Setting it too long will cause the system to get stuck in the I2C thread when an ERR occurs in I2C;,如下图1000为1秒:
2,The I2C rate and pull-up resistor do not match, causing the rising and falling edges of the I2C waveform to be too slow. For 400Kbps, a pull-up resistor of 1.5K-2.2K is recommended;。
3,When debugging I2C devices such as Touch chips with flying wires, excessively long buses can cause interference glitches in the I2C waveform, leading to incorrect recognition of the I2C waveform;。
4,In some cases where I2C devices encounter an Error, SDA might be pulled low by the I2C peripheral and held there. When SDA is pulled low, the I2C controller detects that the bus is busy and cannot send out waveforms, and the log will print ERR;,At this time, the peripheral can be reset. Common reset methods include;:
A,Switching the peripheral power supply or reset pin;。
B,Send an I2C bus reset (9 empty clocks) to reset the peripheral I2C bus (in the SDK, when an I2C ERR occurs, operations to reset the I2C controller and send 9 empty clocks have already been performed at the HAL layer);。
7.4 当I2C设备地址为0x12时I2C波形无法发出¶
After SDA is pulled low, the I2C controller can no longer send out waveforms;,如下图:
根本原因:
SF32LB55x芯片支持i2c slave模式,
而这个slave模式的地址正好在驱动中被配置成了0x12,导致识别到0x12,芯片进入了i2c slave模式
驱动如下:
解决方案1:
Lcpu这部分代码是在ROM里面,直接修改会不起效,从rom.sym删除lcpu中rom内函数:HAL_I2C_Init
并修改此处地址。
解决方案2:
在I2C4设备初始化完成后,直接重新配置该寄存器:
#define _WWORD(reg,value) \
{ \
volatile uint32_t * p_reg=(uint32_t *) reg; \
*p_reg=value; \
}
_WWORD(0x4004c014, 0x01); //i2c slave_addr 0x01