STM32 I2C从机时序出错

硬件I2C从机通讯,偶尔发生错误:主机发起读操作,从机在向外吐数据,然后在某个SCL为高的时刻,SDA发生翻转。导致出现STOP信号,通讯出错。

初始化代码

    GPIO_InitTypeDef IICGPIO_InitStructure;

 

    NVIC_InitTypeDef NVIC_InitStructure;

    I2C_InitTypeDef I2C_InitStructure;

 

    RCC_APB2PeriphClockCmd(GPIO_CLK, ENABLE);

 

    IICGPIO_InitStructure.GPIO_Pin = SCL_GPIO_PIN | SDA_GPIO_PIN;

    IICGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;

    IICGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(SCL_GPIO_PORT, &IICGPIO_InitStructure); 

 

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); 

    I2C_DeInit(I2C2);

    //I2C2 configuration

    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

    I2C_InitStructure.I2C_OwnAddress1 = SMB_SLAVE_ADDR;

 

    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

    I2C_InitStructure.I2C_ClockSpeed = 100000;

    I2C_Init(I2C2, &I2C_InitStructure);


 

    NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

 

    NVIC_InitStructure.NVIC_IRQChannel = I2C2_ER_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure); 

    I2C_ITConfig(I2C2, I2C_IT_BUF | I2C_IT_EVT | I2C_IT_ERR, ENABLE);

    I2C_Cmd(I2C2, ENABLE);

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

在上述代码中,你已经完成了硬件I2C从机的初始化配置。然而,在处理偶尔出现的通讯错误时,你可能需要在初始化代码的基础上进行进一步的优化和调试。以下是一些建议来解决这个问题:

  1. 确认硬件连接:首先,请确保硬件连接没有问题。检查SDA和SCL线是否正确连接到从机设备。

  2. 降低时钟速率:尝试将I2C时钟速率降低,比如减少到50 kHz。降低时钟速率可以增加通讯的稳定性。

I2C_InitStructure.I2C_ClockSpeed = 50000; // 50 kHz
  1. 禁用ACK:尝试在初始化配置中禁用ACK(应答信号),这样从机将不会向主机发送应答信号,有时可以解决通讯错误问题。
I2C_InitStructure.I2C_Ack = I2C_Ack_Disable;
  1. 检查从机设备:确认从机设备是否正常工作,并且其响应主机请求的正确性。可以通过连接其他主机或使用逻辑分析仪等工具来检查从机设备的响应情况。

  2. 添加延时:在从机向外输出数据时,尝试在SCL高电平期间添加一个适当的延时,以确保SDA线的稳定性。

  3. 添加I2C中断处理函数:实现I2C2_EV_IRQHandler和I2C2_ER_IRQHandler中断处理函数,用于处理I2C事件和错误。在这些中断处理函数中,您可以进一步调试通讯错误并进行错误处理。

  4. 检查I2C总线的负载:确保I2C总线上连接的设备负载合理,避免超出I2C总线的驱动能力范围。

  5. 检查其他中断:如果在I2C通讯中使用了其他中断,例如DMA中断等,请确保它们的优先级设置正确,以避免干扰I2C中断的正常处理。

  6. 检查主机和从机之间的通讯协议:确认主机和从机之间的通讯协议是否正确,并符合硬件设备的规格要求。

请注意,解决硬件I2C通讯问题可能需要一定的调试和排查过程。建议逐步尝试上述建议,并在每次更改后仔细测试和验证通讯的稳定性和正确性。在必要时,你可以使用逻辑分析仪等工具来监测I2C信号的波形,以进一步帮助你定位问题所在。