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

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

[复制链接]
STMCU小助手 发布时间:2022-2-14 23:46
前言* M0 Z; e7 e# i3 V) {
本篇文章主要是对 STM8Lxxxx 在 I2C 通信调试中遇到的第一次通信正常,但第二次通信失败问题的分析和处理。% W5 }! b4 q3 [0 r
" D; r0 E# {. X
1. I2C 协议总体分析。
% E. X( ]. v! s) P/ F2 I4 P   STM8Lxxx I2C 硬件逻辑使用时非常灵活,因此也造成对各个状态处理的复杂性,稍不注意,I2C 调试就不能通过。3 j; p+ j6 W; [. R7 N% ~5 L* k+ F
   下面是 I2C 开始(START)和结束(STOP)波形,STM8Lxxx 也是遵守这个协议的。9 I5 u/ _8 k  j* g9 F5 `( w! f
   SCL 信号由主控提供。  B  m, b6 q( i2 x9 C
   STM8Lxxx 总线端口为开漏输出,外部需要上拉电阻。8 {; N* @/ D5 N' c3 u4 H8 V4 K; [# |: @
   下面协议为简单的单主控单从机收发协议。- T% X, s. x* S! U  g1 J) m' u6 ?
XIN`NCJHC7P_DHP]ZGA6V.png   ]2 D( I: u* z! \) O9 W; [

: p% g  ~+ ]  D/ v2 v2. 下面对一个简单的单主机发送,单从机接收协议进行说明
! ?! u- W7 h9 H5 o) G# C- k
2 R$ v4 ^: {, g5 O下面为主发送的一个协议图:7 T$ l: T0 T4 u" v# Q
主控给从机发送数据,等到从机应答信号后再发送下 byte 数据,直到数据发送完成后,主机发送一个 stop 信号释放总线。
3 _8 L6 x1 K  ]+ N" H9 d; n+ N; j) `. n  b6 V/ _" R- e4 m8 T1 A: d# O
2D43FXAOKO(%YOF`XTM0E)B.png
0 v5 q8 j  Z, I$ ]8 m9 l3 y6 o4 H3 z" v! [' G1 w
下面是从机接收协议图,从机接收主机发过来的数据并存储,每 byte 传输完成后发送一个应答信号给主机(从机在每 byte 传输完的第九个 Clock 把 SDA 信号线拉低到低电平)。
+ j+ Z/ l& B" H6 R9 s2 y# @3 {- p. w( W$ z
XKNMVV]}43A3KB(]~~({FB2.png ! d1 q7 I: [7 p2 O- T8 p6 L) ~
  p; S/ L6 S/ I/ `6 l1 |
3. 程序中的出错现象4 y8 b0 p8 v' s$ f3 v: A4 [' l
客户的程序调时发现相同的数据连续从主控发给从机,只有第一次的通信波形是好的,第二次通信时设备地址可正常发送,从机也有应答,但当第一 byte 数据发送完成后,主机收不到从机的应答信号。
. J1 |: Z# n- e6 g8 n9 \5 r$ W7 `! Y" F. H: r
4. 问题产生原因
) M- _" ~% Z0 ?6 H; k  r0 J' F1 q客户使用的是 E:\Download\STM8L\STSW-STM8016\STM8L15x-16x-05x-AL31-4 R! _" i1 J" U
L_StdPeriph_Lib\Project\STM8L15x_StdPeriph_Examples\I2C\I2C_TwoBoards\I2C_DataExchange 中的程序。
) k+ u3 @( F, h
  1. /**7 G9 Z8 k+ K& a* D
  2. 1 M6 h# B$ G, E2 x2 Z( z
  3. * @brief I2C1 / SPI2 Interrupt routine.& M, \: W7 F5 G7 c$ v
  4. * @param None
    5 L: U; m5 `- b% |
  5. * @retval None
    % k! o/ b2 N" b! z% W
  6.   */
    , e# w( K% V6 C  f9 z, Z1 H5 s: e
  7.   INTERRUPT_HANDLER(I2C1_SPI2_IRQHandler, 29)
    ( x( b; x( N; I. l
  8.   {
    5 l8 m. H& _$ V( [& @
  9.   /* Read SR2 register to get I2C error */7 d$ c; K  W5 `) _
  10.   if (I2C_ReadRegister(I2C1, I2C_Register_SR2))4 L, v- s4 H& o6 u
  11.   {  p" b9 z+ X  e4 D, v! k
  12.   /* Clears SR2 register */  f* }) }# h0 q! ~, m" R+ I4 ^! ~6 y
  13.   I2C1->SR2 = 0;% d; e6 n& h, N$ f  @" d5 U: ]- N
  14.   /* Set LED2 */
    # x7 J' Q" p+ }# {
  15.   STM_EVAL_LEDOn(LED2);
    5 E$ L9 e4 r5 _1 W; n1 k
  16.   }8 a& S0 n/ a9 N  v
  17.   Event = I2C_GetLastEvent(I2C1);& K4 c7 ]2 m/ T2 ~
  18.   switch (Event)
    7 M; Z9 v! @7 z. a. q. b
  19.   {
    ) _, L- u4 ?: U% M' \' I
  20.   /******* Slave transmitter ******/
    3 l* r# k  D9 j. {# y7 g8 u9 P0 S
  21.   /* check on EV1 */
    4 N* n2 o' _! R
  22.   case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:
    " }! R8 o; U; S6 y
  23.   Tx_Idx = 0;
    6 C8 A* l( O7 h% @
  24.   break;
    0 M" h) t  c7 o: u3 p; X
  25.   /* check on EV3 */( L. |: T$ }- ~/ f# W6 r
  26.   case I2C_EVENT_SLAVE_BYTE_TRANSMITTING:( N4 l2 i6 Y; U) r/ p
  27.   /* Transmit data */8 j5 Z' z  y4 t; I' i! b5 P/ {6 }' r
  28.   I2C_SendData(I2C1, Slave_Buffer_Rx[Tx_Idx++]);$ C* H/ V: Q2 F" m) P% H
  29.   break;
    : n; @* F' Q* z# W7 s! w; h- Q
  30.   /******* Slave receiver **********/9 y  W* o5 O5 }% w, `  _
  31.   /* check on EV1*/8 y3 U8 B6 l6 y: l- W7 W) b
  32.   case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:% M- B) ~5 z3 z
  33.   break;$ K& f8 J' b8 P" V' I5 C
  34.   /* Check on EV2*/+ r7 `* j/ l, w5 T, X$ D+ j
  35.   case I2C_EVENT_SLAVE_BYTE_RECEIVED:
    ! I( j" j$ c! Z) {
  36.   Slave_Buffer_Rx[Rx_Idx++] = I2C_ReceiveData(I2C1);' s0 w" u* g3 }4 B$ c6 f+ n" `  I
  37.   break;# L# b0 H4 r1 R/ r0 l3 q
  38.   /* Check on EV4 */
      w+ n) P: I2 @0 q
  39.   case (I2C_EVENT_SLAVE_STOP_DETECTED):
    1 N/ U& n9 ~; z  I3 p% j
  40.   /* write to CR2 to clear STOPF flag */( U$ d: M2 T, b1 Z$ h, y# s" |
  41.   I2C1->CR2 |= I2C_CR2_ACK;
    ! ]) l3 B" Q, G$ p' O4 b/ w' t
  42.   break;
    3 I; f' O4 F6 M  C( J
  43.   default:
    : w5 ~( X1 @0 c3 R( S6 U
  44.   break;
    ( J; z' f- \1 N/ t% T( Q+ l
  45.   }5 G. m% k% n! v: D  ]7 S
  46.   }
复制代码
; S( i4 i' h, ^( B
  客户在程序编写时看到下图中用橙色标出的文字,就错误理解成从机每次收到 I2C 的 STOP 信号后,从机都要给 I2C_CR2 的STOP 置位来释放 SCL 和 SDA 信号线。( W( U* K0 H3 C3 @0 L

2 E4 n( u" W# j/ P, D- @ E04GTO~GKN_@95G%1@TM$_B.png
3 ]; P! f- w$ `1 Y
% {1 @3 S" c' h* d & E" F8 j. ?4 w, i  t+ M* \5 {

) q) A. [& |9 ?8 a. J  客户对 I2C 中断处理程序进行了修改,对应的代码如下,黄色部分标出了客户修改的代码:; e6 z0 \* v7 z$ w$ F; |
  1. case (I2C_EVENT_SLAVE_STOP_DETECTED):
    " M: g* _7 m, ^+ B2 I3 ?
  2. /* write to CR2 to clear STOPF flag */
    : S% r) ^& d1 C! r$ i  i8 t
  3. //I2C1->CR2 |= I2C_CR2_ACK;$ Y4 `" t# h$ t3 A- E
  4. I2C1->CR2 |= (I2C_CR2_ACK + I2C_CR2_STOP);
    " F  A7 M1 H$ e& X" ]7 Q: y$ m# P0 k0 s
复制代码
0 v  I# w' ?# a/ R8 `
  跟踪程序发现 I2C 主机在发送第二次数据时,从第一个 byte 数据传输完成时信号波形开始不正常,从机一直没有 ACK 发出来。9 _8 C) e9 K& I* V) B
  SCL 线一直保持在低电平。
/ S, l* I" k6 s$ E4 O  Z. e  跟踪从机程序,发现第二次传输时 ADDR 中断能正常进入,从机也有应答,但之后 RXNE 位一直不会被置位,被置位的是I2C_SR1 的 bit7, TXE 位一直为“1”,而中断处理中并没对这一状态进行处理和清空,所以一直会不断进入中断处理程序,不做处理又跳出中断,程序通信就死在了这里。( l! Y' d3 }7 ]$ q' p, ~4 Z& n$ z, \, V
( A8 j" A9 w* _2 b. c; _2 i
~DN07}I~B2H)XG$ETEBSA8J.png
# [2 K( A* \7 j$ h0 ~+ e, x
/ P) J; b5 A. b; w$ t把程序恢复成示例程序,通信正常。
0 G- v8 B* C$ e" G1 o( M5 S7 s
) ]( d" d5 `0 d" Q4 s! R
( p7 Z$ y% ^; N8 N6 ?, [( Q1 F/ V5.代码设计中应注意的地方。7 R, @$ P: g$ D
建议客户在修改示例代码时谨慎一些,特别要注意重要寄存器的操作;弄明白后再进行更改;如果需要测试,最好标注清楚,
; j' M, o( N5 L" Q不要测试完成后又忘了修改回来。( [" Y8 I! G8 w% ~# Z7 p' ^  D

3 F0 h4 _/ f# W3 O& Y
赞 收藏 评论0 发布时间:2022-2-14 23:46

举报

0个回答

所属标签

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版