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

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

[复制链接]
攻城狮Melo 发布时间:2024-5-29 19:23
IIC(Inter-Integrated Circuit)是一种常见的串行通信协议,广泛应用于各种嵌入式系统中,包括STM32单片机。在STM32中,IIC通信可以通过硬件IIC和软件IIC两种方式实现。本文将介绍IIC的基本原理,然后重点探讨STM32中硬件IIC和软件IIC的区别。8 D  J$ P( f( H! @* X9 Q6 I4 h3 P0 N

! ~7 w  w) B! q& @1 l  \+ G( }( @" V6 ~ 微信图片_20240529192252.png - h3 H' r' q/ }7 ^* D8 y( ?

4 d0 r& k; Z8 T9 l. T7 SIIC基本原理:IIC是由飞利浦(Philips)公司提出的一种串行通信协议,适用于在同一电缆上连接多个设备。它采用两根线进行通信,即SDA(数据线)和SCL(时钟线)。设备之间通过这两根线实现数据传输,其中SDA用于传输数据,SCL用于同步时钟。
2 \$ e% h4 f8 w* ^5 |& a
$ \% d; D0 d4 I2 [/ ~ 微信图片_20240529192248.png
. V% w' B+ [& p, U4 \0 S

" P- y) ?  x! y; x一对IIC总线上面可以挂载多个设备并且多个设备之间有不同的地址,所以我们可以根据不同设备的地址来实现不同设备之间的通信。! C# y3 x! [4 j5 y/ J: M

) B5 `  {8 D7 u
软件IIC" D' s: L5 O# L; c# j
在STM32中,软件IIC是一种通过程序控制GPIO口模拟实现IIC通信的方法。这种实现方式常用于一些资源有限的应用场景,或者在需要更灵活控制IIC通信时使用。' w- y/ c. x% V8 K* Y

$ J: B+ T: e5 L" m/ B5 q/ K" x 微信图片_20240529192245.png
5 s# u0 w0 i$ d- \% J7 k1 d9 D

0 b; g0 a/ Y$ b. |1 H( t2 u总而言之,软件IIC是利用GPIO的翻转,一个IO模拟SCL线,一个IO模拟SDA线实现IIC通信协议的实现。& Y" `! Y5 x  c1 g$ e$ V
" m* F, ^2 X7 X% E1 ]2 O/ g, x# Q
软件IIC不需要对IO有特殊的要求,只需要两个普通的GPIO即可实现,因此较为方便也方便移植,不同设备只需要重写IIC的基本通讯即可。/ K  O, k* s, `4 E+ o
  1. // 定义IIC的GPIO口和引脚
    / O+ O) e- j4 t3 q2 v8 B6 Q
  2. #define IIC_SCL_PIN GPIO_PIN_6' N0 n0 E% F& x( J: w
  3. #define IIC_SCL_PORT GPIOB4 }5 a9 q& I" ?7 W, _3 ?

  4. ! b6 p, I- K. w6 @# T
  5. 1 R, d9 H2 y  ~* J
  6. #define IIC_SDA_PIN GPIO_PIN_9' E; D& s  g8 F
  7. #define IIC_SDA_PORT GPIOB2 k% k9 d/ s! V7 a7 q& H, w1 U# n/ {

  8. , _8 C- \' ^2 X' }0 v: q
  9. ! h+ w9 S7 l8 v- H% o
  10. // 定义读写控制位
    8 k# ?; n: |# m  f2 f& O8 {/ w* y# J
  11. #define IIC_READ  1* g, i8 C9 _0 {: Q8 _  X7 d
  12. #define IIC_WRITE 01 k+ ~5 K3 l' h& j
  13. - O3 k$ I5 s/ ]+ Y3 M
  14. , U+ ]9 i7 t6 \" b: Q; Y5 j' ^
  15. // 定义函数
    ' i  N( b8 t" @) h" M! w: k3 p& @+ u
  16. void IIC_Start(void);6 C$ Q" P. g" R5 z. k5 C, u8 `3 f
  17. void IIC_Stop(void);5 P8 @0 m& p* c9 S
  18. void IIC_SendByte(uint8_t byte);
    + E/ T0 }5 T$ q' G7 p( G6 u
  19. uint8_t IIC_ReadByte(uint8_t ack);
    3 ?/ q2 ^3 ~0 c2 e+ {$ o

  20. ! z. u8 N9 b* _( d2 `# C

  21. ' e4 \" ?$ p- u
  22. 8 v9 Z# j8 B5 P3 m: ?" D

  23. & b! f0 X$ r8 R; C
  24. // 启动IIC总线
    & T7 g. f- [( D% h
  25. void IIC_Start(void)$ [& [- I+ w9 Y
  26. {( k/ q3 b! h4 m9 \* E4 Z
  27.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);1 {1 j+ k0 U. [
  28.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
      x( r5 h& q. j6 s; b. |) b7 ~0 N5 X
  29.     HAL_Delay(2);  // 稍微延时,确保时序正确" m* o, V5 P4 B8 F
  30.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);
    # _8 V- V9 l9 ~2 j& K& L
  31.     HAL_Delay(2);+ ~+ H2 R( Q) i& q# m: W, h
  32.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);% U: V- B+ t" l. M1 N0 b7 _
  33. }* Y" u# U! x- W6 D) Q- Z- |" ^
  34. 7 F+ P6 x* k9 ?/ V* \2 X
  35. 2 g; r2 ^8 |8 k9 e$ @
  36. // 结束IIC总线
    ' _3 [7 @  d6 y. s! {
  37. void IIC_Stop(void)
    ( i5 {( D) W- {; a. e, q' ^+ R
  38. {
    , |# ~8 T: ~+ R; ]3 J/ U
  39.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);
    : G" Z, \) P/ R4 _& Y& c
  40.     HAL_Delay(2);
    : S* O3 V) J7 u6 ?
  41.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    6 J+ b  P* \; ?% X
  42.     HAL_Delay(2);
    % F' d2 h- E) M! M  f- E9 ~0 G
  43.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
    " x  C. n) V6 ?1 ~
  44.     HAL_Delay(2);( o) c1 c( b2 R/ l% _8 A
  45. }
    5 t- m; P$ ~. l; Y/ `1 t" K
  46. ) h0 j$ U7 m. y6 o4 r
  47. # O3 L3 h6 Q8 B8 X' h
  48. // 发送一个字节- R+ M4 Z- k4 v# h3 ^
  49. void IIC_SendByte(uint8_t byte)9 x& b1 B. h+ N6 C9 {  G
  50. {
    0 h6 \+ K# ~6 W* {
  51.     for (int8_t i = 7; i >= 0; i--)
    ! m, ~8 f, q: e! E7 h$ F
  52.     {
    . Q. F& |, W' a2 \" r
  53.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    . Y& S9 x/ T( }$ h# Y' n" b; i
  54.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, (byte & (1 << i)) ? GPIO_PIN_SET : GPIO_PIN_RESET);- z: Q2 S- G' z
  55.         HAL_Delay(1); // 稍微延时,确保时序正确( M2 @5 T9 I5 {% r0 l; a
  56.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    , m9 @! e: N3 D: a7 q: p9 A
  57.         HAL_Delay(1);
    $ H* a# H) Y" Z0 _0 m
  58.     }
    ) }" K* N7 }  {$ X
  59.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);4 G& V% V" R6 w7 ]
  60. }
    , N' h, U6 n) ^4 I( ~; t( Z

  61. 2 T# ?* H: x. h) D4 s/ S9 e9 ~- d

  62. 9 R& c! s6 Z& i) S3 z  c
  63. // 读取一个字节
    0 H8 ?& i# l! I) L9 X7 K
  64. uint8_t IIC_ReadByte(uint8_t ack)
    : x  N: B4 w' ~# c( G; {! L
  65. {" f$ V6 c; o& i5 o
  66.     uint8_t byte = 0;1 ^+ U: o' _+ z( e1 X% s# D& Z
  67.    
      h1 i% `+ c4 g% [. N% V0 p
  68.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
    3 b5 c' u  ]4 Q4 z& l
  69.     for (int8_t i = 7; i >= 0; i--)7 L) k$ f- h1 M; l2 a8 V4 e9 {+ N
  70.     {
    0 B. p6 G9 y% c; \
  71.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);& L/ \7 s4 N$ n, k/ N3 |1 [: G: y
  72.         HAL_Delay(1); // 稍微延时,确保时序正确
    8 q$ D: g9 u/ i7 ?1 c
  73.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    3 A  _$ x6 a# c) `, W% r
  74.         HAL_Delay(1);
    + u& \6 K8 ]; }- |1 a
  75.         byte |= (HAL_GPIO_ReadPin(IIC_SDA_PORT, IIC_SDA_PIN) << i);
    9 q# d9 [% |2 H6 n% A( f
  76.     }
    , Q9 v( H2 m) J
  77.    
    2 W6 ^: ]0 y& T1 q$ ~$ r8 Z4 L6 c
  78.     if (ack)
      R) G( z( P" P1 H8 P
  79.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET); // 发送应答; f+ ~6 _, g- P4 f
  80.     else8 T) P& O6 n" Q) C. m/ O
  81.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);   // 不发送应答0 u; k* z# G2 L1 f3 D: C+ q
  82.    , i+ j& c- h0 e7 W% s
  83.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);4 ?. y% Q) x0 _6 Q+ U1 l' A& s
  84.     HAL_Delay(1); // 稍微延时,确保时序正确9 v" G0 m0 ]2 @: I. q8 L
  85.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    % U6 q2 {- q! j* p$ ^1 R0 l
  86.     HAL_Delay(1);
    ; D. z: E2 k& y% x
  87.    : N2 X9 ^" X, X; K8 a! T: Z
  88.     return byte;- E& J7 X6 M$ g) R+ y
  89. }
复制代码
( H- m2 }5 d: f' X4 I
例如IIC的启动信号为:SCL为高电平的时候,SDA从高电平转为低电平。% ~: h! [' Z; u4 _9 e

. }; a% h4 W# Q4 f) P$ P
IIC的结束信号为:在SCL线是高电平时,SDA线从低到高的跳变。; p. j0 g2 V& J* q

( g& G7 Q) P) H2 ?
因此使用这种方法可以模拟IIC时序完成通讯。
- z  H6 E) X; j3 C0 h6 S3 p
6 X, z. z5 P/ _. E% I2 g
但是这种方法的弊端也是非常明显的,需要占用CPU,其次这样子并不能确保I2C时序的正确性。所以无论是稳定性还是可移植性还是IIC的效率都欠妥。
4 O  e7 A+ m1 [3 V% i6 W- J0 _# Z, x, m$ X' D6 x- f
STM32中的硬件IIC    3 P5 J: w8 e0 f/ w. f
STM32系列单片机提供了硬件IIC(Inter-Integrated Circuit)模块,用于支持IIC通信协议。硬件IIC通过专门的硬件模块实现了IIC协议的基本功能,包括起始信号、停止信号、时钟同步等,无需用户通过软件模拟实现。
, {  d* U9 ~7 L5 x+ z/ v& g
! R4 k) K% o, D) [7 E8 V+ m, \# N
STM32硬件IIC优势:
; @9 J9 ~, s7 {8 e6 z2 D0 Y* `) r1.高效性: 硬件IIC使用专用硬件模块处理通信,不需要CPU直接参与,提高了通信效率,降低了对CPU的负担。
  L: B4 R/ m( j! Q4 C/ C3 P8 s, c
2.时序精确控制: 硬件IIC模块能够精确控制时序,确保通信的稳定性,避免了由于软件执行时间不确定性而引起的时序问题。, d. M4 t& \3 c6 `+ F
3.多主机模式支持: 硬件IIC模块通常支持多主机模式,能够轻松处理多个设备同时访问总线的情况。
, m# X3 Y. G7 W  o1 W! p' \4.易用性: 由于硬件IIC是芯片内置模块,使用起来相对简单,只需配置相应的寄存器和引脚即可。1 @* Q( w+ R+ z
5.占用资源少: 硬件IIC模块通常占用较少的资源,对于资源有限的嵌入式系统来说,是一种较为理想的选择。
/ R" e" B# h/ s; g. k0 x( C0 R9 S, ?6 m% O8 X6 n
微信图片_20240529192242.png
/ S+ N5 i* o% N
0 P, T- @3 ^% p3 K( x在CubeMX中配置好硬件IIC即可利用HAL库函数进行IIC通讯。
  1. static void MX_I2C1_Init(void)
    ( d. o8 i- I+ b1 a8 g) g
  2. {
    " U  r3 G" ?7 y6 t" n- |' V
  3.   hi2c1.Instance = I2C1;8 P- @3 C9 w) x" @4 d2 A
  4.   hi2c1.Init.ClockSpeed = 100000;8 j$ o5 d! b3 j1 X, R1 ^
  5.   hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;* i, v* k. ~- \$ ^  |
  6.   hi2c1.Init.OwnAddress1 = 0;
    4 X9 _3 R, x; {2 d
  7.   hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;  S# G* ?8 q% E0 ^5 u
  8.   hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    ' h& ~; J+ H2 X. H2 U, S
  9.   hi2c1.Init.OwnAddress2 = 0;
    ) T+ d9 ~! x/ }( n" e, L
  10.   hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    3 g# e6 w1 O% A1 z
  11.   hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    ! \" `8 S6 h: D1 E/ h2 ?" D
  12.   HAL_I2C_Init(&hi2c1);
    5 Y# O. H. ~3 }  G$ O
  13. }$ v% c4 l% l% S$ R7 j. s

  14. 2 O" l3 [3 p$ j/ }1 u* N

  15. 0 X& C0 W% l- m2 O/ t* ?
  16. uint8_t deviceAddress = 0x50;//设备地址
    6 j7 E% I3 V) F2 t5 _& I2 u
  17. uint8_t registerAddress = 0x00;//寄存器地址
    7 C+ _' G+ d& a+ s) z' P' }3 N6 W
  18. HAL_I2C_Master_Transmit(&hi2c1, deviceAddress, &registerAddress, 1, HAL_MAX_DELAY);
复制代码

4 k; R8 o% p4 a" `1 }0 X调用CubeMX的初始化函数,之后就可以使用例如HAL_I2C_Master_Transmit,HAL_I2C_Master_Receive等函数来实现IIC通讯。
! V& W' ?# _! P  Y3 B* U0 j8 H$ e$ M$ ?3 ?% A5 V% e5 t6 |  s0 q
" o% J( N- p1 A! U! N
STM32硬件IIC缺点:$ W5 L" x8 I% n. [7 h* q
1.资源占用: 相比软件IIC,硬件IIC模块可能会占用一定的硬件资源,因此在资源受限的系统中需要谨慎选择。
- S& |8 B6 A1 O" v- x5 e2.灵活性: 硬件IIC通常由芯片内部硬件模块实现,因此在一些特殊场景下可能缺乏一些灵活性,例如无法更改时序。
5 f( d! l7 y! }9 X3.部分限制: 不同型号的STM32芯片的硬件IIC模块可能存在一些差异,不同芯片的IO不一样,所以设计时需要谨慎检查。7 d5 s0 F7 Q: ^/ d5 o* @* j4 g
4 o% I/ q: D9 O; u
总体而言,STM32的硬件IIC是一种高效、稳定的IIC通信方式,特别适用于对性能要求较高的应用场景,同时在易用性和可靠性上有较大优势。在选择IIC通信方式时,可以根据具体需求权衡硬件IIC和软件IIC的优缺点。7 Y4 X; _$ Q" t; @5 o
- i! Q# t. h; E2 a; s/ Q. e- Q
' A  G- m0 k6 V4 e# V

, E& e/ n/ c. j( P转载自:电路小白
/ p  v% }2 B1 b如有侵权请联系删除: V' ^# Q  o) y' M( V( o
3 w7 i& {( c! h* g
收藏 评论0 发布时间:2024-5-29 19:23

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版