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

STM8S I2C总线中断程序

[复制链接]
磊元lystudio 发布时间:2015-10-2 01:49
阅读主题, 点击返回1楼
赞 收藏 1 评论23 发布时间:2015-10-2 01:49
23个回答
磊元lystudio 回答时间:2015-10-2 01:56:07

  w* H  \/ |& R* _- j4 c; ~
! A! D$ c: `3 Q7 m# y2 _/*==========================================================================================================
  Y4 Y3 Z9 g7 D# V- n* V' G6 s函数功能:    本函数是I2C总线通信接收和发送作业不间断循环调用运行函数。& e1 F; _4 ]% O4 D9 q2 e
备注:        ▲.注意:本函数为消息任务队列函数,要在主函数中不间断循环调用运行。
6 k+ Z2 r* @. B- a9 H" b6 m              ▲.当I2C总线工作于从机方式时,I2C总线中断总是处于使能状态,以便
( P9 _) Y# Z+ N                  I2C总线处于随时接收数据状态。. A4 m3 x, T, K9 x
==========================================================================================================*/
+ a0 |6 g& L& X6 }void  CommI2cCircleFunc (void)
2 j+ h4 @  O, a( `{
- u( z0 [4 U' E! p# c$ j#ifdef DEBUG
1 g+ E/ s, N$ b4 n. x. M  unsigned char i;                           // 循环计数器变量
$ B0 Q9 u$ R. X( t! ^9 d( y  unsigned char j;9 D; t2 ~+ E9 D1 H, f& P4 q
  unsigned char hex_data[2];* g' V' E" B0 R$ H9 p
  unsigned char *ptr;; b( Z1 M0 o8 _3 R4 K
#endif
9 k' O3 F$ r- y- `) C1 G8 Q2 n  unsigned char              i;                           // 循环计数器变量
. P7 n( ^6 S, Y7 B. M  CommI2cDataStru           *pI2c;                        // 指向I2C总线通讯收发数据处理变量的指针
+ C& z; Z! \; h9 I) D! d7 Z$ @$ k0 G; e
  pI2c                      = &gstvI2c;                   // 取I2C总线通讯收发数据处理变量的首个地址
/ P8 k6 W$ r+ z2 `$ R- _; [% i#ifdef PreCommI2cUseSingleMasterMode                      // “I2C总线工作于单主机方式”的条件编译
) }' X# Q; r1 C" s& {  if (   (gbitI2c.Error == SET)                           // 如果I2C总线通讯收发作业发生错误,* r* c7 u: R1 v5 r9 j8 O, f7 d
      && ( ! CommI2cBusBusy( )) )                         // 且I2C总线收发器处于空闲状态?8 l1 i4 T! }) ]2 S, ?) J
  {8 F% u/ Q' g% f5 l
    if (pI2c->Cycle > cI2cErrorMax)                       // 检查重新启动收发作业错误次数是否大于最大值?2 c' y' R% ?) J
    {
2 r% B& H7 p$ A      pI2c->Cycle           =  0x00;                      // I2C总线的重新启动收发作业发生错误次数清0. ~) |8 \, {. c. s
      gbitI2c.Error         =  CLEAR;                     // 清除“通讯收发作业发生错误”标志
. |$ V5 O" Y- g+ p7 o      gbitI2c.Busy          =  CLEAR;                     // 清除“I2C总线〖忙〗”标志( X# N6 Z: `& }& U3 L
#ifdef _SYSTEM_ERROR_MANAGE_H_
& V7 L* ]- H1 e' n* B      sys_error_type       |=  SYS_ERROR_TYPE_IS_GENERAL; // 置【普通】错误类型消息任务标志位/ d  j$ p& Z. u6 F
      sys_error_value       =  SYS_ERROR_COMM_I2CBUS    ; // 置“I2C总线通信收发作业”错误代码值
1 ]; c+ u9 u( K# O#endif1 F0 e/ N/ t2 M8 s  v2 f
    }3 W' `( O+ x: _
    else
/ [& \$ {8 t2 Z) O! B+ o) Y& C    {
$ B, f5 r9 _0 n; E* s9 ~      pI2c->Cycle++;                                      // I2C的重新启动收发作业发生错误次数值+1
  u- i3 u+ e9 n/ }& W      gbitI2c.Error         =  CLEAR;                     // 清除“通讯收发作业发生错误”标志* C% I# T6 D$ S/ y
      CommI2cBusAgain( );                                 // 重新启动I2C总线前一个通讯收发作业操作1 a, l$ k! R1 ]6 Q( ?  K( t  C
    }; T! p& G/ W/ P  Y( b
  }
  g% h! \) M3 M, A  // 通讯任务时间超时计时处理,用以处理I2C总线直处于“BUSY”状态。( \3 m$ p: U. h( x5 K) T' V
  if (gbitI2c.OverS == SET)
. B7 U& s& j3 E8 G9 K" ~- |  {/ N5 M, y8 l  i0 |6 l
    if (RtcSecByteOverflow(pI2c->OverS))                  // 如果通讯任务时间计时秒表时间已溢出?- i$ D; B( V) G! p: e& T
    {7 K/ O% j6 F, v5 M7 y# e
      I2CCR2      = (u8)( ((0<<i2cSTART)|                 // 禁止 START 信号(起始条件)
, H% O' O1 s. @                           (0<<i2cSTOP )|(0<<i2cACKEN)|   // 禁止 STOP 信号(停止条件),使能 ACK 应答' s, ^/ j8 W$ a3 S' M
                           (0<<i2cPOS  )|(1<<i2cRST  ) ));// 应答的位置=当前字节,复位I2C模块! g( m3 P) k5 z; I9 j
      CLKPECR1   &= (u8)(~((1<<clkI2C  )));               // 禁止I2C外设时钟( ~) s; R& _4 V, ?* ?( t
      I2CCR1      = (u8)( ((0<<i2cEN   )|(0<<i2cGCEN )|   // 禁止I2C模块,禁止广播呼叫& ?3 J# V2 C; T" `- I
                           (0<<i2cCKTEN) ));              // 禁止时钟延展/ p* @! |: W6 }, u8 d
      MFH_PIN_CFG_OUTH_I2cScl;                            // 设置I2C时钟引脚为推挽输出,并为H电平(释放 SCL)1 q& q( i6 j; s
      MFH_PIN_CFG_OUTH_I2cSda;                            // 设置I2C数据引脚为推挽输出,并为H电平(释放 SDA)& f, e7 g' M1 c3 ~, X$ U1 M
      for (i=0; i<9; i++)                                 // 发送 9 个 SCL 时钟脉冲;在此过程中,SDA 为高电平,以复位从设备' u+ j6 _8 Q, Z6 C# n5 z0 l0 a
      {4 v* C/ l3 h3 U5 p
        DelayUs(1);
) a, Y; J( j: ?& G2 v5 [        MFH_PIN_OUT_CLRL_I2cScl;
6 r9 J0 j1 E# ]8 S' w        DelayUs(1);
5 g7 S1 t3 ]5 W) f: W5 E& u        MFH_PIN_OUT_SETH_I2cScl;, x' R7 S& O: Q8 m$ E4 [0 ], m' s' H
      }5 C* r) L- ~( |; _) x& v; e
      CLKPECR1   |= (u8)( ((1<<clkI2C  )));               // 使能I2C外设时钟, f+ V) I9 R) u; ]" j" w& r- r0 v
      CommI2cInit( );                                     // 重新初始化I2C总线" }% W8 m' v( f
    }! F- @: [. A9 ~: U( n- W: \7 p
  }
7 x2 }3 g1 E6 a# k#endif                                                    // “PreCommI2cUseSingleMasterMode”; o, m! x( s) C2 [* U6 X
& _5 ?6 z3 ^7 z1 l; O
}
6 @3 R, H0 p( b* `" ?8 I
2 G9 r/ J, E6 l' f3 l. g# E
3 C% }# q6 L- {1 ]8 ]
2 w& p5 w) S+ J; X& B  a9 i5 ]9 r, n0 E. O# b. K! a" L% j

" n! S& a; ?' v) C6 [#ifdef __cplusplus
5 G# d: d* Z$ X: E  {3 ~1 h}                                                         // extern "C" 链接指示符作用域结束# x2 R3 @9 C' e" c7 P
#endif
; ~9 n' P/ f% _6 |6 s7 J3 l# K: a9 @4 l7 w
; x! }% V8 U" y, H3 `3 t5 ^
/*( P( I6 v- q5 w6 g9 ]
************************************************************************************************************
" p8 [( Z! S4 b/ e. t( b3 a                     本C语言源程序文件到此结束
. l! H( B# \- M/ Q( V. o************************************************************************************************************
* Z' M4 [/ e! _, z*/" i4 ^$ e" K* n3 N$ I, P% k

) a1 [4 C9 A! v% Z1 a
3 ~7 R6 U. L9 u# }+ j* ^6 O
磊元lystudio 回答时间:2015-10-2 01:56:49
/*------------------------------------------------------------------------------------------------
1 P; D! w( ~2 E( C! y         两线串行总线接口(I2C)
& w+ x7 f; P" Y' l, ^' H7 t! `------------------------------------------------------------------------------------------------*/
0 C: K4 l/ N: ]) t( t// I2CCR1(I2C_CR1)——— I2C控制寄存器1" n& q" ~3 n% U/ ~% Y$ v
#define i2cEN                 0                           // I2C启动/停止使能位+ Z& t" l- y- e3 Y* H6 D
#define i2cGCEN               6                           // 广播呼叫使能位
( ~+ \! S4 K6 X& m7 q#define i2cCKTEN              7                           // 时钟延展禁止位
7 T' Z$ J! U4 K2 x* [, y/ C3 F& T7 i; O4 Z3 r/ U* {
// I2CCR2(I2C_CR2)——— I2C控制寄存器2) i- b- u( }, T# [
#define i2cSTART              0                           // 起始位状态  B; [1 V& _: M1 n
#define i2cSTOP               1                           // 结束位状态
+ |* H6 }) ?7 o& a2 I#define i2cACKEN              2                           // 应答使能位
& t& _- Y9 Y1 p3 I' `" f#define i2cPOS                3                           // 应答的位置- f9 R, ?( ~6 n5 Z
#define i2cRST                7                           // 软件复位
9 G8 d2 F0 b) c$ x- T( J) B0 x- D" @" V. s
// I2CARL(I2C_OARL)——— I2C(从机)地址低位寄存器+ j: w( E. A2 P! ^/ h
#define i2cADD0               0                           // I2C从机地址位0
1 S, \6 h- k/ h: R0 E  J#define i2cADD1               1                           // I2C从机地址位14 o4 \+ L8 O! h! U
#define i2cADD2               2                           // I2C从机地址位2, E8 f7 U& f- ~; _
#define i2cADD3               3                           // I2C从机地址位3
8 O1 p$ U0 M+ W$ x#define i2cADD4               4                           // I2C从机地址位4
0 B/ Q9 o- y( o7 C" |2 l#define i2cADD5               5                           // I2C从机地址位5/ V, U' e( `; k  R6 }: V, B& t
#define i2cADD6               6                           // I2C从机地址位6$ `% \% x. Q$ t4 ^" U/ w' v) j! Q
#define i2cADD7               7                           // I2C从机地址位7# e( M5 Z( ?" A* k9 D* n, E4 S
#define i2cADD17              1                           // I2C从机地址位1~7
7 _- P+ _$ W8 c5 @  L9 k- V: x5 X  ]0 x) a/ k
// I2CARH(I2C_OARH)——— I2C(从机)地址高位寄存器
. ?1 Z, [: i: v  ~9 K#define i2cADD8               1                           // I2C从机地址位8
/ z( w/ D- K1 d#define i2cADD9               2                           // I2C从机地址位9& X3 V. k0 g/ H! T
#define i2cCFG                6                           // 地址模式配置
# ^! @$ ?- K+ F# L1 h( P#define i2cMODE               7                           // 寻址模式
: N/ C  O+ T  y/ n- R( g6 t#define i2cADD89              1                           // I2C从机地址位8~94 W- {* n5 G" b
! k7 T6 A) Z5 K; m3 e: m1 Q
// I2CSR1(I2C_SR1)——— I2C状态寄存器19 Y1 p- [& H: L  a6 A: k( P3 a. T
#define i2cSTAF               0                           // 起始位(主模式)
- w' o) T/ l/ C: I+ ^+ V#define i2cADDTR              1                           // 地址已被发送(主模式)/地址匹配(从模式). \/ }7 {+ g5 o2 \8 l" j) J, |
#define i2cTXC                2                           // 字节发送结束
6 O( t: b# `$ ?! s; j7 `#define i2cADD10              3                           // 10位头序列已发送(主模式)2 N) y7 B$ B  B# q
#define i2cSTODF              4                           // 停止条件检测位(从模式)# n! `2 P* f2 k  A/ {! T4 R9 g
#define i2cRXNE               6                           // 接收数据寄存器非空
) b' l6 N, ~3 k% ~) _0 p$ D#define i2cDRE                7                           // 发送数据寄存器空3 o- R9 P) w) ^4 f. m" H

4 Y# X8 n, d. A9 Z// I2CSR2(I2C_SR2)——— I2C状态寄存器2
. z/ ~+ p' a. v#define i2cBERR               0                           // 总线错误+ x, E+ N! V7 c; Y4 }8 |
#define i2cARLO               1                           // 仲裁失败(主模式)) g( p* q1 m2 u  g2 R, e. E
#define i2cACKF               2                           // 应答失败$ _) @  ?  q2 }8 E& k# v
#define i2cOVF                3                           // 溢出标志位
$ ]3 d1 {7 L6 ~* S4 N9 o#define i2cWUF                5                           // 从停机(Halt)模式唤醒标志
% i+ |2 v# U! V: N
+ c% R& j8 G2 R// I2CSR3(I2C_SR3)——— I2C状态寄存器37 s0 Z7 g+ U( G
#define i2cMSF                0                           // 主/从机模式标志位
0 Q. Y  a& L& X. J1 {! L! O# C; k. A#define i2cBSY                1                           // 总线忙标志- I+ V5 w& u7 U+ K2 T. B
#define i2cRXTX               2                           // 接收器/发送器,0:接收,1:发送4 Z* @/ a5 Q6 M' U( }
#define i2cGCF                4                           // 广播呼叫头序列(从模式)+ g7 v: N3 G& H3 F
& ?" ^# h  O% D$ ]0 W. h8 n1 C
// I2CICR(I2C_ITR)——— I2C中断控制寄存器; [/ u6 v7 s9 a% m
#define i2cERRIE              0                           // 错误中断使能位
+ H" n- {$ |: J$ S( S#define i2cEVTIE              1                           // 事件中断使能位1 {& V2 r* _; D# p2 a* g) e( ?
#define i2cBUFIE              2                           // 缓冲中断使能位- G2 x! s9 I8 J0 g
$ z, W9 P$ s1 h* c2 l1 [- u% H: v
// I2CCCRL(I2C_CCRL)——— I2C时钟控制低位寄存器
7 g0 @. V* l) L8 N  h$ l#define i2cCS0                0                           // 预分频器时钟选择位0
5 h1 @) F' Y9 p$ e#define i2cCS1                1                           // 预分频器时钟选择位1$ c% y7 f2 z( W, b0 t$ p: W
#define i2cCS2                2                           // 预分频器时钟选择位2- K1 O: w- \0 `8 W
#define i2cCS3                3                           // 预分频器时钟选择位3
/ p1 v2 v: u3 S1 z#define i2cCS4                4                           // 预分频器时钟选择位4
5 u: R' I+ |: A5 ^' Q# G#define i2cCS5                5                           // 预分频器时钟选择位5- c$ i8 _  N& p# k9 T1 g" d
#define i2cCS6                6                           // 预分频器时钟选择位6
& Z( y8 U& N5 l2 O( i#define i2cCS7                7                           // 预分频器时钟选择位7
0 u+ d; l; v  P% s
! {% W0 H* @# H5 |4 ~/ }+ [// I2CCCRH (I2C_CCRH)——— I2C时钟控制高位寄存器, r% R2 O) J7 A* q
#define i2cCS8                0                           // 预分频器选择控制位82 `& ~& S+ ^# H8 D& S( A
#define i2cCS9                1                           // 预分频器选择控制位92 C, `: g# D/ O. V# M0 o1 j1 ~7 g
#define i2cCSA                2                           // 预分频器选择控制位10
2 I( ~! B4 V& G6 m  l#define i2cCSB                3                           // 预分频器选择控制位11
  }0 S' d$ ?. \& @8 A2 Z$ n. l+ C#define i2cDUTY               6                           // 快速模式下的占空比$ F+ ~; t! _# ?8 N$ t' s7 A
#define i2cSFM                7                           // 标准/快速模式选择位
磊元lystudio 回答时间:2015-10-2 01:57:14
__IO_REG8_BIT(I2CCR1    , 0x5210, __READ_WRITE, __BITS_I2C_CR1      );// I2C控制寄存器1) u* V& z9 X( ]
__IO_REG8_BIT(I2CCR2    , 0x5211, __READ_WRITE, __BITS_I2C_CR2      );// I2C控制寄存器23 L0 c$ z* G7 Q  S2 g/ V& c  \
__IO_REG8_BIT(I2CFR     , 0x5212, __READ_WRITE, __BITS_I2C_FREQR    );// I2C频率寄存器
- R7 h" T% ~) s. L( A* c__IO_REG8_BIT(I2CARL    , 0x5213, __READ_WRITE, __BITS_I2C_OARL     );// I2C(从机)地址低位寄存器
& w4 U- Y% @1 K, m__IO_REG8_BIT(I2CARH    , 0x5214, __READ_WRITE, __BITS_I2C_OARH     );// I2C(从机)地址高位寄存器# f5 }% n4 G; C0 ]) ]" N
__IO_REG8    (I2CDR     , 0x5216, __READ_WRITE                      );// I2C数据寄存器
  z1 q& x/ x) J; Q) B9 v1 W8 }__IO_REG8_BIT(I2CSR1    , 0x5217, __READ,       __BITS_I2C_SR1      );// I2C状态寄存器1
5 @) U/ ~0 N* X8 A0 I0 W__IO_REG8_BIT(I2CSR2    , 0x5218, __READ_WRITE, __BITS_I2C_SR2      );// I2C状态寄存器2
7 n5 d! {0 S1 f& c' G__IO_REG8_BIT(I2CSR3    , 0x5219, __READ,       __BITS_I2C_SR3      );// I2C状态寄存器3
6 ?, o  z) i- c__IO_REG8_BIT(I2CICR    , 0x521A, __READ_WRITE, __BITS_I2C_ITR      );// I2C中断控制寄存器8 y; \. R4 t& u" D# h
__IO_REG8    (I2CCCRL   , 0x521B, __READ_WRITE                      );// I2C比特率低位寄存器* c7 K  D( E' M# a3 g% n4 |; ^9 T
__IO_REG8_BIT(I2CCCRH   , 0x521C, __READ_WRITE, __BITS_I2C_CCRH     );// I2C比特率高位寄存器- m* B: t5 `) g( M: j
__IO_REG8_BIT(I2CTRISER , 0x521D, __READ_WRITE, __BITS_I2C_TRISER   );// I2CTRISE寄存器
5 J" D; [& K/ J3 \  Y: E2 M; ]__IO_REG8    (I2CPECR   , 0x521E, __READ_WRITE                      );// I2C包错误检查寄存器
皈依 回答时间:2015-10-2 08:28:22
感谢分享~一大串
你好我好大家好! 回答时间:2015-10-2 09:36:00
这是干什么呢,求关注吗
#define 回答时间:2015-10-3 11:09:15
MARK   最近在弄    问下   3.5的库 现在I2C中断还有问题吗
cos12a-21701 回答时间:2015-10-3 20:46:56
时光飞逝,都2016了。
磊元lystudio 回答时间:2015-10-22 22:45:50
修改一处错误:将
# q  B; u; w: b      case cI2cMrxAddrAck:                                // SLA+R 已发送,接收到 ACK' h6 P' j3 C- v( c
      {  E2 Q1 L+ u5 k; H* U# C; V
        MFHI2cBusRdataAck( );                             // 在接收之后发出 ACK 脉冲  f( e& y$ q! R# L/ M: _) ]& w% ^
        MFHI2cIntEventOnn( );                             // 使能缓冲中断
- n7 l& E" u7 a        break;
1 P& |- i& g/ X* d      }/ u/ I5 i9 W, L3 |3 Z7 T2 ~* `
改为:
- h. G0 w2 s0 {3 s$ l      case cI2cMrxAddrAck:                                // SLA+R 已发送,接收到 ACK( P. ~/ ?. ?7 U, |
      {
# D) ]! t' U$ r1 Q4 l( Z        if (pI2c->RxSize <= 1)                            // 如果只接收1个字节?% M- r" Q6 `% r9 @
        {. L0 V' ~, n3 l6 E! x/ ^$ J% [
          MFHI2cBusRdatNack( );                           // 在接收之后发出 NOT ACK
6 D, q6 Q) ~2 H- W" ^& _          MFHI2cBusNackStop( );                           // 发出 STOP 信号(结束条件),没有 ACK 脉冲
5 N* G+ l4 x. d0 `( j4 Y$ F. `        }% ^7 Z1 K: y4 M( o% w
        else
, R( d0 F7 C( Q+ l8 B% r' ?8 L        {
# A4 X2 i8 H/ M4 C+ {. }* G          MFHI2cBusRdataAck( );                           // 在接收之后发出 ACK 脉冲
  k0 c+ J% r- }& D: x        }4 S( b* }( u- ?7 ]3 l
        MFHI2cIntEventOnn( );                             // 使能缓冲中断( J1 q7 _6 a, D& G, C- Y
        break;. L) G% b7 I9 X- c5 ^: @* ]
      }
% Z5 T1 R+ d1 f$ u; |- _& X以避免只接收1个字节时,发生溢出错误。
samsamhoo 回答时间:2015-10-25 18:50:25
好资料,谢谢分享。
12

所属标签

相似技术帖

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