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

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

[复制链接]
攻城狮Melo 发布时间:2024-5-29 19:23
IIC(Inter-Integrated Circuit)是一种常见的串行通信协议,广泛应用于各种嵌入式系统中,包括STM32单片机。在STM32中,IIC通信可以通过硬件IIC和软件IIC两种方式实现。本文将介绍IIC的基本原理,然后重点探讨STM32中硬件IIC和软件IIC的区别。
, x5 G+ [4 A% s7 O/ `4 H5 p" j9 s, [9 R9 q0 q; c+ d
微信图片_20240529192252.png " S% G% l8 z4 h/ Z9 ?' u+ G1 g5 a/ V) P

! d, _- B( z4 }  }. h5 b' AIIC基本原理:IIC是由飞利浦(Philips)公司提出的一种串行通信协议,适用于在同一电缆上连接多个设备。它采用两根线进行通信,即SDA(数据线)和SCL(时钟线)。设备之间通过这两根线实现数据传输,其中SDA用于传输数据,SCL用于同步时钟。$ `3 l- W% K( K  l
% B. K: g/ W5 t: t& K
微信图片_20240529192248.png 6 g$ h0 T2 Q! _' @2 H% S
  s  A% {$ y& B5 S9 L( }' k- |
一对IIC总线上面可以挂载多个设备并且多个设备之间有不同的地址,所以我们可以根据不同设备的地址来实现不同设备之间的通信。
# n7 Q2 c3 `. z" r& v# i" @% M1 P) e9 h( k8 G- O* H
软件IIC
. @6 U' `+ s" c! {0 p4 m: J# V在STM32中,软件IIC是一种通过程序控制GPIO口模拟实现IIC通信的方法。这种实现方式常用于一些资源有限的应用场景,或者在需要更灵活控制IIC通信时使用。7 G# J$ m# @7 q" t6 L

% e+ d, Q6 ]9 j 微信图片_20240529192245.png
+ T: E1 C+ c4 Y, ^2 {

0 ], p, M4 \8 D2 y6 H总而言之,软件IIC是利用GPIO的翻转,一个IO模拟SCL线,一个IO模拟SDA线实现IIC通信协议的实现。
! `! }" N" C& c% N) W
& E1 Z& J8 E  B/ N0 W; k
软件IIC不需要对IO有特殊的要求,只需要两个普通的GPIO即可实现,因此较为方便也方便移植,不同设备只需要重写IIC的基本通讯即可。; ]6 |, c, d: y( P, f6 M3 i
  1. // 定义IIC的GPIO口和引脚2 ^' ]7 T+ }" O0 e' C$ e4 {' I
  2. #define IIC_SCL_PIN GPIO_PIN_6- U0 u. k1 S$ y+ q/ Z/ O
  3. #define IIC_SCL_PORT GPIOB
    . z) I" O2 R; w! K& i  O+ [7 r- N
  4. 3 D: B7 ~) y: ^
  5. + N% l6 m2 L; n$ ?, T
  6. #define IIC_SDA_PIN GPIO_PIN_9
    ) h- n9 f* d  p
  7. #define IIC_SDA_PORT GPIOB
    ) K$ K% I' x8 O6 s2 F, v

  8. 1 k9 y+ F$ g. M

  9. / y4 o/ R2 g' M2 V" E3 ^* V# H0 z6 m, h
  10. // 定义读写控制位" P* @1 ?; a5 F+ A; [: D9 ]0 h
  11. #define IIC_READ  1! N, i' _, p& G( O4 F: o. s8 I
  12. #define IIC_WRITE 0
    # s* a& e( }7 w3 W

  13. . F3 X  v' k( Q
  14.   v( M+ Z8 m* P% E9 R- f+ Z1 {. c
  15. // 定义函数1 p' z! R( `& C3 A6 B3 `/ @
  16. void IIC_Start(void);
    $ t0 d! [- i2 v9 i4 x
  17. void IIC_Stop(void);0 Q  q) N/ \7 h0 q* @
  18. void IIC_SendByte(uint8_t byte);7 c) i( X8 t- U: o. Q# A
  19. uint8_t IIC_ReadByte(uint8_t ack);
    # H. M7 q5 @- A4 K% K$ U' V
  20. $ L0 b+ {+ r4 @: {

  21. . [5 \. L, Z6 r, ?2 Z, H

  22. ! V  V4 j* D6 o" x( W0 [

  23. 8 A8 j# n1 k! ^. D/ R. Y
  24. // 启动IIC总线) a- L5 A& x# t! c
  25. void IIC_Start(void)
    1 Q  |  t& \0 R: [* Z1 }
  26. {: @$ t; F; e2 G7 v+ Q
  27.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);- y! y+ r5 f/ X
  28.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);) |$ z. }5 [5 z2 `. K0 I! t4 j+ ?
  29.     HAL_Delay(2);  // 稍微延时,确保时序正确7 K* U- t! Y. O  M  E5 n* M1 B" S
  30.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);
    6 [  `  W! Q" c7 m
  31.     HAL_Delay(2);
    ; M9 E# ^# {9 T; I
  32.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);. n" v: b; s* N6 e3 K3 N5 }& `0 y' S
  33. }
      V/ O5 C& c6 n# A) c' K3 B7 n

  34. / d9 I* o5 ?' B. y: U

  35.   `7 g- F, z# z7 t" s
  36. // 结束IIC总线
      }! Q  U7 a/ D7 }# E6 W
  37. void IIC_Stop(void)
    1 y5 z3 g; U+ Z, a  i( `+ j
  38. {* y1 U# J/ ~( n& P
  39.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);
    ' O2 f% x$ M6 \; |6 v
  40.     HAL_Delay(2);
    & A3 H) B  z; v
  41.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    6 R6 g! T. {. p, L: e8 W% r% f- d
  42.     HAL_Delay(2);
    / _" w# R4 c/ s. f1 L
  43.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
    9 `, E, L* F( b0 }7 N. W  E$ m7 W
  44.     HAL_Delay(2);
    & [. e5 ~; n& o0 c$ ^+ h
  45. }
    2 Q* h$ f+ ~2 s! J
  46. 6 ]; {0 `: u5 V& Q# i+ |; s
  47. ) W8 q& P( e: ?" a4 X: x. E; n
  48. // 发送一个字节
    : l- Z- O6 n9 E5 M
  49. void IIC_SendByte(uint8_t byte)1 J9 e% F0 a. ]/ v- P" e
  50. {
    ' y' O1 P5 r0 c, V! S) o
  51.     for (int8_t i = 7; i >= 0; i--)
    ! J; U( B9 H! x* D' g
  52.     {
    ! @$ V. g2 R3 b
  53.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);- Q& r3 j) M+ k8 C4 R* a
  54.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, (byte & (1 << i)) ? GPIO_PIN_SET : GPIO_PIN_RESET);; `' }6 r2 \. }. v% i
  55.         HAL_Delay(1); // 稍微延时,确保时序正确
    $ e. u+ D9 ~: i2 U: h
  56.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);9 j5 m- Z( w# p$ L- b- v6 p* C$ \
  57.         HAL_Delay(1);2 [  a( x' u: |
  58.     }! X2 E' \1 P  z$ t
  59.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);& M  K$ l" c: \8 t  R
  60. }
    " M) I' Q7 J) q( o+ }

  61. 3 x9 f7 f7 u+ x: i' t; g
  62. / f& |& J  I% P3 A0 S- n
  63. // 读取一个字节3 e2 l, N3 A8 z: {( Y
  64. uint8_t IIC_ReadByte(uint8_t ack)
    ) w3 U6 E1 ~2 Y- ?5 B
  65. {
    % a* g+ A$ I6 ^
  66.     uint8_t byte = 0;. a- V1 P; n; r/ E! @
  67.    8 y5 p1 A2 J$ @8 T6 d) Y- M5 B; T
  68.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
    5 _1 ~0 a, G  ?  J( E
  69.     for (int8_t i = 7; i >= 0; i--)0 W" Y: z/ {* n( w4 H
  70.     {% y  G+ A& Y  U% u
  71.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);% W6 u$ I4 k) i  J6 o% m4 N0 ]
  72.         HAL_Delay(1); // 稍微延时,确保时序正确1 O  x0 W) p( K# j
  73.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    ' h+ S# F; u$ k
  74.         HAL_Delay(1);' n- y4 Y9 }% S7 I
  75.         byte |= (HAL_GPIO_ReadPin(IIC_SDA_PORT, IIC_SDA_PIN) << i);
    # \0 M' l' ~. P. f+ c
  76.     }( H! Q- U( w$ F$ p, }9 g
  77.    
    " s2 L5 @, i, }6 @' q- o
  78.     if (ack)
    8 w$ ]# k: h6 p1 ~
  79.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET); // 发送应答
    , @9 W0 y4 H9 i$ ~8 O! ?6 p  q
  80.     else2 t: l. _; |7 B
  81.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);   // 不发送应答* U: G7 h8 H# E* T1 G) o9 ^8 C
  82.    & h7 Q% G, O+ F! Q/ n: r
  83.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);% }4 q$ U0 k$ \+ n
  84.     HAL_Delay(1); // 稍微延时,确保时序正确
    % l! f7 S) c' _
  85.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);( i8 ~" m+ e4 a% Q4 s6 g
  86.     HAL_Delay(1);
    * j0 p' B, ]: U  y  X& r
  87.    
    " f' B/ R! p8 H' y: @6 L6 r6 j  |
  88.     return byte;+ T8 v3 y3 f( S& T9 s' Q% ^- C% o
  89. }
复制代码
$ ^5 t) F7 O% ?/ s9 G
例如IIC的启动信号为:SCL为高电平的时候,SDA从高电平转为低电平。, w! o5 F; o" [2 r% C; C

' x9 L. D9 {8 J8 b6 [0 N
IIC的结束信号为:在SCL线是高电平时,SDA线从低到高的跳变。4 O1 {0 p2 T% w0 ]9 p
  `% n" Q# c+ ?, r) I
因此使用这种方法可以模拟IIC时序完成通讯。/ a! B) Z' |/ |' h, V
" `: g1 F$ ~, C; Q$ v
但是这种方法的弊端也是非常明显的,需要占用CPU,其次这样子并不能确保I2C时序的正确性。所以无论是稳定性还是可移植性还是IIC的效率都欠妥。3 h# Y" Q. D) Q8 T. F: i

% V1 a  d! E4 R3 ~9 H' T% q
STM32中的硬件IIC   
& N8 D; i- H, b3 A* [STM32系列单片机提供了硬件IIC(Inter-Integrated Circuit)模块,用于支持IIC通信协议。硬件IIC通过专门的硬件模块实现了IIC协议的基本功能,包括起始信号、停止信号、时钟同步等,无需用户通过软件模拟实现。
  |6 k* q& S3 Z

* _7 h1 f2 [: h+ U5 r/ pSTM32硬件IIC优势:, a5 d9 A* |; J/ e) @% v
1.高效性: 硬件IIC使用专用硬件模块处理通信,不需要CPU直接参与,提高了通信效率,降低了对CPU的负担。& v4 ?8 S" n/ T. |: v
2.时序精确控制: 硬件IIC模块能够精确控制时序,确保通信的稳定性,避免了由于软件执行时间不确定性而引起的时序问题。
& E' T- h4 Z# N6 E- X9 G3.多主机模式支持: 硬件IIC模块通常支持多主机模式,能够轻松处理多个设备同时访问总线的情况。
9 J2 e# N: q& i: }0 c" z) w3 I4.易用性: 由于硬件IIC是芯片内置模块,使用起来相对简单,只需配置相应的寄存器和引脚即可。8 E) C1 P: y; |- P
5.占用资源少: 硬件IIC模块通常占用较少的资源,对于资源有限的嵌入式系统来说,是一种较为理想的选择。
3 P& K* j, N" T( _) `1 @8 w, z; \& C) ]' U6 O; u* g
微信图片_20240529192242.png , `5 w* M6 D2 C, z$ u6 a# X3 m

3 N2 Y4 J8 |8 J6 S0 s在CubeMX中配置好硬件IIC即可利用HAL库函数进行IIC通讯。
  1. static void MX_I2C1_Init(void)
    , a6 B2 a4 h8 E6 o5 h3 w" R
  2. {2 |9 e3 |: v* ~3 i( W
  3.   hi2c1.Instance = I2C1;
    : Y% ?$ C9 c" `9 b3 v( r
  4.   hi2c1.Init.ClockSpeed = 100000;
    ! m) L  h1 T6 Y/ C2 L" R
  5.   hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
    6 b# G6 N9 r1 p. d4 D& \
  6.   hi2c1.Init.OwnAddress1 = 0;, b4 x; |- e- y( q/ z7 m, P" E5 e% J
  7.   hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    & a; D/ l4 n3 t4 W8 \/ y( {" X: S
  8.   hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;/ ?7 }; v- u7 ]
  9.   hi2c1.Init.OwnAddress2 = 0;" R8 C9 ^* n6 ?$ v0 x
  10.   hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;+ C" T: x( G' d; `6 s1 B. n
  11.   hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;2 D$ c' W1 C6 d/ d4 E  k; [
  12.   HAL_I2C_Init(&hi2c1);
    ( D5 k& `' e- x4 Z
  13. }8 N2 p; d; P! _  h# l

  14. + k1 p6 s, m8 Y' B( Z. {

  15. / [0 B* j- q, f1 K
  16. uint8_t deviceAddress = 0x50;//设备地址  V5 \* d; |5 O9 G4 }
  17. uint8_t registerAddress = 0x00;//寄存器地址
    0 K' Q9 ?0 Y1 u" ]$ ?% e
  18. HAL_I2C_Master_Transmit(&hi2c1, deviceAddress, &registerAddress, 1, HAL_MAX_DELAY);
复制代码
5 T- r* }) N0 ]
调用CubeMX的初始化函数,之后就可以使用例如HAL_I2C_Master_Transmit,HAL_I2C_Master_Receive等函数来实现IIC通讯。
) s- q6 Q0 L" {! _
* l7 s. R4 U: q# ]8 r5 x" g4 S+ _  |5 ~' k
STM32硬件IIC缺点:
5 D  u7 D# q+ u5 P4 q; k, \& I1.资源占用: 相比软件IIC,硬件IIC模块可能会占用一定的硬件资源,因此在资源受限的系统中需要谨慎选择。( A& |. g( f/ T2 m
2.灵活性: 硬件IIC通常由芯片内部硬件模块实现,因此在一些特殊场景下可能缺乏一些灵活性,例如无法更改时序。( o2 l1 b+ G" F. N& }# G
3.部分限制: 不同型号的STM32芯片的硬件IIC模块可能存在一些差异,不同芯片的IO不一样,所以设计时需要谨慎检查。
$ L0 O, H: T: l+ T- ~' b; M9 [% T* A! m0 v, M
总体而言,STM32的硬件IIC是一种高效、稳定的IIC通信方式,特别适用于对性能要求较高的应用场景,同时在易用性和可靠性上有较大优势。在选择IIC通信方式时,可以根据具体需求权衡硬件IIC和软件IIC的优缺点。5 e3 p! A/ |7 L. n: P
- j4 y+ a8 @, X" D' C" H+ n5 T/ s

9 \8 O% }3 L+ O6 I9 b1 F* U1 C- u; U
转载自:电路小白( H2 J- x$ t0 P( ^8 ^3 f
如有侵权请联系删除
; J% k5 B  P7 q5 [+ B, i) S
# [$ @  w8 T8 `+ ~6 W1 Y
收藏 评论0 发布时间:2024-5-29 19:23

举报

0个回答

所属标签

相似分享

官网相关资源

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