你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM8Lxxx I2C 程序第二次数据通信失败的问题分析

[复制链接]
STMCU小助手 发布时间:2022-2-14 23:46
前言
本篇文章主要是对 STM8Lxxxx 在 I2C 通信调试中遇到的第一次通信正常,但第二次通信失败问题的分析和处理。

1. I2C 协议总体分析。
   STM8Lxxx I2C 硬件逻辑使用时非常灵活,因此也造成对各个状态处理的复杂性,稍不注意,I2C 调试就不能通过。
   下面是 I2C 开始(START)和结束(STOP)波形,STM8Lxxx 也是遵守这个协议的。
   SCL 信号由主控提供。
   STM8Lxxx 总线端口为开漏输出,外部需要上拉电阻。
   下面协议为简单的单主控单从机收发协议。
XIN`NCJHC7P_DHP]ZGA6V.png

2. 下面对一个简单的单主机发送,单从机接收协议进行说明

下面为主发送的一个协议图:
主控给从机发送数据,等到从机应答信号后再发送下 byte 数据,直到数据发送完成后,主机发送一个 stop 信号释放总线。

2D43FXAOKO(%YOF`XTM0E)B.png

下面是从机接收协议图,从机接收主机发过来的数据并存储,每 byte 传输完成后发送一个应答信号给主机(从机在每 byte 传输完的第九个 Clock 把 SDA 信号线拉低到低电平)。

XKNMVV]}43A3KB(]~~({FB2.png

3. 程序中的出错现象
客户的程序调时发现相同的数据连续从主控发给从机,只有第一次的通信波形是好的,第二次通信时设备地址可正常发送,从机也有应答,但当第一 byte 数据发送完成后,主机收不到从机的应答信号。

4. 问题产生原因
客户使用的是 E:\Download\STM8L\STSW-STM8016\STM8L15x-16x-05x-AL31-
L_StdPeriph_Lib\Project\STM8L15x_StdPeriph_Examples\I2C\I2C_TwoBoards\I2C_DataExchange 中的程序。
  1. /**

  2. * @brief I2C1 / SPI2 Interrupt routine.
  3. * @param None
  4. * @retval None
  5.   */
  6.   INTERRUPT_HANDLER(I2C1_SPI2_IRQHandler, 29)
  7.   {
  8.   /* Read SR2 register to get I2C error */
  9.   if (I2C_ReadRegister(I2C1, I2C_Register_SR2))
  10.   {
  11.   /* Clears SR2 register */
  12.   I2C1->SR2 = 0;
  13.   /* Set LED2 */
  14.   STM_EVAL_LEDOn(LED2);
  15.   }
  16.   Event = I2C_GetLastEvent(I2C1);
  17.   switch (Event)
  18.   {
  19.   /******* Slave transmitter ******/
  20.   /* check on EV1 */
  21.   case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:
  22.   Tx_Idx = 0;
  23.   break;
  24.   /* check on EV3 */
  25.   case I2C_EVENT_SLAVE_BYTE_TRANSMITTING:
  26.   /* Transmit data */
  27.   I2C_SendData(I2C1, Slave_Buffer_Rx[Tx_Idx++]);
  28.   break;
  29.   /******* Slave receiver **********/
  30.   /* check on EV1*/
  31.   case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
  32.   break;
  33.   /* Check on EV2*/
  34.   case I2C_EVENT_SLAVE_BYTE_RECEIVED:
  35.   Slave_Buffer_Rx[Rx_Idx++] = I2C_ReceiveData(I2C1);
  36.   break;
  37.   /* Check on EV4 */
  38.   case (I2C_EVENT_SLAVE_STOP_DETECTED):
  39.   /* write to CR2 to clear STOPF flag */
  40.   I2C1->CR2 |= I2C_CR2_ACK;
  41.   break;
  42.   default:
  43.   break;
  44.   }
  45.   }
复制代码

  客户在程序编写时看到下图中用橙色标出的文字,就错误理解成从机每次收到 I2C 的 STOP 信号后,从机都要给 I2C_CR2 的STOP 置位来释放 SCL 和 SDA 信号线。

E04GTO~GKN_@95G%1@TM$_B.png



  客户对 I2C 中断处理程序进行了修改,对应的代码如下,黄色部分标出了客户修改的代码:
  1. case (I2C_EVENT_SLAVE_STOP_DETECTED):
  2. /* write to CR2 to clear STOPF flag */
  3. //I2C1->CR2 |= I2C_CR2_ACK;
  4. I2C1->CR2 |= (I2C_CR2_ACK + I2C_CR2_STOP);
复制代码

  跟踪程序发现 I2C 主机在发送第二次数据时,从第一个 byte 数据传输完成时信号波形开始不正常,从机一直没有 ACK 发出来。
  SCL 线一直保持在低电平。
  跟踪从机程序,发现第二次传输时 ADDR 中断能正常进入,从机也有应答,但之后 RXNE 位一直不会被置位,被置位的是I2C_SR1 的 bit7, TXE 位一直为“1”,而中断处理中并没对这一状态进行处理和清空,所以一直会不断进入中断处理程序,不做处理又跳出中断,程序通信就死在了这里。

~DN07}I~B2H)XG$ETEBSA8J.png

把程序恢复成示例程序,通信正常。


5.代码设计中应注意的地方。
建议客户在修改示例代码时谨慎一些,特别要注意重要寄存器的操作;弄明白后再进行更改;如果需要测试,最好标注清楚,
不要测试完成后又忘了修改回来。

收藏 评论0 发布时间:2022-2-14 23:46

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版