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

基于STM32的硬件和软件IIC区别经验分享

[复制链接]
攻城狮Melo 发布时间:2024-5-29 19:23
IIC(Inter-Integrated Circuit)是一种常见的串行通信协议,广泛应用于各种嵌入式系统中,包括STM32单片机。在STM32中,IIC通信可以通过硬件IIC和软件IIC两种方式实现。本文将介绍IIC的基本原理,然后重点探讨STM32中硬件IIC和软件IIC的区别。/ V9 _* O! m! M: z
* ]7 I. L7 S3 a, c
微信图片_20240529192252.png 2 |% d/ S0 }6 R3 u  r( x0 \
6 t- t: {7 M6 B: d& E4 h. x4 l
IIC基本原理:IIC是由飞利浦(Philips)公司提出的一种串行通信协议,适用于在同一电缆上连接多个设备。它采用两根线进行通信,即SDA(数据线)和SCL(时钟线)。设备之间通过这两根线实现数据传输,其中SDA用于传输数据,SCL用于同步时钟。
+ r, U! N: g1 z
0 {5 g  ^6 c* X 微信图片_20240529192248.png ) `1 q$ I, w7 {( l8 c
+ u1 O! S9 ?1 _2 H6 u- d
一对IIC总线上面可以挂载多个设备并且多个设备之间有不同的地址,所以我们可以根据不同设备的地址来实现不同设备之间的通信。6 S4 \& `9 I' h& d6 o
" M8 N: {  @+ I5 e- S( e
软件IIC
0 t5 [. F" W! n' Q9 T( `在STM32中,软件IIC是一种通过程序控制GPIO口模拟实现IIC通信的方法。这种实现方式常用于一些资源有限的应用场景,或者在需要更灵活控制IIC通信时使用。) ^5 E: \8 j1 x2 P' V# b; @& i
0 Z, O# F& x3 b: |- W2 H
微信图片_20240529192245.png $ J  l$ G9 i$ f- X# ~+ J

' E) p2 t, J1 n" ?9 l* d% X总而言之,软件IIC是利用GPIO的翻转,一个IO模拟SCL线,一个IO模拟SDA线实现IIC通信协议的实现。2 p+ f/ r# l; ?# X' I3 {
5 N/ Z8 T' L! Z; e- H  L
软件IIC不需要对IO有特殊的要求,只需要两个普通的GPIO即可实现,因此较为方便也方便移植,不同设备只需要重写IIC的基本通讯即可。
  a0 k+ Z  ]1 {9 u0 b
  1. // 定义IIC的GPIO口和引脚/ E  H6 ]* A" x! J! v2 o
  2. #define IIC_SCL_PIN GPIO_PIN_63 F0 F6 }: R6 l. H
  3. #define IIC_SCL_PORT GPIOB
    1 y5 }( N& `! R# \+ A

  4. * f( |7 S/ o7 \5 U
  5. # T6 \# G7 ?9 g7 \- M5 `
  6. #define IIC_SDA_PIN GPIO_PIN_9
    9 n* u/ g7 L0 c# U
  7. #define IIC_SDA_PORT GPIOB
    : U- c( U# y) p+ x5 I: p
  8. ' v4 I9 y. \  `) \
  9. 9 `2 ?8 L" t* a( R- A2 f4 g
  10. // 定义读写控制位/ }& W3 t4 n% v5 K$ a# f
  11. #define IIC_READ  1+ r& w3 v5 A, C* d. y
  12. #define IIC_WRITE 0* q/ }4 M' W8 ~* r1 H1 t0 T
  13. ( }0 f  T% g1 c6 c5 H
  14. 1 w. @8 i) o9 K" D" ^
  15. // 定义函数4 P) r% R- Q0 I# C! J
  16. void IIC_Start(void);; b/ h9 M$ _9 i# e0 ?3 A( m# V, M
  17. void IIC_Stop(void);
    $ p$ S% L  }, F% Y: Q* p
  18. void IIC_SendByte(uint8_t byte);" Z7 R4 y$ K# @* @3 F
  19. uint8_t IIC_ReadByte(uint8_t ack);7 w* l! q8 L( G" ?- s: n

  20. % ?( h+ R6 H, m# Z+ {, y5 E* B0 [9 d
  21. ) ?1 V5 C6 D3 s6 n0 u
  22. & `0 C. b  A5 F4 V* T' i+ f

  23. $ u: Q$ T  h) p) p+ v
  24. // 启动IIC总线9 e* u. p: ?  N& l0 N
  25. void IIC_Start(void)
    1 k" H+ `! |6 i( p  r0 L. H
  26. {
    : t. l$ Z* O$ Y
  27.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
    ' k, G8 Y% S% x! x, ?
  28.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    : ]" x% M5 f3 q, i
  29.     HAL_Delay(2);  // 稍微延时,确保时序正确8 ?: H+ h$ e: j9 z  r* s
  30.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);
    ' T( D2 M' I. T; r0 G4 O
  31.     HAL_Delay(2);
    8 q, w6 n, N* C
  32.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    4 m) p; B8 G1 F$ Q  S
  33. }! d. I' C9 d4 y3 ^
  34. 4 M; J8 c$ s/ I

  35. ; T! \) T& q3 Q& I1 z
  36. // 结束IIC总线7 i) b0 Y+ ?  C' m& P2 p9 z# V8 x
  37. void IIC_Stop(void)) P, T" f% S& e4 u4 f
  38. {
    6 S: H  G: J) f! A1 o" P
  39.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);
    4 M2 e) T# B+ @( y
  40.     HAL_Delay(2);
    ; p7 \/ Z# U' O5 c' N2 [
  41.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    9 c% q1 T. _* V0 Q$ w/ v
  42.     HAL_Delay(2);$ q0 \$ s1 ^$ k0 c
  43.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);+ E* |5 _9 c0 Q4 M& Z5 e) r' m* T
  44.     HAL_Delay(2);: h. k7 R4 K; [1 |7 `% A3 y& l
  45. }! S% W3 _  a6 Q: {9 O# l8 N9 v! v
  46. 9 ]! j+ D# z* X$ U5 T$ @% `

  47. 4 w9 B! G/ p( Y# J
  48. // 发送一个字节( M  y( q) r2 ]6 b6 W
  49. void IIC_SendByte(uint8_t byte)  C; O( S( Q( }% e2 q
  50. {
    ' x' \* |& F* S3 A  d4 X
  51.     for (int8_t i = 7; i >= 0; i--)& |9 V. g) T, s/ P  W, v4 D
  52.     {5 }, a' X; z" @4 t; w
  53.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);0 w1 L" R3 |+ T
  54.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, (byte & (1 << i)) ? GPIO_PIN_SET : GPIO_PIN_RESET);
    , }2 h+ I% Z3 l
  55.         HAL_Delay(1); // 稍微延时,确保时序正确# o( y! A# u. C( Y/ `1 P- \' W- `
  56.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    . X+ w9 r* h0 A) B
  57.         HAL_Delay(1);) l( r- b* v8 V) U3 X  `/ W
  58.     }( }: K: v0 `. u. T2 s
  59.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);( x& a& D7 y0 x1 [4 }# r; ?* K1 m3 l
  60. }5 K6 M# s  A2 G( N8 f/ G7 |# Q
  61. 5 W5 @+ _1 Z! S* X

  62. # s4 _5 z8 E5 E
  63. // 读取一个字节1 G5 ?  T5 F* a# A& d" @
  64. uint8_t IIC_ReadByte(uint8_t ack)0 k0 [  j* v( W
  65. {# ?) a" k/ k  v  _5 ^, b. A* X3 o; \
  66.     uint8_t byte = 0;
    , g: k. O: x6 G  W( {
  67.    ! ^7 T) I" `6 [) T
  68.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);+ b# b" V3 ^/ I6 ~4 u5 N0 j
  69.     for (int8_t i = 7; i >= 0; i--)
    - B, Y7 B" e4 R
  70.     {9 G2 G. K9 P: b
  71.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    ( f/ T/ P) z. u0 g1 ~6 D. n
  72.         HAL_Delay(1); // 稍微延时,确保时序正确7 w, [( B2 I: W' H9 U* ~% \) q0 q# @( [
  73.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);9 W: J7 i6 Z9 Q7 z& [# _, |5 Q
  74.         HAL_Delay(1);: x( L" d* r7 M% f, s
  75.         byte |= (HAL_GPIO_ReadPin(IIC_SDA_PORT, IIC_SDA_PIN) << i);) ?, t# ^: O. W% ?- B" P
  76.     }0 V2 H& e$ e) z
  77.    
    6 B4 e- u2 |2 x
  78.     if (ack)
    , y3 M# k6 G2 }' P0 G' M
  79.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET); // 发送应答
    # }* u$ d* e+ [
  80.     else
    1 ^5 p+ m$ Y9 [9 t
  81.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);   // 不发送应答
    4 |* E9 P% R$ z" u
  82.    
    * x8 Q+ u. a9 d9 q$ L3 l/ ?
  83.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    ; A  }0 a. i% c" R
  84.     HAL_Delay(1); // 稍微延时,确保时序正确
    - r" P! t" r0 T3 T8 ?! P! ^
  85.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    2 m8 z2 h5 _; L" c1 _) X
  86.     HAL_Delay(1);
    4 @  m) j7 g* B$ d% n
  87.    5 \+ N: Y! \9 j1 m& f( C; `
  88.     return byte;& y7 b0 S' ~" X# H
  89. }
复制代码
' s. K$ _/ _# H# c8 x5 i
例如IIC的启动信号为:SCL为高电平的时候,SDA从高电平转为低电平。$ {/ J5 ^$ @0 O

& U7 n; M' [5 z9 c& r* S; q
IIC的结束信号为:在SCL线是高电平时,SDA线从低到高的跳变。) q/ K. u8 a* W4 `# J# C) ]
3 @. N2 l6 Q& V
因此使用这种方法可以模拟IIC时序完成通讯。. m. j% @; m2 H# z4 w4 V

0 r( M2 \4 X" s; U" W. w
但是这种方法的弊端也是非常明显的,需要占用CPU,其次这样子并不能确保I2C时序的正确性。所以无论是稳定性还是可移植性还是IIC的效率都欠妥。% C# w) O" g+ h+ Y

* u* i/ [6 j" S* a
STM32中的硬件IIC    - ?6 W( D7 f8 C, o1 u- r
STM32系列单片机提供了硬件IIC(Inter-Integrated Circuit)模块,用于支持IIC通信协议。硬件IIC通过专门的硬件模块实现了IIC协议的基本功能,包括起始信号、停止信号、时钟同步等,无需用户通过软件模拟实现。
/ b6 a/ }  j* Z3 u) j
/ U4 f4 V8 P' G' @. p
STM32硬件IIC优势:( C: R" O- q( }* m4 F
1.高效性: 硬件IIC使用专用硬件模块处理通信,不需要CPU直接参与,提高了通信效率,降低了对CPU的负担。1 ]3 d5 y' g8 D8 l+ S6 H) e7 Y
2.时序精确控制: 硬件IIC模块能够精确控制时序,确保通信的稳定性,避免了由于软件执行时间不确定性而引起的时序问题。
) D6 E' W$ \4 t" h/ D! ^& I3.多主机模式支持: 硬件IIC模块通常支持多主机模式,能够轻松处理多个设备同时访问总线的情况。! {8 f' O* _$ Q) R/ K% E
4.易用性: 由于硬件IIC是芯片内置模块,使用起来相对简单,只需配置相应的寄存器和引脚即可。% L/ F2 x: ?) a5 Y- H! p
5.占用资源少: 硬件IIC模块通常占用较少的资源,对于资源有限的嵌入式系统来说,是一种较为理想的选择。) |+ D& s% v. F( G0 k- I1 y

5 S; T6 h. T5 q1 _' j/ E2 q
微信图片_20240529192242.png
( V( d- O2 l% n3 u# ~, y6 w7 R3 `) M, H6 A6 q! Z1 o- N7 G
在CubeMX中配置好硬件IIC即可利用HAL库函数进行IIC通讯。
  1. static void MX_I2C1_Init(void)
    / B2 `7 Z4 @/ n; u2 @
  2. {
    " [0 r& }9 L2 v1 h. ?) d
  3.   hi2c1.Instance = I2C1;$ Y5 U+ Y, O# ~# v$ {8 m
  4.   hi2c1.Init.ClockSpeed = 100000;
    2 c! O+ C: m4 @4 g, ~& \  x' |
  5.   hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;6 U1 V% q- G/ m: W. v& V4 n
  6.   hi2c1.Init.OwnAddress1 = 0;* W7 d, V6 y! h. N7 V
  7.   hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;" T- E* l8 S1 w: {# w- }8 i: B5 [
  8.   hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;, i: \; S5 K1 ^6 r) L0 a
  9.   hi2c1.Init.OwnAddress2 = 0;- r3 S# e: n* b# D6 S
  10.   hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;9 C/ t: [. `% l5 e$ B
  11.   hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    8 K4 j$ l4 t' S9 i2 Q  G. \
  12.   HAL_I2C_Init(&hi2c1);
    1 O2 h! P* h/ o# U+ U' A: W! r7 A
  13. }
    / t4 ]% k- B3 p8 G( Z( e0 r& k

  14. # u1 h! M7 r& y; D' ?* y8 R4 v

  15. ) A* `$ \6 r) H
  16. uint8_t deviceAddress = 0x50;//设备地址
    * t) f4 r' S$ F; s
  17. uint8_t registerAddress = 0x00;//寄存器地址
    6 {% [& R, {7 ?' x3 ^4 h; u
  18. HAL_I2C_Master_Transmit(&hi2c1, deviceAddress, &registerAddress, 1, HAL_MAX_DELAY);
复制代码

0 v  d, r! X  \4 Z  V9 \调用CubeMX的初始化函数,之后就可以使用例如HAL_I2C_Master_Transmit,HAL_I2C_Master_Receive等函数来实现IIC通讯。+ K) T, O" O5 ]4 D

& m2 I" l5 x! E0 L, H  \8 }) A* @2 j+ \, G6 F$ m: `: J& t
STM32硬件IIC缺点:4 l$ i2 G" C6 v! ]) `/ |  Y/ L3 R
1.资源占用: 相比软件IIC,硬件IIC模块可能会占用一定的硬件资源,因此在资源受限的系统中需要谨慎选择。
5 j) E9 }' ]2 g% n- ]! \# B' z3 r2.灵活性: 硬件IIC通常由芯片内部硬件模块实现,因此在一些特殊场景下可能缺乏一些灵活性,例如无法更改时序。
1 S$ |+ ^" H( h- f& F8 U# r$ |1 I3.部分限制: 不同型号的STM32芯片的硬件IIC模块可能存在一些差异,不同芯片的IO不一样,所以设计时需要谨慎检查。
) h) S  h- e( N6 T$ D% e
/ f" M" k3 X; s; S8 _总体而言,STM32的硬件IIC是一种高效、稳定的IIC通信方式,特别适用于对性能要求较高的应用场景,同时在易用性和可靠性上有较大优势。在选择IIC通信方式时,可以根据具体需求权衡硬件IIC和软件IIC的优缺点。
4 b" |1 Z" W7 o& E7 S7 O* q  p# B, S1 [7 z+ l

4 J% G4 M0 W5 L/ Z
* w- K2 k5 U& Y* r3 K3 O2 _转载自:电路小白
4 f: u2 E% }4 U如有侵权请联系删除$ ?' ?1 k' g# f, C% w

8 s2 i! a& q7 e' x. Y+ A$ t
收藏 评论0 发布时间:2024-5-29 19:23

举报

0个回答

所属标签

相似分享

官网相关资源

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