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

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

[复制链接]
攻城狮Melo 发布时间:2024-5-29 19:23
IIC(Inter-Integrated Circuit)是一种常见的串行通信协议,广泛应用于各种嵌入式系统中,包括STM32单片机。在STM32中,IIC通信可以通过硬件IIC和软件IIC两种方式实现。本文将介绍IIC的基本原理,然后重点探讨STM32中硬件IIC和软件IIC的区别。
9 e1 u; f! f, r) A' T- y1 Y$ l8 q
微信图片_20240529192252.png & N1 B2 J! Q, h/ e. M2 _8 q% f1 N

- U8 l$ Z) F, t( p4 R# {3 [* D8 IIIC基本原理:IIC是由飞利浦(Philips)公司提出的一种串行通信协议,适用于在同一电缆上连接多个设备。它采用两根线进行通信,即SDA(数据线)和SCL(时钟线)。设备之间通过这两根线实现数据传输,其中SDA用于传输数据,SCL用于同步时钟。
' e1 d2 k1 ?: u6 x
. e% A7 J, z, A" M: \. T 微信图片_20240529192248.png   X" L  ?% M1 i! w& H4 o0 s

) g; [  Y( F- \( }9 z1 U一对IIC总线上面可以挂载多个设备并且多个设备之间有不同的地址,所以我们可以根据不同设备的地址来实现不同设备之间的通信。
, G& @( u) L0 F1 Q9 T6 E
- @- Q8 h/ r' U% F" G+ u! G" q7 U
软件IIC
. o0 z; j: E5 w/ l" B1 q4 D3 V在STM32中,软件IIC是一种通过程序控制GPIO口模拟实现IIC通信的方法。这种实现方式常用于一些资源有限的应用场景,或者在需要更灵活控制IIC通信时使用。, q: o1 _) o8 |7 S8 l* L
( r  ]" f. f; }6 g# E
微信图片_20240529192245.png
. ^. k1 k3 m  }2 g- ]! p
- R0 C4 @0 }) n3 \
总而言之,软件IIC是利用GPIO的翻转,一个IO模拟SCL线,一个IO模拟SDA线实现IIC通信协议的实现。
4 B7 E$ j3 |: Y
' E* G' t3 c8 _% x8 ]% E3 K
软件IIC不需要对IO有特殊的要求,只需要两个普通的GPIO即可实现,因此较为方便也方便移植,不同设备只需要重写IIC的基本通讯即可。
+ J" ^. |+ s7 C0 m1 M4 f8 k9 x. u
  1. // 定义IIC的GPIO口和引脚) g! u6 a6 y! P' |/ W6 }
  2. #define IIC_SCL_PIN GPIO_PIN_6
    ! i6 ^- L- z' q- g% R+ u
  3. #define IIC_SCL_PORT GPIOB/ S- o# Y8 M& d( J! w+ K& E

  4. ' t* i5 p! Z) T5 [
  5. 4 V) B, D. ?4 O1 l8 t% ]
  6. #define IIC_SDA_PIN GPIO_PIN_9
    ( I0 y3 {% a  s( Q" E. ]' a
  7. #define IIC_SDA_PORT GPIOB
    : R& w2 r' {- N; Q5 C: u( u3 p

  8. % o( ~$ F, {  r0 A% h8 N4 N

  9.   H6 O/ O4 J( n3 z0 i% C) R0 U: ?
  10. // 定义读写控制位$ q1 M9 d' R6 N! b; _* [
  11. #define IIC_READ  1
    % v5 o7 W. n3 q+ n3 `( g
  12. #define IIC_WRITE 0
    * S" ~" n8 t3 C, \0 f
  13. 5 u5 W. v- @1 |& ]) K' Z" q
  14. . x- k$ h3 B2 G1 I
  15. // 定义函数
    + I, o- F: I. b8 D5 \" H' W
  16. void IIC_Start(void);% \% |3 R& F( q
  17. void IIC_Stop(void);
    4 |8 |2 j1 o) Z1 N# R& g. L! O) h) s5 C
  18. void IIC_SendByte(uint8_t byte);( h( F# d+ c5 a8 F, }" K; [- a" a
  19. uint8_t IIC_ReadByte(uint8_t ack);
    5 b) ~9 R% G- U
  20. 0 s/ U# T# g, t+ r
  21. $ o: t$ _. p8 q+ u9 T" i
  22. ( ?; Q+ H8 m: p* t; C: X  \
  23. ) w- H. ?' Y8 E7 }
  24. // 启动IIC总线6 ~& a) C; n0 ?5 }; p; ~, u
  25. void IIC_Start(void)
    * c; @6 r1 V5 ]$ V% W3 |8 m. Y' c
  26. {
    ) K2 f$ d6 K5 a% |$ ?
  27.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
    5 j7 e' D' D2 l
  28.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);0 {) R% _! P: o+ z6 |
  29.     HAL_Delay(2);  // 稍微延时,确保时序正确
    : u/ Q8 Q7 v4 h" _
  30.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);! A3 j% [# b: y( t# l4 }
  31.     HAL_Delay(2);
    2 n. {% m/ @) L6 T2 m6 o. [
  32.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);! p% D2 M1 B- S; x3 ]
  33. }! @+ h% t- ~% A6 T, G
  34. & |. j5 p( i3 d, n! @

  35. ; K$ X  C/ m' O, P' S+ h4 }' s$ U
  36. // 结束IIC总线
    8 E; X7 l9 _8 x/ R3 U( h
  37. void IIC_Stop(void)
    % [# B0 m2 y& t! L2 t
  38. {+ F0 r0 c3 P1 ]* g% u
  39.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);
    3 T6 r) j/ P: D: A0 V
  40.     HAL_Delay(2);5 f* M6 ~4 W: s9 X. u
  41.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);; [1 N% r8 F0 w5 N4 h
  42.     HAL_Delay(2);4 b9 ^8 a( V5 \( W  E/ p
  43.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);. V1 Y" _% _/ y# z3 K7 \) k# V8 o
  44.     HAL_Delay(2);) v6 ?; m" w! Z- u' D3 Q9 o
  45. }1 F( M+ [& [& A  o7 x" Q

  46. 4 T+ N* o; T* D7 d( l

  47. 5 D9 g% F8 I% S. o' F0 F
  48. // 发送一个字节
    2 w# E8 h! ?* ]* Y2 r4 U7 N1 Q
  49. void IIC_SendByte(uint8_t byte)
      q1 `5 I8 G. {
  50. {) n2 N7 T$ a8 p. U/ F. h, \1 p
  51.     for (int8_t i = 7; i >= 0; i--)
    , S1 `- x, f8 o9 u) g5 b7 Q3 F
  52.     {% J8 |. d& F$ N+ Z
  53.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    0 h$ b7 D& o' g3 {8 }
  54.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, (byte & (1 << i)) ? GPIO_PIN_SET : GPIO_PIN_RESET);- a1 s3 A6 R& `% |, D0 X
  55.         HAL_Delay(1); // 稍微延时,确保时序正确7 U0 {  G1 g; ?8 {' D! t; L
  56.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    / }- b) d* E( o; N) Q+ ~
  57.         HAL_Delay(1);& o+ j% @7 j5 C
  58.     }) M4 {( H3 Q( f% D1 d+ O
  59.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    1 s+ U9 ^0 G2 b) x! q6 A" X. ?
  60. }3 x, x6 g- r! w& y( U- o8 ?8 j1 m

  61. $ c% E7 H/ x' s/ b7 m

  62. 0 P' D8 H- U3 c
  63. // 读取一个字节) J4 b9 F  b& e6 W! H
  64. uint8_t IIC_ReadByte(uint8_t ack)
    0 \6 C* s. y+ M& O: M  H0 h
  65. {
    - y) m6 u: @, X
  66.     uint8_t byte = 0;
    , S2 e! W7 K  d  x1 {* G
  67.    5 g: p8 h; H7 G3 ]2 [/ L; D
  68.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
    - c" x5 V, {3 Q# d2 O9 a2 o# s
  69.     for (int8_t i = 7; i >= 0; i--)
    3 {8 V8 i6 w/ c( h
  70.     {$ {1 s( G: h2 I4 o) n8 X
  71.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);# v3 W3 ^9 A4 l& v
  72.         HAL_Delay(1); // 稍微延时,确保时序正确/ _& Z. t3 Q" H( c2 V' f
  73.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    ' }) }7 E, C( j
  74.         HAL_Delay(1);
    9 b; ]8 e5 B: z7 F
  75.         byte |= (HAL_GPIO_ReadPin(IIC_SDA_PORT, IIC_SDA_PIN) << i);/ [8 w6 p7 c2 a) x4 b
  76.     }
    7 A% _" s& j0 Z
  77.    
    / ]1 V2 K  e2 N2 V0 {
  78.     if (ack). l( Z6 i6 [6 X! [
  79.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET); // 发送应答
    - Y/ Y: B) U/ u1 S8 p
  80.     else8 m2 w6 w- K/ M  F
  81.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);   // 不发送应答
    ; ?+ k+ z, W# R. R2 O) N7 ]5 Z
  82.    4 q- ]: Z) |  }* y3 J: u
  83.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);6 ^; Y, Y: d* f6 I+ Q
  84.     HAL_Delay(1); // 稍微延时,确保时序正确1 M; J* T/ ~. @5 Y7 ~. }+ Y
  85.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);' R6 r- O- @8 ?6 w' D
  86.     HAL_Delay(1);
    ! k% f6 U+ w" T7 ~) B; ^; E
  87.    
    3 A# }2 h- ]  o% m+ `' n# k& c
  88.     return byte;
    0 L: v  K/ a/ P  j4 v
  89. }
复制代码

! v$ P6 p, C* v/ _例如IIC的启动信号为:SCL为高电平的时候,SDA从高电平转为低电平。
2 J& i" F7 V6 ^
- z+ {: l/ R( `5 R; i
IIC的结束信号为:在SCL线是高电平时,SDA线从低到高的跳变。
' ]' m1 w8 ^+ q& h: H/ \! l  ^' F- a) g1 R
因此使用这种方法可以模拟IIC时序完成通讯。
7 @  Z8 v( t  w+ P
% H0 y# v, F; b% v; P
但是这种方法的弊端也是非常明显的,需要占用CPU,其次这样子并不能确保I2C时序的正确性。所以无论是稳定性还是可移植性还是IIC的效率都欠妥。
& A- r" D+ _* \+ ^/ I9 W
  u8 Q7 l2 h( f0 L
STM32中的硬件IIC    ) t- O. b; x* C# c; q
STM32系列单片机提供了硬件IIC(Inter-Integrated Circuit)模块,用于支持IIC通信协议。硬件IIC通过专门的硬件模块实现了IIC协议的基本功能,包括起始信号、停止信号、时钟同步等,无需用户通过软件模拟实现。/ ]6 r" E! t" r8 [/ _% ~

1 j( e- K8 ^! s2 `/ _; ESTM32硬件IIC优势:1 E' z5 I7 e9 ]" D2 H) m1 \
1.高效性: 硬件IIC使用专用硬件模块处理通信,不需要CPU直接参与,提高了通信效率,降低了对CPU的负担。
, g" w- M. x, @& t8 _: X& G
2.时序精确控制: 硬件IIC模块能够精确控制时序,确保通信的稳定性,避免了由于软件执行时间不确定性而引起的时序问题。
4 v; t3 n' c# E, R3 V3 J3.多主机模式支持: 硬件IIC模块通常支持多主机模式,能够轻松处理多个设备同时访问总线的情况。% P. x' T! S- {9 p
4.易用性: 由于硬件IIC是芯片内置模块,使用起来相对简单,只需配置相应的寄存器和引脚即可。
$ z+ J! |6 {0 s5.占用资源少: 硬件IIC模块通常占用较少的资源,对于资源有限的嵌入式系统来说,是一种较为理想的选择。+ q% K) L$ H$ i

* p- N/ W, ^5 T: d& o5 j! ?3 [
微信图片_20240529192242.png
0 e& M- M+ t# E9 Y' @( a7 ~8 `5 U  |* a$ X$ S+ @4 S
在CubeMX中配置好硬件IIC即可利用HAL库函数进行IIC通讯。
  1. static void MX_I2C1_Init(void)& s* G& h, o( z9 P7 |; R4 l
  2. {, v% Z' a( `7 y5 X2 k
  3.   hi2c1.Instance = I2C1;
    , A+ y& z( C$ c: J
  4.   hi2c1.Init.ClockSpeed = 100000;
    " [2 s: v& B& \* Z5 d2 C$ z8 R1 q
  5.   hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;3 Y0 d- Z* E2 F  |: K
  6.   hi2c1.Init.OwnAddress1 = 0;
    4 b6 c1 G4 U' j, Y6 l- \
  7.   hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    % a( o5 W: q5 h6 |- |. I
  8.   hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
      F$ k7 U: W9 }- X3 I6 Y1 w
  9.   hi2c1.Init.OwnAddress2 = 0;( ^" p0 Q" G% T
  10.   hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    ) D) V5 ]- G2 X% g; [8 R+ Q
  11.   hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    . R" d/ {' ~9 q4 p% K# V
  12.   HAL_I2C_Init(&hi2c1);4 E% K8 N7 Q$ v$ W! H
  13. }
    6 T4 Y" r* h$ O
  14.   Q) l; n9 G) O3 ]% O' t) k
  15. 6 e5 \/ N8 \. O8 {6 j+ d/ ~
  16. uint8_t deviceAddress = 0x50;//设备地址
    & i  j  M7 r4 U7 Z+ e8 c$ v* X
  17. uint8_t registerAddress = 0x00;//寄存器地址
    ; e+ S- s' {$ }* N
  18. HAL_I2C_Master_Transmit(&hi2c1, deviceAddress, &registerAddress, 1, HAL_MAX_DELAY);
复制代码
0 n- O3 d$ Y- _  I$ W
调用CubeMX的初始化函数,之后就可以使用例如HAL_I2C_Master_Transmit,HAL_I2C_Master_Receive等函数来实现IIC通讯。
  ]+ Z7 g+ C+ t2 m1 `' N
2 C0 ?! s# c  ?; U! e0 y) C7 o1 j" F+ M* s- `- M
STM32硬件IIC缺点:3 p% b" |! A: L% R  K) \; d4 W
1.资源占用: 相比软件IIC,硬件IIC模块可能会占用一定的硬件资源,因此在资源受限的系统中需要谨慎选择。4 F! s3 {8 P" }( U" F) d, A, g
2.灵活性: 硬件IIC通常由芯片内部硬件模块实现,因此在一些特殊场景下可能缺乏一些灵活性,例如无法更改时序。
+ s2 [" ]  @% Y2 _/ I3.部分限制: 不同型号的STM32芯片的硬件IIC模块可能存在一些差异,不同芯片的IO不一样,所以设计时需要谨慎检查。  s2 g, z( A* `# @% y

3 p, p/ w% n) E* h5 R  Z! p  f总体而言,STM32的硬件IIC是一种高效、稳定的IIC通信方式,特别适用于对性能要求较高的应用场景,同时在易用性和可靠性上有较大优势。在选择IIC通信方式时,可以根据具体需求权衡硬件IIC和软件IIC的优缺点。7 Y3 w9 u8 z9 q* ]( r# e
; o7 I6 @4 H: ~" {! u2 N5 r  }. U

, i6 x: }  ?3 a( s! V  V3 ^
5 G9 E8 c2 V9 {1 X转载自:电路小白
0 {, G* L+ w0 ?; @- r5 E如有侵权请联系删除; ~- k" p4 c4 s/ u, i5 e

' z$ J' T$ t/ _
收藏 评论0 发布时间:2024-5-29 19:23

举报

0个回答

所属标签

相似技术帖

官网相关资源

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