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

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

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

% x1 i7 ~* a4 \$ X% [; H0 z 微信图片_20240529192252.png $ W: G( `1 N0 s7 d# u

: D4 e) Y1 I3 w' `- kIIC基本原理:IIC是由飞利浦(Philips)公司提出的一种串行通信协议,适用于在同一电缆上连接多个设备。它采用两根线进行通信,即SDA(数据线)和SCL(时钟线)。设备之间通过这两根线实现数据传输,其中SDA用于传输数据,SCL用于同步时钟。
% u" F* g* F$ N- T, J5 a" s# s2 k( `* g2 _: G8 Q6 J
微信图片_20240529192248.png # k- t/ G% B2 {8 t2 ^+ C2 E" l
& N- X2 P$ r0 K6 R. {9 ~1 R" g
一对IIC总线上面可以挂载多个设备并且多个设备之间有不同的地址,所以我们可以根据不同设备的地址来实现不同设备之间的通信。& \* ~) z$ n/ o" [' q' G

5 G# `+ t9 ?/ _  a) A
软件IIC
6 J# b4 ?# x: D  C在STM32中,软件IIC是一种通过程序控制GPIO口模拟实现IIC通信的方法。这种实现方式常用于一些资源有限的应用场景,或者在需要更灵活控制IIC通信时使用。
( i+ m2 D7 }% c6 ~4 l
$ K% K9 ~3 @" {2 G3 `# o% ]; | 微信图片_20240529192245.png / f' f( f9 t4 r$ E

& ^1 S* \9 |) |$ E. N9 f8 Y  T总而言之,软件IIC是利用GPIO的翻转,一个IO模拟SCL线,一个IO模拟SDA线实现IIC通信协议的实现。5 M6 X# S" D5 s/ m- x

2 H$ E0 h1 K( L/ u3 ^
软件IIC不需要对IO有特殊的要求,只需要两个普通的GPIO即可实现,因此较为方便也方便移植,不同设备只需要重写IIC的基本通讯即可。! V* C* m4 f/ I: k6 ]
  1. // 定义IIC的GPIO口和引脚1 j6 s" x* w$ Y7 v+ E
  2. #define IIC_SCL_PIN GPIO_PIN_6) i1 {4 _+ _& B8 G$ g. |2 \" m0 U
  3. #define IIC_SCL_PORT GPIOB( m+ s; p3 e* c, k. F# Q

  4. 0 l; n# M. D8 A; o& h" v

  5. & F7 G2 R3 p4 c) L/ B
  6. #define IIC_SDA_PIN GPIO_PIN_9
    , u: x6 s; i/ r! n" v
  7. #define IIC_SDA_PORT GPIOB6 z0 @. a$ A5 A- C/ T3 |) f/ y

  8. 0 V& A7 @) ~5 }- a+ C) b! A# j1 e
  9. 2 j: D# J+ F4 p( W
  10. // 定义读写控制位
    ) b7 V/ |% R0 b  p, y
  11. #define IIC_READ  11 }6 m4 a, u& z& N9 T
  12. #define IIC_WRITE 0
    ) r; Q  e' O: c$ _! [7 O/ ~) P
  13. - ~/ @3 ^7 t( ]& V

  14. + S4 z% c& Q7 F& }
  15. // 定义函数! j8 H) z& `5 n4 P& L8 s. m! S
  16. void IIC_Start(void);' k; t3 ^2 z6 p# L
  17. void IIC_Stop(void);* ~% f9 B5 l6 x. x2 w0 E/ ^% z
  18. void IIC_SendByte(uint8_t byte);* M4 @% |" G: o: u2 f# V/ x5 ^
  19. uint8_t IIC_ReadByte(uint8_t ack);
    ' v' f$ b: Y2 L, U) T- i

  20. ) a1 w8 O. J- G. @3 T- z% [

  21. - [; Q3 H$ D( L$ d; g/ A& \
  22. ( \! I3 O- J7 b0 g8 a& c

  23. ) j" Z* C% l; ^) {2 w: T
  24. // 启动IIC总线
    % A. V1 e" B6 }
  25. void IIC_Start(void)
    ( z, s* Q9 B+ L; p* V1 |
  26. {$ F0 i3 x. k- j- ?
  27.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);; O+ Y- @/ I. M3 J! ~
  28.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);: h! S4 c! l/ f2 G
  29.     HAL_Delay(2);  // 稍微延时,确保时序正确
    ) \/ h0 x6 i' J; l# a  h
  30.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);+ R7 m  z: v  t+ T
  31.     HAL_Delay(2);; z, q5 z" ~; i- f- K: L. C9 `9 I
  32.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);' E1 w0 T0 X/ k- m7 r
  33. }) |! c: |5 l4 y5 c3 T4 N$ T* w

  34.   l8 W3 l- m' d9 C8 }
  35. 3 [/ y$ N4 F6 d, D: e  `
  36. // 结束IIC总线3 G+ g  N% \) |3 t
  37. void IIC_Stop(void)( q% q# a4 ?( |; w* L- C; k) M7 z5 n
  38. {$ R3 w. N( I3 Y9 a! w- g7 K
  39.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);
    - r8 L; I* c$ W+ @5 _
  40.     HAL_Delay(2);/ f; k6 U+ R; D8 C* d( e; S6 P
  41.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    * b2 d6 k: y1 T( w% ~7 y/ x1 n
  42.     HAL_Delay(2);
    0 y2 B" w( s5 v; k+ f" d
  43.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);  Q5 X. V3 W) m. p. _* W
  44.     HAL_Delay(2);
    7 U. e1 Q2 D$ ^# `. p9 n& _
  45. }* E* g/ V/ C" y7 B
  46. ! ^5 `( O& [+ r0 f' F
  47. - }/ `, U7 g4 ?! l
  48. // 发送一个字节
    5 G! O: j. ^* ~( l
  49. void IIC_SendByte(uint8_t byte)
    , q9 d! D1 D2 a( ?- p
  50. {! q+ R) z3 X) ~3 i
  51.     for (int8_t i = 7; i >= 0; i--)0 V7 G8 R2 R, \9 @( d* u
  52.     {7 O& O+ Q5 d  D1 p
  53.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    / N& u2 T5 t0 r+ x; X9 M
  54.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, (byte & (1 << i)) ? GPIO_PIN_SET : GPIO_PIN_RESET);  I! p# I; ^) f/ S4 y
  55.         HAL_Delay(1); // 稍微延时,确保时序正确+ U3 b2 s6 ]6 ^+ X4 d) z9 |
  56.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    ; B+ d* M& Q8 E7 J7 z3 D, H9 w
  57.         HAL_Delay(1);+ k5 h! ~# A6 m$ M  ~
  58.     }
    - S: I4 @' S3 d+ a+ w$ ?4 \3 V
  59.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    ; C" _" ^' X1 ^- o, K3 d
  60. }
    1 F5 `2 Q! y; ]& B$ p

  61. " F9 e6 Y: G0 f. y3 s% G- H$ F2 E
  62. : E! R% B% |& K  i& C
  63. // 读取一个字节
    + y, }+ Q' U" X. _" b( N, N+ O
  64. uint8_t IIC_ReadByte(uint8_t ack)
    " n' j8 F3 L* @& l, B
  65. {
    7 x* s9 [5 a% j: c# r( Q
  66.     uint8_t byte = 0;: f" d/ T4 c% \1 {6 C; u( |% g
  67.    7 o9 }5 e. Y- N7 k2 @; ^
  68.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
    ; |8 @9 C: o+ D4 C, j: L
  69.     for (int8_t i = 7; i >= 0; i--)" s/ ]$ m& d. p5 X- p7 ]
  70.     {6 A6 c1 I7 _) Z' S
  71.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    6 z1 C1 N6 E' d5 [/ s; O4 O" C
  72.         HAL_Delay(1); // 稍微延时,确保时序正确5 ]: ]: R* @; t# {9 q  ]6 L7 B
  73.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);9 k4 N1 w" ]4 p
  74.         HAL_Delay(1);
    & g# Y' P3 U1 @0 G# @
  75.         byte |= (HAL_GPIO_ReadPin(IIC_SDA_PORT, IIC_SDA_PIN) << i);
    - D' \0 S$ T- k" J& c; e& }
  76.     }
    - |0 r" O. |1 @7 B( Q1 @3 V
  77.    
    & b/ H+ h  n4 b. |/ U: g" U
  78.     if (ack)( @% ^! @5 x. \( d
  79.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET); // 发送应答
    5 o5 g0 ]% G1 L. m$ P+ v
  80.     else3 M3 `7 N2 n4 c
  81.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);   // 不发送应答1 \' j( ?0 M& v) k' r
  82.    
    ) r6 f) ]3 A8 m
  83.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    * L6 L4 S3 e3 p
  84.     HAL_Delay(1); // 稍微延时,确保时序正确
    * g7 [* ]/ G2 j& u8 h" o  o
  85.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);8 k; c/ k2 ]2 M9 r) `; F
  86.     HAL_Delay(1);
    ) k9 |$ M; _9 {% F
  87.    $ ~0 C& x' Y0 ]/ J) k
  88.     return byte;
    + j% x" S; b9 i/ X( ]4 V8 X( B
  89. }
复制代码
+ G& ?  b) U3 d7 l2 L
例如IIC的启动信号为:SCL为高电平的时候,SDA从高电平转为低电平。% U- I* y0 _- ~! e9 O4 d* Y# G
. b: R: x( C; j' i7 `' S/ ?4 h
IIC的结束信号为:在SCL线是高电平时,SDA线从低到高的跳变。6 y; H, M& y5 j) P5 L; R

0 b8 h" ~: Y% T5 h
因此使用这种方法可以模拟IIC时序完成通讯。  R. C+ a+ k: u0 }

/ H5 R5 i" \6 V5 H4 l! @! l! p2 M
但是这种方法的弊端也是非常明显的,需要占用CPU,其次这样子并不能确保I2C时序的正确性。所以无论是稳定性还是可移植性还是IIC的效率都欠妥。
2 }' h8 F" {) ^4 c  N! V2 A4 U
, e; t0 r( ~! \4 n0 a
STM32中的硬件IIC   
# K" E* t* {8 T0 {6 OSTM32系列单片机提供了硬件IIC(Inter-Integrated Circuit)模块,用于支持IIC通信协议。硬件IIC通过专门的硬件模块实现了IIC协议的基本功能,包括起始信号、停止信号、时钟同步等,无需用户通过软件模拟实现。
& a$ l0 q# [; U
* F9 W! N9 D3 K( _: y
STM32硬件IIC优势:
3 A- U1 T  s. q; |6 x5 ^1.高效性: 硬件IIC使用专用硬件模块处理通信,不需要CPU直接参与,提高了通信效率,降低了对CPU的负担。0 Q0 R- g1 m! W' t4 M' }- S
2.时序精确控制: 硬件IIC模块能够精确控制时序,确保通信的稳定性,避免了由于软件执行时间不确定性而引起的时序问题。" a1 r* `. V3 c8 Q/ R
3.多主机模式支持: 硬件IIC模块通常支持多主机模式,能够轻松处理多个设备同时访问总线的情况。4 q6 h( H9 ]- X; X3 F  \8 V" x
4.易用性: 由于硬件IIC是芯片内置模块,使用起来相对简单,只需配置相应的寄存器和引脚即可。3 s0 m' `( t" Y& h' u
5.占用资源少: 硬件IIC模块通常占用较少的资源,对于资源有限的嵌入式系统来说,是一种较为理想的选择。6 D6 v; G, C* d, O5 k1 O- w9 N! t# G

) Y' \0 Q9 F  b) R2 z* M1 }
微信图片_20240529192242.png & a7 D( f- \; q; j' Z
' k# O( Q0 ?. U& a
在CubeMX中配置好硬件IIC即可利用HAL库函数进行IIC通讯。
  1. static void MX_I2C1_Init(void)) o( T$ f& y) p+ Q) K
  2. {+ D8 E% c% e/ X
  3.   hi2c1.Instance = I2C1;
    . e* Z% a' Y' {. L$ V- J' ?
  4.   hi2c1.Init.ClockSpeed = 100000;6 O+ Q) ]  u& N, s0 R) x
  5.   hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;) P( W1 _* u* ]/ }
  6.   hi2c1.Init.OwnAddress1 = 0;7 x0 s0 S' T  a2 V/ \( P9 F
  7.   hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    : R% j0 K& E8 h0 r5 g
  8.   hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;4 k4 |- o* C' N+ \) F6 K. m
  9.   hi2c1.Init.OwnAddress2 = 0;5 B" T3 ?) ?4 d4 ?5 U' c
  10.   hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    ( s. Y& {: [# [) X
  11.   hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;8 e; L# {* E. z- R
  12.   HAL_I2C_Init(&hi2c1);
    % a' ~' H7 E2 Z! P4 G6 W' Y
  13. }" F5 b, f& f3 A0 L: I5 ^$ Q

  14. 7 J  l5 C: v2 Q+ L3 b

  15. " b7 _' r& I8 U: P# G
  16. uint8_t deviceAddress = 0x50;//设备地址( a. M( f1 J! |; H
  17. uint8_t registerAddress = 0x00;//寄存器地址
    * R1 Y% e! {2 H3 |8 C
  18. HAL_I2C_Master_Transmit(&hi2c1, deviceAddress, &registerAddress, 1, HAL_MAX_DELAY);
复制代码
3 Y$ w+ n9 e! r& L! A  u& ]
调用CubeMX的初始化函数,之后就可以使用例如HAL_I2C_Master_Transmit,HAL_I2C_Master_Receive等函数来实现IIC通讯。; q4 r6 i$ k7 R, w" l( v
; D# m- t5 e& x# b
% Q$ v( X; H% Y5 p
STM32硬件IIC缺点:  C" u/ f! e9 P0 ?/ F& ]3 U: T& l
1.资源占用: 相比软件IIC,硬件IIC模块可能会占用一定的硬件资源,因此在资源受限的系统中需要谨慎选择。
+ @! n$ X0 K( `5 u+ t: E2.灵活性: 硬件IIC通常由芯片内部硬件模块实现,因此在一些特殊场景下可能缺乏一些灵活性,例如无法更改时序。8 J5 {# Z, r' x9 z& G# r. W+ L
3.部分限制: 不同型号的STM32芯片的硬件IIC模块可能存在一些差异,不同芯片的IO不一样,所以设计时需要谨慎检查。! w! y* L& x2 M& G2 f7 m1 e
2 s2 n' ?* t, j0 Q1 o  r" R3 R6 X
总体而言,STM32的硬件IIC是一种高效、稳定的IIC通信方式,特别适用于对性能要求较高的应用场景,同时在易用性和可靠性上有较大优势。在选择IIC通信方式时,可以根据具体需求权衡硬件IIC和软件IIC的优缺点。
5 ?3 t5 k: x  l. B& o
4 o2 B! ]( J! _( b2 d% R3 a! h) }" M" D- ^$ Q

, b4 k. _5 h  i* x2 i转载自:电路小白( W/ B9 w# A" v# K
如有侵权请联系删除
: Q3 A4 c6 e$ d4 f; ~8 b
: {4 P: a. ]( A* I9 d
收藏 评论0 发布时间:2024-5-29 19:23

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版