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

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

[复制链接]
攻城狮Melo 发布时间:2024-5-29 19:23
IIC(Inter-Integrated Circuit)是一种常见的串行通信协议,广泛应用于各种嵌入式系统中,包括STM32单片机。在STM32中,IIC通信可以通过硬件IIC和软件IIC两种方式实现。本文将介绍IIC的基本原理,然后重点探讨STM32中硬件IIC和软件IIC的区别。" _3 \, O+ U/ d! f3 a4 t
% c9 \' \; z# R" \, _3 o. p% q
微信图片_20240529192252.png 6 h  ]) K9 S& W' t

4 c9 K% R1 E4 M7 Z3 D/ ~3 M) ]5 eIIC基本原理:IIC是由飞利浦(Philips)公司提出的一种串行通信协议,适用于在同一电缆上连接多个设备。它采用两根线进行通信,即SDA(数据线)和SCL(时钟线)。设备之间通过这两根线实现数据传输,其中SDA用于传输数据,SCL用于同步时钟。
! K: m' k. m1 v+ D+ B
3 ]6 E# D; @6 A  u" A, }6 `$ w% K$ m 微信图片_20240529192248.png
, P' K' m% `( G( i5 U0 `( P( Y

& s$ [$ e5 p: x- a. w' u一对IIC总线上面可以挂载多个设备并且多个设备之间有不同的地址,所以我们可以根据不同设备的地址来实现不同设备之间的通信。4 K" s- \; u; \6 W- q8 y

0 s, z( J# ?! K. {
软件IIC
% {+ E$ @4 Z% a# q在STM32中,软件IIC是一种通过程序控制GPIO口模拟实现IIC通信的方法。这种实现方式常用于一些资源有限的应用场景,或者在需要更灵活控制IIC通信时使用。' q% j" N6 d, b% w
# J" _7 R+ N9 U' P% q
微信图片_20240529192245.png
: w& @+ [  t/ M3 G2 [6 y

0 M5 h2 ~; v& y总而言之,软件IIC是利用GPIO的翻转,一个IO模拟SCL线,一个IO模拟SDA线实现IIC通信协议的实现。
4 t- c1 b  S, a/ G5 c  Y% |
" @  @' b! u( Q6 d3 i: P
软件IIC不需要对IO有特殊的要求,只需要两个普通的GPIO即可实现,因此较为方便也方便移植,不同设备只需要重写IIC的基本通讯即可。
% X% l: K! b( p/ ?- J* T) ^# S
  1. // 定义IIC的GPIO口和引脚
    + k# E! E$ x; j9 N& J" ]+ t
  2. #define IIC_SCL_PIN GPIO_PIN_6) A, I, W& K) J" A
  3. #define IIC_SCL_PORT GPIOB9 V! h, {) @8 o7 f. b6 a4 \# B2 j
  4. ; `- H) q7 h$ d3 j) ^$ f
  5. " [3 Q4 @& `% B" B
  6. #define IIC_SDA_PIN GPIO_PIN_97 ?: O: D* ?7 Z* s% Q
  7. #define IIC_SDA_PORT GPIOB; Z# W6 L0 d- D$ G# m

  8. % J6 F# K3 O# [
  9. ' W+ K; k2 L/ \, I1 k" L# B
  10. // 定义读写控制位# p+ ]0 E  M: a. [$ @+ g6 o0 g
  11. #define IIC_READ  1
    . H& g; A- i3 C0 v& a: }  m
  12. #define IIC_WRITE 0
    ! \. Q$ X. S" K( }4 T  N

  13. % r- Q6 w" v* R" Q9 E! x0 f
  14. , \  ^1 Y, E2 s  f
  15. // 定义函数
    4 U. O3 n, y/ C' Y
  16. void IIC_Start(void);
    0 f1 e. e/ D0 g/ N6 }. X* q5 H
  17. void IIC_Stop(void);7 v# S' q" G+ e/ @* W
  18. void IIC_SendByte(uint8_t byte);
    5 z; i( r% q: S$ J/ Z# Q3 Y# ]
  19. uint8_t IIC_ReadByte(uint8_t ack);
    8 L; C7 x9 @% H, r2 }

  20. 4 k/ Y6 F' M  ^( F+ I% P5 i% [  E
  21. * Y, x9 Z, D9 m7 @6 P
  22. - a; D3 G; F% l, O

  23. " @5 O% ?+ f4 q, [0 R
  24. // 启动IIC总线
    # o# v1 J5 X/ k# s0 x6 I
  25. void IIC_Start(void)3 E+ x( p3 o6 O; I) n
  26. {
    6 E0 N7 O  l8 n$ ]; {
  27.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);! B1 m/ z- T: o+ C8 |& |  J' w
  28.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);* j  R2 H0 W/ |& |9 B
  29.     HAL_Delay(2);  // 稍微延时,确保时序正确
    1 E7 c8 N# u& Z
  30.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);
    " }5 k# n8 G- ?3 E
  31.     HAL_Delay(2);2 q5 N' K+ [: O* k3 z% }
  32.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    ; _$ n7 Q* J; M/ j; b
  33. }& r; M. t& q, G3 @4 m. C5 L

  34. ' E# d  R# D( d2 s9 w6 `6 Z* P
  35. % Z& Y! c. R$ k
  36. // 结束IIC总线
    4 d5 B3 ?2 y* n- A7 O+ @8 U( X" u
  37. void IIC_Stop(void)( D4 {) i- q' c. `  E( V" q
  38. {5 ?8 T$ S3 W' s  g7 h. h  [+ O+ ^
  39.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);9 N7 G; d2 v4 ?" ~: ]
  40.     HAL_Delay(2);
    9 `2 k$ l0 [8 \& c
  41.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    $ x& N9 O0 O+ W) ^% \
  42.     HAL_Delay(2);
    5 z2 ~6 _5 a' V, k2 c2 s
  43.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
    + w- ~; o. v- l2 q) T$ r) f; C
  44.     HAL_Delay(2);
    8 r6 ]# y3 _) R1 F
  45. }
    / z! d/ X! f& n1 L
  46. : D- H1 J& a0 \- D5 X

  47. 1 ?* ^8 H' B1 a; [- a& H
  48. // 发送一个字节+ ]; X' K# [# {; @7 `
  49. void IIC_SendByte(uint8_t byte)
    $ b0 ~" e4 {/ ^+ S
  50. {- m) X: V' W3 g8 d$ D; M/ K
  51.     for (int8_t i = 7; i >= 0; i--)" B7 l! g! [1 m  j' b
  52.     {/ Y2 c) ~. }* y8 e- l7 f
  53.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    * g1 V9 ^( E7 N: v" G
  54.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, (byte & (1 << i)) ? GPIO_PIN_SET : GPIO_PIN_RESET);6 u9 V( t: I. T4 f7 K4 b( e
  55.         HAL_Delay(1); // 稍微延时,确保时序正确3 g* i, Q, E; @, ~
  56.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    . S% p: X2 q, B) f/ \5 h
  57.         HAL_Delay(1);/ |/ ]2 s% g' H* x+ A
  58.     }) g7 C! ^/ V  L# E
  59.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    $ e  }3 t  A& Y  M; ?5 s
  60. }
    5 K" y. J2 c: A9 u' B& B( v
  61. ; W1 d+ L4 a, A. r% u, \
  62. - l% t" U$ _. C) O
  63. // 读取一个字节& u) s: O; F) G* ?/ J* r, S$ N
  64. uint8_t IIC_ReadByte(uint8_t ack)
    5 I  K) N" L0 j
  65. {) J' p* ^8 }. f0 Q% n
  66.     uint8_t byte = 0;/ ^* S' n$ A  |/ p+ Q( d
  67.    
    , c1 n$ f& D7 q) U. b! E  p
  68.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);% ]0 H) G3 e0 r7 {4 M# d* @; k
  69.     for (int8_t i = 7; i >= 0; i--)
    7 N3 {+ @3 m' V& X
  70.     {" M8 |; i: ^6 n/ z
  71.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);- \6 B0 j% z) O' G( i. J' S# H# X6 Z
  72.         HAL_Delay(1); // 稍微延时,确保时序正确
    ( d$ R) U( p; P+ `
  73.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);) M) d5 Z, |( j  y. a7 ~
  74.         HAL_Delay(1);7 n9 l( ?6 k. |' O
  75.         byte |= (HAL_GPIO_ReadPin(IIC_SDA_PORT, IIC_SDA_PIN) << i);1 a' A2 y  @8 I3 X) A+ I, V
  76.     }3 I+ U; I$ }- _, G& C
  77.    
    / p8 e! c& V& o9 C9 W
  78.     if (ack)
    9 ]  s- V" s7 h+ s# K2 x
  79.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET); // 发送应答6 v; D! J- u0 |7 Q1 U
  80.     else* C2 d! p. W: j* e9 ~% Z
  81.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);   // 不发送应答2 l- |9 l! F& M2 Z2 i
  82.    
    6 _! k6 {5 u/ u' D& M3 w) ^
  83.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);1 |: L9 j2 X% f7 i; I3 x1 t
  84.     HAL_Delay(1); // 稍微延时,确保时序正确" A( O8 ?5 u: o1 S' U
  85.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);0 e6 ~- Q- J, s$ j6 K7 D
  86.     HAL_Delay(1);
    + I: C  B/ Z) [
  87.    9 K: t4 I9 l) S# C  u" n
  88.     return byte;
    , O5 P7 ^. u+ B5 Z& O! J
  89. }
复制代码
' W& r' t; N& ?  s9 X! F
例如IIC的启动信号为:SCL为高电平的时候,SDA从高电平转为低电平。
0 `% U/ f6 v' T4 _+ A0 f; p, J9 w
1 |8 ]7 _+ {& n: h9 G: r. ^8 p- Y
IIC的结束信号为:在SCL线是高电平时,SDA线从低到高的跳变。
9 m+ w- Y: U! p/ l3 B
. |7 B; t/ m' T% h2 I
因此使用这种方法可以模拟IIC时序完成通讯。& j& J; ~, N! F& d

+ H' h" E( S+ q$ R" t
但是这种方法的弊端也是非常明显的,需要占用CPU,其次这样子并不能确保I2C时序的正确性。所以无论是稳定性还是可移植性还是IIC的效率都欠妥。
3 N, N6 f, H; |3 n  b# U# K
$ i4 B3 \9 G# \  M2 w$ h; [) g( W& G
STM32中的硬件IIC   
, {/ H8 h: \9 z! g5 I  gSTM32系列单片机提供了硬件IIC(Inter-Integrated Circuit)模块,用于支持IIC通信协议。硬件IIC通过专门的硬件模块实现了IIC协议的基本功能,包括起始信号、停止信号、时钟同步等,无需用户通过软件模拟实现。
1 B" z" o/ Z; L+ }2 e

: ]9 h3 ]" }! d+ \7 BSTM32硬件IIC优势:
) v. c) s; v( M4 _* m# D1.高效性: 硬件IIC使用专用硬件模块处理通信,不需要CPU直接参与,提高了通信效率,降低了对CPU的负担。
6 t; Y8 s7 s7 X+ k
2.时序精确控制: 硬件IIC模块能够精确控制时序,确保通信的稳定性,避免了由于软件执行时间不确定性而引起的时序问题。
% K" L& t8 i. I- k3.多主机模式支持: 硬件IIC模块通常支持多主机模式,能够轻松处理多个设备同时访问总线的情况。
: J+ Q+ V: V: a4.易用性: 由于硬件IIC是芯片内置模块,使用起来相对简单,只需配置相应的寄存器和引脚即可。
2 `; Y, g3 n+ y* e* J, ]9 @/ [5.占用资源少: 硬件IIC模块通常占用较少的资源,对于资源有限的嵌入式系统来说,是一种较为理想的选择。
9 c+ H7 @2 u4 u; c+ C
; L' T$ u9 T( F! {
微信图片_20240529192242.png 3 [& b" X- N3 O, @6 v& k
& g9 p9 `5 q) \- O+ h
在CubeMX中配置好硬件IIC即可利用HAL库函数进行IIC通讯。
  1. static void MX_I2C1_Init(void)8 j: v- I4 S' X8 a. w( J
  2. {  }$ E" s" q& K; o: C8 Q
  3.   hi2c1.Instance = I2C1;8 V! z4 `0 B! B( t8 a$ L% K* ^
  4.   hi2c1.Init.ClockSpeed = 100000;$ h5 S9 f0 Z/ M
  5.   hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;4 T7 M( Y9 k% h. W! Y' F
  6.   hi2c1.Init.OwnAddress1 = 0;
    " C0 V0 O. c) O! @" {9 i$ e" t( i2 ]
  7.   hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;' c. L7 ]& r. N7 x
  8.   hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;5 [  K$ K# w0 H# B6 s3 v2 a! j
  9.   hi2c1.Init.OwnAddress2 = 0;
    7 m8 |: R+ H5 ?! m3 A
  10.   hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    ( L: M1 C. f. f  ^: ]
  11.   hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
      p  V# ~; F/ B! U+ x
  12.   HAL_I2C_Init(&hi2c1);* n8 _! Q% P1 ?: Q# P
  13. }
    + E% ]8 t* w8 n# V4 C' `9 l' Z

  14. 8 G8 g4 e6 K: o

  15. / F; e/ U5 ?( H; v& Q& L- c
  16. uint8_t deviceAddress = 0x50;//设备地址
    & |4 l' L5 h4 p) o
  17. uint8_t registerAddress = 0x00;//寄存器地址
    1 f, S7 v. ]" Q  ]# ]
  18. HAL_I2C_Master_Transmit(&hi2c1, deviceAddress, &registerAddress, 1, HAL_MAX_DELAY);
复制代码
1 @0 e4 u! \1 f5 p1 L8 z
调用CubeMX的初始化函数,之后就可以使用例如HAL_I2C_Master_Transmit,HAL_I2C_Master_Receive等函数来实现IIC通讯。
$ z& C5 F- r& W! S) K" u, Y0 e6 Z6 S* `8 }8 N3 b

0 e2 H  q( b  B2 j5 WSTM32硬件IIC缺点:
2 r9 w8 x! C9 d1 \# T1.资源占用: 相比软件IIC,硬件IIC模块可能会占用一定的硬件资源,因此在资源受限的系统中需要谨慎选择。
# z/ H( e% o2 ~" w4 W% `2.灵活性: 硬件IIC通常由芯片内部硬件模块实现,因此在一些特殊场景下可能缺乏一些灵活性,例如无法更改时序。$ ]$ L4 [7 |/ f; Y' Q& h# g4 J( H
3.部分限制: 不同型号的STM32芯片的硬件IIC模块可能存在一些差异,不同芯片的IO不一样,所以设计时需要谨慎检查。9 K# O7 B8 p( R

3 a( v# U1 L/ }$ _1 {) V总体而言,STM32的硬件IIC是一种高效、稳定的IIC通信方式,特别适用于对性能要求较高的应用场景,同时在易用性和可靠性上有较大优势。在选择IIC通信方式时,可以根据具体需求权衡硬件IIC和软件IIC的优缺点。
; x6 S' U) d- z/ w  ^- s, P% B
9 z, N4 J6 J. T8 ?7 R( Q) a7 ]: y: G8 o" \/ S8 F5 ]. y
/ c- X. D/ t' ^3 Z& p
转载自:电路小白/ _9 {7 I* A8 s0 l% I& ?
如有侵权请联系删除% }7 t; k& W5 n# {7 Y% O
& y( Y# ~) j# Q
赞 收藏 评论0 发布时间:2024-5-29 19:23

举报

0个回答

所属标签

相似技术帖

官网相关资源

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