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

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

[复制链接]
攻城狮Melo 发布时间:2024-5-29 19:23
IIC(Inter-Integrated Circuit)是一种常见的串行通信协议,广泛应用于各种嵌入式系统中,包括STM32单片机。在STM32中,IIC通信可以通过硬件IIC和软件IIC两种方式实现。本文将介绍IIC的基本原理,然后重点探讨STM32中硬件IIC和软件IIC的区别。4 r8 T/ f3 Z1 p7 W

9 w* c# c+ k+ ^: M5 d+ K7 P! s 微信图片_20240529192252.png & l7 [+ S1 g! \$ Q9 C

" Q. e1 ]1 j  A3 WIIC基本原理:IIC是由飞利浦(Philips)公司提出的一种串行通信协议,适用于在同一电缆上连接多个设备。它采用两根线进行通信,即SDA(数据线)和SCL(时钟线)。设备之间通过这两根线实现数据传输,其中SDA用于传输数据,SCL用于同步时钟。
& D% {- I. E  o' F2 ]9 E3 e, i" U; G
微信图片_20240529192248.png
# y1 N" b& W9 ~- w% @

; f: j. b9 y6 k一对IIC总线上面可以挂载多个设备并且多个设备之间有不同的地址,所以我们可以根据不同设备的地址来实现不同设备之间的通信。' U6 ]) w9 ^# p7 x
- d; `& i2 M6 W
软件IIC
7 F. p2 [3 a" X- [3 e; L% r在STM32中,软件IIC是一种通过程序控制GPIO口模拟实现IIC通信的方法。这种实现方式常用于一些资源有限的应用场景,或者在需要更灵活控制IIC通信时使用。1 k9 c1 c4 U6 ]3 U0 u( }

) {" d9 T. v- @8 N# r/ \2 C) | 微信图片_20240529192245.png ) s/ ^1 ]; n" v+ u4 }4 H0 z

* l$ p9 R5 {; X0 Y& p2 s总而言之,软件IIC是利用GPIO的翻转,一个IO模拟SCL线,一个IO模拟SDA线实现IIC通信协议的实现。2 _7 t  F: L3 T$ ]1 O- i# _

  O1 ?$ ^* Y, N  w: P
软件IIC不需要对IO有特殊的要求,只需要两个普通的GPIO即可实现,因此较为方便也方便移植,不同设备只需要重写IIC的基本通讯即可。# v9 N% A0 M) V+ u  `" L
  1. // 定义IIC的GPIO口和引脚
    * Q6 y0 S; h3 S0 d
  2. #define IIC_SCL_PIN GPIO_PIN_69 R1 ?+ b1 l* a' c- h! w
  3. #define IIC_SCL_PORT GPIOB
    % e9 k* E& W) \* {- J* _, m6 {% P4 s

  4. ; j- f/ r9 L- |4 l

  5. & z( ]" c" {& p
  6. #define IIC_SDA_PIN GPIO_PIN_9/ L" `" {6 ^. [  ~- J
  7. #define IIC_SDA_PORT GPIOB0 y/ {. O& C' }5 X$ M2 {7 Y6 ]
  8. 7 O) L. ]- ^; y* i

  9. & H+ N5 R* H' u% Q+ g+ \" X9 ]9 y
  10. // 定义读写控制位
    $ @7 x& B: j/ Z% q; w+ |
  11. #define IIC_READ  1/ u1 A9 V2 D" }9 f$ p
  12. #define IIC_WRITE 0
    4 a0 {4 E6 y; U' |

  13. , H; d* K; O" u& w1 o  n7 f, e, R

  14. 2 G; R) l; [2 M" C% A  y
  15. // 定义函数
    6 J" k, I6 J9 t6 M) E* v
  16. void IIC_Start(void);
    ! d% L0 s6 b/ @! `; g; g
  17. void IIC_Stop(void);
    0 Y& J4 O9 J' R' A5 i/ ^
  18. void IIC_SendByte(uint8_t byte);
    0 T8 Q0 M& o# ^* X* d
  19. uint8_t IIC_ReadByte(uint8_t ack);
    5 T; \2 g, R8 c6 _% v
  20. $ n* s% E9 A% V) U6 a7 b1 p+ P
  21. ) ~4 t. W* l- u: ?, [" O+ X" d
  22. + A2 e3 w" x* a# L  A

  23. ' X. M: Q( R0 P( |/ v
  24. // 启动IIC总线
    " r% a2 Z0 E, m( C& l' Y) `
  25. void IIC_Start(void)1 d) r& S3 @2 {8 x
  26. {9 ?( ~, s2 z/ W5 X4 t! X; g
  27.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);; @  i4 e5 u5 ]5 q& y9 B4 b
  28.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);$ ~/ i9 l3 \4 J$ c% A# Y; l0 d
  29.     HAL_Delay(2);  // 稍微延时,确保时序正确; A) G3 }, F! `0 S9 J  x  U
  30.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);8 @6 T3 W5 B4 W) e. h
  31.     HAL_Delay(2);! D; D4 e+ G- T8 m! d
  32.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);5 @) B" a6 _1 r- R  \. _3 `5 `/ f
  33. }
    7 `6 r' |$ L) D* V% R5 g

  34. ; ^; m- b2 D' v1 A$ L" X! F  P
  35. 3 z# v# Y. V. G/ j( H& c8 e9 X4 s
  36. // 结束IIC总线
    2 y$ t: e9 n, ]. D& {: m
  37. void IIC_Stop(void)$ s4 A8 t- Y7 _9 R; U% R# I6 r
  38. {
      F/ d( O. X' h' Q- i8 \
  39.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);
    : O7 @$ I* l/ X" U# U
  40.     HAL_Delay(2);
    ( p) p, T6 Q* ~+ k
  41.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);6 G. a! n. i. w7 K0 y6 C
  42.     HAL_Delay(2);
    7 H  _3 B  }5 ]; `4 l
  43.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);+ h6 {% [' q9 s0 e) A
  44.     HAL_Delay(2);
    % h" i  n' y* Z0 F/ v
  45. }" U% W6 R/ s) q6 p4 {8 I/ R8 t

  46. 4 J9 R# L) f8 ?% O9 t$ J* ]

  47. 4 ^$ m9 l- M. |7 I2 H, a
  48. // 发送一个字节* n: p+ o. ^! A/ u4 a1 F( [4 e
  49. void IIC_SendByte(uint8_t byte)3 c' L; W/ V) k! z: s0 M( c! x
  50. {
      D+ N# n% z% J; ?8 q
  51.     for (int8_t i = 7; i >= 0; i--)
    : [! X$ j  F3 \* V$ o
  52.     {3 ^; q* s' o( ^3 y# E
  53.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);, v, g0 J  G4 ^7 z( D9 S
  54.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, (byte & (1 << i)) ? GPIO_PIN_SET : GPIO_PIN_RESET);( z! N% h; `. L3 L0 z3 \! Y/ H
  55.         HAL_Delay(1); // 稍微延时,确保时序正确9 j) r8 A' T+ |: T
  56.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);* s! Y0 q* u1 P
  57.         HAL_Delay(1);: x4 h2 w7 _5 ]2 D
  58.     }0 w9 w: x6 k+ n$ G' [, s% u) Z
  59.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    * J% B8 k- R. ^% z- {5 W/ \
  60. }
    / s: t2 P: W4 T$ g9 i' I& i

  61.   U% O2 H! R9 V3 M( S1 q. H( u5 L

  62. ' F- w' n* J' B
  63. // 读取一个字节
    1 f! t0 o! @/ R1 V' U3 O
  64. uint8_t IIC_ReadByte(uint8_t ack)
    . C( x! M! B( p
  65. {+ {3 z2 D# g2 r6 ^
  66.     uint8_t byte = 0;
    " j. n/ R3 Z  V! C2 ]9 x
  67.    & n6 t; [( a8 O3 H; S
  68.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);7 s) U7 u( i' j- }! S  q& F$ F! X" m
  69.     for (int8_t i = 7; i >= 0; i--)
    ( W  Y. A# C/ R. r9 h
  70.     {
    * p2 B; P8 P( Y0 A" w. M: W
  71.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);- D  z6 t( Z: s
  72.         HAL_Delay(1); // 稍微延时,确保时序正确
      ]8 C2 |; W* Q, \* ^/ N5 F
  73.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    % O4 z" f4 ~, I) U7 j
  74.         HAL_Delay(1);
    : }9 ?: N3 `- a8 ^  |" B
  75.         byte |= (HAL_GPIO_ReadPin(IIC_SDA_PORT, IIC_SDA_PIN) << i);: o0 O8 B" P( X  b6 y2 i
  76.     }" `$ P2 r2 }; k# Y
  77.    
    9 j# I- T$ }+ @9 ^: m& K0 l
  78.     if (ack)
    * X2 g6 ~6 p" n- \5 ?+ e0 ?3 z5 b
  79.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET); // 发送应答7 e; n1 S: P: [: H7 ]9 {
  80.     else
    9 H( e0 C! H6 P
  81.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);   // 不发送应答
    ; U. {% A, E2 u8 q5 T7 f( t' Q
  82.    
    " W' _( R& [2 Q. m3 P
  83.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    ) ^6 L  }. C& C7 F0 v0 W# E  S
  84.     HAL_Delay(1); // 稍微延时,确保时序正确
    % `& a% v/ h3 Z: l$ q9 W* `
  85.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);) C6 f' i5 }, V& U1 q3 A
  86.     HAL_Delay(1);; v0 V, l' |- Y) q1 Q
  87.    0 @$ k3 p; f% b* Y2 l
  88.     return byte;
    2 I4 }$ j& j, b2 E& X$ g
  89. }
复制代码

: i# }0 p2 |9 O9 `/ c例如IIC的启动信号为:SCL为高电平的时候,SDA从高电平转为低电平。
2 i, i: \8 f  j9 z2 q* f/ Q' ^( V1 R/ l3 y9 C' J8 q) p, E& g
IIC的结束信号为:在SCL线是高电平时,SDA线从低到高的跳变。* o2 O* l5 q- K) ]4 x5 N1 L

& P0 z- Z! |6 @
因此使用这种方法可以模拟IIC时序完成通讯。+ f- a2 j) w9 m0 L2 ?

) m& u3 k/ y# U( E: k: B- ?2 k
但是这种方法的弊端也是非常明显的,需要占用CPU,其次这样子并不能确保I2C时序的正确性。所以无论是稳定性还是可移植性还是IIC的效率都欠妥。
% P- o. l" F4 q: w* T4 O  e+ Y" q3 v4 W( w+ O) w8 q
STM32中的硬件IIC    ( Y7 ?* ^8 ~; y. {! K5 R. V- Q
STM32系列单片机提供了硬件IIC(Inter-Integrated Circuit)模块,用于支持IIC通信协议。硬件IIC通过专门的硬件模块实现了IIC协议的基本功能,包括起始信号、停止信号、时钟同步等,无需用户通过软件模拟实现。
, y4 W/ r4 D- U' j$ F/ X

! ^+ [9 ^$ f' T1 y; \STM32硬件IIC优势:
4 [# w7 s- d2 |1.高效性: 硬件IIC使用专用硬件模块处理通信,不需要CPU直接参与,提高了通信效率,降低了对CPU的负担。( X& f6 J4 z6 D. D; {% B  Z
2.时序精确控制: 硬件IIC模块能够精确控制时序,确保通信的稳定性,避免了由于软件执行时间不确定性而引起的时序问题。
: {5 A: S# l9 n2 t; i2 S3.多主机模式支持: 硬件IIC模块通常支持多主机模式,能够轻松处理多个设备同时访问总线的情况。
# r) M. S1 z" e# w, n4.易用性: 由于硬件IIC是芯片内置模块,使用起来相对简单,只需配置相应的寄存器和引脚即可。+ P  ^$ W( _2 @
5.占用资源少: 硬件IIC模块通常占用较少的资源,对于资源有限的嵌入式系统来说,是一种较为理想的选择。5 R  v& ~1 Y8 x* S/ C2 _

) T7 B" a2 {0 M/ E6 Q# I, c7 c
微信图片_20240529192242.png
! p5 N) A5 x3 l9 f* D% i9 g* |' I, F* p3 X$ o2 s
在CubeMX中配置好硬件IIC即可利用HAL库函数进行IIC通讯。
  1. static void MX_I2C1_Init(void)
    ' G$ T  t8 [; m& v* X
  2. {
    9 O: y. i" Z. i5 j0 j6 k9 d
  3.   hi2c1.Instance = I2C1;
    " o/ F# K& ]3 v
  4.   hi2c1.Init.ClockSpeed = 100000;) k; E* _/ C0 ]
  5.   hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;% C9 y% J& R+ r# Y; n
  6.   hi2c1.Init.OwnAddress1 = 0;
    " V; O, B2 K/ b
  7.   hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;" Q% n: i+ X! l6 h# A' k& b, D2 D
  8.   hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;  N8 r$ [$ \+ c7 @" H3 {
  9.   hi2c1.Init.OwnAddress2 = 0;
    9 J: A6 Y3 }  S* A( m
  10.   hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    - R$ S' Y% H6 K) [* D9 u
  11.   hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    2 w0 ?% I2 K- ^% d
  12.   HAL_I2C_Init(&hi2c1);
    ) J0 ~: I/ r1 H2 d5 O/ t
  13. }: I: w) s0 h3 V8 t' R

  14. + K* e% w! E: }/ I4 p; a0 ]+ r

  15. ; J+ o. A* k- {6 h1 N# I& C
  16. uint8_t deviceAddress = 0x50;//设备地址4 g. V! D5 I0 L& l
  17. uint8_t registerAddress = 0x00;//寄存器地址# Q( t0 j) U& Y8 J6 w: \( j
  18. HAL_I2C_Master_Transmit(&hi2c1, deviceAddress, &registerAddress, 1, HAL_MAX_DELAY);
复制代码

- s/ Q  [9 c( C! q& w& t9 A调用CubeMX的初始化函数,之后就可以使用例如HAL_I2C_Master_Transmit,HAL_I2C_Master_Receive等函数来实现IIC通讯。
; i# s8 L3 q) _5 j& R  Y7 A
. ^' t- e, z, a4 P* ~5 \# G3 G! w7 x7 \, c: ^$ T
STM32硬件IIC缺点:
2 n# u3 R, W. Z1.资源占用: 相比软件IIC,硬件IIC模块可能会占用一定的硬件资源,因此在资源受限的系统中需要谨慎选择。' n' i- Q6 P' Z  c; x
2.灵活性: 硬件IIC通常由芯片内部硬件模块实现,因此在一些特殊场景下可能缺乏一些灵活性,例如无法更改时序。
( U3 b% \! W: r3.部分限制: 不同型号的STM32芯片的硬件IIC模块可能存在一些差异,不同芯片的IO不一样,所以设计时需要谨慎检查。
5 \# [+ K1 O" f4 s7 x% M
0 V  J$ {  D  L总体而言,STM32的硬件IIC是一种高效、稳定的IIC通信方式,特别适用于对性能要求较高的应用场景,同时在易用性和可靠性上有较大优势。在选择IIC通信方式时,可以根据具体需求权衡硬件IIC和软件IIC的优缺点。, q' |+ c$ p  y' s5 E

" h  e) x/ @0 z) u1 E) o8 i" T! a" s6 f9 \. S; ~2 {
7 |- |* k: @0 Q9 u
转载自:电路小白
6 z: h3 j" N% c8 H如有侵权请联系删除& ]7 O7 L# v# A) h
( m& p) p  t/ u" P$ G3 S4 _8 k
收藏 评论0 发布时间:2024-5-29 19:23

举报

0个回答

所属标签

相似分享

官网相关资源

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