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

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

[复制链接]
攻城狮Melo 发布时间:2024-5-29 19:23
IIC(Inter-Integrated Circuit)是一种常见的串行通信协议,广泛应用于各种嵌入式系统中,包括STM32单片机。在STM32中,IIC通信可以通过硬件IIC和软件IIC两种方式实现。本文将介绍IIC的基本原理,然后重点探讨STM32中硬件IIC和软件IIC的区别。
% q0 R! B" H" w  S" N. D. j" H3 N; O' e& h0 P8 k! T* K
微信图片_20240529192252.png ' v+ l) z( G5 t" }3 {7 X5 r
+ [1 |# y0 r0 B
IIC基本原理:IIC是由飞利浦(Philips)公司提出的一种串行通信协议,适用于在同一电缆上连接多个设备。它采用两根线进行通信,即SDA(数据线)和SCL(时钟线)。设备之间通过这两根线实现数据传输,其中SDA用于传输数据,SCL用于同步时钟。  p* _5 x/ s2 X+ Y' l

6 B: a- L8 Q' X9 @1 M9 x 微信图片_20240529192248.png
8 l  ?8 |1 H) s0 x, U8 ~
& S* e3 r9 _  `& J  h$ h
一对IIC总线上面可以挂载多个设备并且多个设备之间有不同的地址,所以我们可以根据不同设备的地址来实现不同设备之间的通信。) g& D5 `: b% Y3 S4 p
$ F0 [' H5 a$ l0 P' W9 l
软件IIC
7 O0 T. t7 Q' ?6 A在STM32中,软件IIC是一种通过程序控制GPIO口模拟实现IIC通信的方法。这种实现方式常用于一些资源有限的应用场景,或者在需要更灵活控制IIC通信时使用。2 x2 I$ y+ V- h4 \. c

4 z" G! }6 ~, U, O7 J 微信图片_20240529192245.png
+ g( g" c* O: R# }7 Y& V) c

4 D% q, L$ X0 P: v/ ^7 i) k总而言之,软件IIC是利用GPIO的翻转,一个IO模拟SCL线,一个IO模拟SDA线实现IIC通信协议的实现。9 t. ?9 S$ f9 S2 \

/ g, P6 L. p& l  G9 q
软件IIC不需要对IO有特殊的要求,只需要两个普通的GPIO即可实现,因此较为方便也方便移植,不同设备只需要重写IIC的基本通讯即可。+ A1 h4 ?, a' N: N, p( q
  1. // 定义IIC的GPIO口和引脚
    # x9 D. m0 X2 N2 L
  2. #define IIC_SCL_PIN GPIO_PIN_6
    9 {! x: t: B0 q7 o( f# S' k' ~& N
  3. #define IIC_SCL_PORT GPIOB
    / l6 y; E% E1 M' Y' I5 }

  4. " ^; e( p# b/ F6 m7 m/ `; W, s. H
  5. 9 `% O! Q' x$ e2 O, O% Z! k
  6. #define IIC_SDA_PIN GPIO_PIN_9
    $ T% K: n1 i  {. t# g
  7. #define IIC_SDA_PORT GPIOB
    % i# z  k6 K" J; }" z) P% _
  8. ! Q. F6 `) E! C! x+ ~3 H" q

  9. ( ^7 R! B4 C' h$ ?9 b
  10. // 定义读写控制位0 V' ^, a/ }  I: r
  11. #define IIC_READ  1
    * F: Z' k1 a+ C, N, [
  12. #define IIC_WRITE 08 h: @2 Q0 c9 I- `
  13. 8 @3 }. p+ p+ N* A2 J" O5 _+ ^0 X9 R
  14. + ?9 G3 D  Q0 f/ M9 w' k4 c
  15. // 定义函数
    ; H6 [! h9 `' e; x3 ^
  16. void IIC_Start(void);8 s! L$ b; G: Q* a
  17. void IIC_Stop(void);
    % t' J7 e: v* k$ L# J) y% c
  18. void IIC_SendByte(uint8_t byte);
    # G- p! Y% ~$ Z* Y2 S
  19. uint8_t IIC_ReadByte(uint8_t ack);" I6 [6 c! N8 h& ]  q; G- b

  20. 3 z; G# H6 }. H
  21. ; H! w) K& G& [% O9 F2 g

  22.   b2 H/ k9 [2 r3 z) E7 u
  23. 4 I+ d- E+ D/ U: X/ v& ?
  24. // 启动IIC总线
    6 J/ t7 a6 u. J
  25. void IIC_Start(void)
    / v. b: |% {+ k" _7 N, [
  26. {
    : C' e& a$ i. A+ V5 t
  27.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
    $ h7 o6 N+ d4 K+ n' A: E2 C" u; v
  28.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    * a' i' x! E' X/ y* c6 W
  29.     HAL_Delay(2);  // 稍微延时,确保时序正确
    3 \, b1 a! ]2 |0 O5 `" t
  30.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);& d) U$ s* q" g2 q
  31.     HAL_Delay(2);
    - S: [6 f& d) |9 g8 R' I
  32.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    & X$ t* j* [9 ]4 p4 X
  33. }- a/ }8 J7 Y1 }
  34. 6 v$ R* `9 Y' u% x
  35. * u7 t+ Z% V* Z, |, M& L7 i
  36. // 结束IIC总线  D7 V2 L% A& }* B% W
  37. void IIC_Stop(void)
    0 R& ^! l1 u: |2 J3 {* y: @% }! ]9 t/ d+ t$ x
  38. {9 M3 p' Y$ ^9 s/ ]+ ^& c
  39.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);: z0 [" I+ F; \" ^( k/ R
  40.     HAL_Delay(2);
    & g& D5 T+ M- s& t( j/ O# {
  41.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);+ }( S) c6 F& l
  42.     HAL_Delay(2);
    ! Q; g+ z5 T# b
  43.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);# H& l0 v2 W# e5 }
  44.     HAL_Delay(2);* T$ V: _+ h6 q& w6 H
  45. }
    + J- U; ~  q/ _8 s  T5 o8 @

  46. % u4 ^! a5 t( `6 I" h2 g2 W2 F

  47. 5 ^# ~# r: L& U$ d
  48. // 发送一个字节
    8 v5 _5 [* `! D: D
  49. void IIC_SendByte(uint8_t byte)5 b7 H" h, B0 s# v9 G  U  S1 q) O
  50. {
    + T8 \1 Z/ q' K5 t& y2 Q" Y0 B
  51.     for (int8_t i = 7; i >= 0; i--)2 O& h0 C; q3 h) D7 y
  52.     {
    - _% u0 @- W3 j
  53.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);9 H& k3 o; j; c& e) ], P
  54.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, (byte & (1 << i)) ? GPIO_PIN_SET : GPIO_PIN_RESET);: ]; B9 ^$ K, ~4 m- T2 S
  55.         HAL_Delay(1); // 稍微延时,确保时序正确
    3 A. Q: U0 b: o/ N
  56.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);1 T2 o# @! h/ G6 x" S
  57.         HAL_Delay(1);
    ! P4 ^6 w" x9 z3 U
  58.     }  |! D" \1 {) W
  59.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    + ^: R! `. j- U3 N8 f
  60. }
    ; N/ N# Y" h! [$ F
  61. : c, p1 a% y5 \$ I

  62.   H" A6 F- h4 D& c) u
  63. // 读取一个字节
    * u6 h8 f% p# l+ r: F2 ]# o; t
  64. uint8_t IIC_ReadByte(uint8_t ack)8 k8 G# A7 G4 L9 D* e. F/ Q& z; i  W
  65. {0 P9 s; P8 O8 G: L! l, N
  66.     uint8_t byte = 0;8 a% u( k* A3 L0 p$ j* n' G! ~
  67.    
    : j3 D( }8 I/ R- |' J7 k6 {- v5 G
  68.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);7 @# g2 z' @. d& h
  69.     for (int8_t i = 7; i >= 0; i--)6 V5 I0 Q+ S& T& J5 E; s
  70.     {
    1 ~+ q+ f! }7 P0 T
  71.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);% h" b; ?1 e- e6 \
  72.         HAL_Delay(1); // 稍微延时,确保时序正确
    * x' i# e7 W- B0 n& X3 E) e
  73.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    ! s$ n* q1 F; `8 n, q
  74.         HAL_Delay(1);6 S: A+ l  T( x/ v0 f5 g+ v8 R' G) ^
  75.         byte |= (HAL_GPIO_ReadPin(IIC_SDA_PORT, IIC_SDA_PIN) << i);7 x/ G, ~$ H/ S
  76.     }
    , \) n; @/ l, B9 Z' P8 a
  77.    % U; ^2 b9 q' |5 l- j) A! j
  78.     if (ack)' D5 l( P' U2 Y: s7 q
  79.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET); // 发送应答) X2 g& Z& [& E7 N0 l
  80.     else/ _# L# H  P* T* r$ ?) J! X8 D
  81.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);   // 不发送应答
    / w$ {6 ]1 P, E) Y" b" e
  82.    & u) y  }- i& |- @- a3 \7 M
  83.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    . X) G8 t1 E4 i4 V
  84.     HAL_Delay(1); // 稍微延时,确保时序正确5 a6 f7 _2 d' Q; ~9 }
  85.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    4 I% }; E* s8 Q2 ~
  86.     HAL_Delay(1);
    # z/ n+ H0 ?. s9 i
  87.    , e) y) h1 A+ e$ o* `8 D
  88.     return byte;. H: J. D) h( }! K& Y
  89. }
复制代码
3 b/ A4 n7 k" ]2 s3 O; Q' R
例如IIC的启动信号为:SCL为高电平的时候,SDA从高电平转为低电平。
! [* D+ \0 o3 m6 Y# B; B0 G8 P
; e0 z# U8 B; n& D1 |. l1 Y
IIC的结束信号为:在SCL线是高电平时,SDA线从低到高的跳变。5 u) r7 d. `/ c6 X" h
. @" t/ t$ c7 W( }1 x  S
因此使用这种方法可以模拟IIC时序完成通讯。
! U) g- |! g) q1 ~3 B
( O' d$ d; Y8 ~  L& J- F
但是这种方法的弊端也是非常明显的,需要占用CPU,其次这样子并不能确保I2C时序的正确性。所以无论是稳定性还是可移植性还是IIC的效率都欠妥。
, K- q! P, \$ z  J. j
0 \, U8 ?  S) F9 Q, `
STM32中的硬件IIC    + k1 P4 v& Z& k: B
STM32系列单片机提供了硬件IIC(Inter-Integrated Circuit)模块,用于支持IIC通信协议。硬件IIC通过专门的硬件模块实现了IIC协议的基本功能,包括起始信号、停止信号、时钟同步等,无需用户通过软件模拟实现。$ K- ^- h: ^% l" r
2 M) o* u  ^; s: I8 m6 y: m& a
STM32硬件IIC优势:) [4 O7 o$ i; U5 U0 |6 b9 r
1.高效性: 硬件IIC使用专用硬件模块处理通信,不需要CPU直接参与,提高了通信效率,降低了对CPU的负担。
. M0 p+ X! m7 l6 y' Y
2.时序精确控制: 硬件IIC模块能够精确控制时序,确保通信的稳定性,避免了由于软件执行时间不确定性而引起的时序问题。
+ ~  h4 z0 j5 a* o  z$ s3.多主机模式支持: 硬件IIC模块通常支持多主机模式,能够轻松处理多个设备同时访问总线的情况。7 ~/ Y1 ]7 ~0 |
4.易用性: 由于硬件IIC是芯片内置模块,使用起来相对简单,只需配置相应的寄存器和引脚即可。- p4 y3 y0 P. j' H
5.占用资源少: 硬件IIC模块通常占用较少的资源,对于资源有限的嵌入式系统来说,是一种较为理想的选择。
5 X* P8 V9 ~2 E  S" _) w: t0 J0 }" T0 ~" p9 \* }2 k/ |$ k
微信图片_20240529192242.png ! a) `1 p# M  v  J

5 E$ T2 N) I$ y# R; h5 p在CubeMX中配置好硬件IIC即可利用HAL库函数进行IIC通讯。
  1. static void MX_I2C1_Init(void)  |/ O: [7 u- I. x3 |
  2. {
    # K- t5 h8 h& u% o6 F: l
  3.   hi2c1.Instance = I2C1;0 w  k. j& o- R8 ?* K2 x, P
  4.   hi2c1.Init.ClockSpeed = 100000;8 w/ j, R' Y. V7 n  ]1 J8 Y
  5.   hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;+ M. X! r2 L  v  C3 I
  6.   hi2c1.Init.OwnAddress1 = 0;
    . O- u7 ^$ c0 }% R& g$ [' M3 N; Z$ }
  7.   hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;8 o; J0 w$ G5 u% ~; d- H
  8.   hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;% S3 x, U4 W" U  l9 |
  9.   hi2c1.Init.OwnAddress2 = 0;+ n0 T# j! \5 S6 I$ I
  10.   hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    0 u+ h3 ~& G- e% C' {) D
  11.   hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    / R! z6 \1 _; k1 p: q& E
  12.   HAL_I2C_Init(&hi2c1);
    ' S1 V1 c/ K" _
  13. }: l# z% q# G/ P9 S! p, Z  Q
  14. " y% W8 L3 ~2 L4 k9 x% V; q; g

  15. / o  h0 E, Y7 L
  16. uint8_t deviceAddress = 0x50;//设备地址
    ( B7 E3 w/ `; H, I8 B" n
  17. uint8_t registerAddress = 0x00;//寄存器地址0 O' z) B, h6 X- {
  18. HAL_I2C_Master_Transmit(&hi2c1, deviceAddress, &registerAddress, 1, HAL_MAX_DELAY);
复制代码

7 W7 |' v  z. a0 a调用CubeMX的初始化函数,之后就可以使用例如HAL_I2C_Master_Transmit,HAL_I2C_Master_Receive等函数来实现IIC通讯。
8 U# k: Z: E9 `1 e4 x: v& N: p% h7 p. c; t" Q
" r" x! N& e3 ]  y5 h/ J
STM32硬件IIC缺点:
# Z; H  }2 j/ [( ?1.资源占用: 相比软件IIC,硬件IIC模块可能会占用一定的硬件资源,因此在资源受限的系统中需要谨慎选择。
" v: i/ M  O$ N  T5 q7 c2.灵活性: 硬件IIC通常由芯片内部硬件模块实现,因此在一些特殊场景下可能缺乏一些灵活性,例如无法更改时序。
9 b& i# H: M4 R& T( u; A3.部分限制: 不同型号的STM32芯片的硬件IIC模块可能存在一些差异,不同芯片的IO不一样,所以设计时需要谨慎检查。8 {( T8 z4 u& K) W- ^3 y1 L
! j6 r8 i6 i- n5 j6 f
总体而言,STM32的硬件IIC是一种高效、稳定的IIC通信方式,特别适用于对性能要求较高的应用场景,同时在易用性和可靠性上有较大优势。在选择IIC通信方式时,可以根据具体需求权衡硬件IIC和软件IIC的优缺点。
; c, W# X% Q& s- B) [! s  j3 T5 T; G9 A9 n. u& K
. y+ X7 s% p* Z8 `& I, v; o
  ]& t" Y$ J! ]! \& G; T
转载自:电路小白
" z+ G( C# T( i如有侵权请联系删除2 O1 |7 U4 d) t6 Q/ e' f" d! l
! X' A- g. H5 j( @
收藏 评论0 发布时间:2024-5-29 19:23

举报

0个回答

所属标签

相似技术帖

官网相关资源

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