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

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

[复制链接]
攻城狮Melo 发布时间:2024-5-29 19:23
IIC(Inter-Integrated Circuit)是一种常见的串行通信协议,广泛应用于各种嵌入式系统中,包括STM32单片机。在STM32中,IIC通信可以通过硬件IIC和软件IIC两种方式实现。本文将介绍IIC的基本原理,然后重点探讨STM32中硬件IIC和软件IIC的区别。9 P% S* U6 `$ G1 q& M) N
5 |: K: B- ]: j6 \4 L  S/ R  n
微信图片_20240529192252.png ; l6 T+ l- \6 K% T

/ ?4 K4 g/ ?# v; ]$ l- D6 x, F+ {1 CIIC基本原理:IIC是由飞利浦(Philips)公司提出的一种串行通信协议,适用于在同一电缆上连接多个设备。它采用两根线进行通信,即SDA(数据线)和SCL(时钟线)。设备之间通过这两根线实现数据传输,其中SDA用于传输数据,SCL用于同步时钟。
6 g! O+ h# P4 H+ P9 y2 Q! \% A% q( Q
微信图片_20240529192248.png : J$ q, ~0 }+ V$ \2 Z- i4 v
5 t+ h2 V4 [% I8 b$ I, a% e- W
一对IIC总线上面可以挂载多个设备并且多个设备之间有不同的地址,所以我们可以根据不同设备的地址来实现不同设备之间的通信。( o- N' v4 [( g

' N5 C# A5 q4 o6 g( F: x
软件IIC$ c* [9 S; @0 ^3 J4 t: g/ D6 w! n
在STM32中,软件IIC是一种通过程序控制GPIO口模拟实现IIC通信的方法。这种实现方式常用于一些资源有限的应用场景,或者在需要更灵活控制IIC通信时使用。
: J; G# }  Q$ J, v
$ G2 @/ _: W, X( z 微信图片_20240529192245.png 8 a( s; S9 h+ K+ T3 _
4 l* H- d8 r3 g
总而言之,软件IIC是利用GPIO的翻转,一个IO模拟SCL线,一个IO模拟SDA线实现IIC通信协议的实现。& [" {4 c% S2 m6 x
: G' Q  b1 }! g3 ^7 ]2 L' R
软件IIC不需要对IO有特殊的要求,只需要两个普通的GPIO即可实现,因此较为方便也方便移植,不同设备只需要重写IIC的基本通讯即可。. F+ Y9 r& h6 Z) b4 R# s
  1. // 定义IIC的GPIO口和引脚3 i! `% y4 M) F- }2 p
  2. #define IIC_SCL_PIN GPIO_PIN_6
    & K! N. H: M9 {- |1 p
  3. #define IIC_SCL_PORT GPIOB
    ) n) z) g% f; M. }) r1 C3 y7 y
  4. # v( ?" l. }$ z6 m
  5. " l$ b! F* G; \8 O
  6. #define IIC_SDA_PIN GPIO_PIN_9  G- f# E2 Q3 C
  7. #define IIC_SDA_PORT GPIOB
    2 D  G/ K$ C- y# b! s( o5 w5 H8 y

  8. 7 i$ H) O/ }# q) y

  9. + ~- h+ A# X2 i
  10. // 定义读写控制位
    * v$ O1 u, a& H* |, y
  11. #define IIC_READ  1
    0 F# `5 q% p) @1 ?, D4 R) A: A, Q( u
  12. #define IIC_WRITE 0+ d+ b0 s$ c3 S% A# I& Z# r1 E

  13. - f4 K7 `) q- h1 W# t' s+ r

  14. 5 d) I. R! m% |; i1 W0 d& o% N! A) v) L
  15. // 定义函数: H5 \1 W0 b  z% S
  16. void IIC_Start(void);9 b4 S' e8 v4 W
  17. void IIC_Stop(void);8 P; W9 |( T* a2 d! M! ~
  18. void IIC_SendByte(uint8_t byte);. X; r: p* X* _
  19. uint8_t IIC_ReadByte(uint8_t ack);4 T& B9 s8 v1 V9 G) F4 x! ^
  20. 0 h- X$ D# C3 _! {0 K# z$ F

  21. 6 W) @$ X: Y; `7 C+ a
  22. 4 w0 H2 b( l4 g' y& T- \
  23. 1 F6 ~& Z: r" X
  24. // 启动IIC总线
      y7 |  j( H# |$ u
  25. void IIC_Start(void)1 L* X8 j6 t1 C: m/ n: m
  26. {
    $ R6 G# S& T7 q* [' d* N, r
  27.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
      e0 {" \4 j8 k' V$ B! v
  28.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    2 b8 G" v, }) P' |; i  g# \
  29.     HAL_Delay(2);  // 稍微延时,确保时序正确+ U0 n2 k9 ]+ a# i8 H2 [4 r
  30.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);
    8 F; \( K4 J1 t
  31.     HAL_Delay(2);
    3 t1 }; M* b& P7 v" v' W, ?4 K
  32.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    ! C) Y* A" t9 Y2 a+ ]( H7 i) w- z) u5 i9 k
  33. }
    % {/ s4 n/ p4 n# v* ^, C5 D

  34. / n4 d) U4 i# M# w
  35. ' K0 A; ]7 d0 `% |, q/ ~- l2 ]
  36. // 结束IIC总线
    7 Y1 \, ?/ r; U) M) w
  37. void IIC_Stop(void)
    3 ]0 ]2 O, a9 [/ b
  38. {, b' a5 ^% s2 R4 V( X5 \
  39.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);
    5 G6 [& g1 D5 _9 J. N
  40.     HAL_Delay(2);
    1 ~0 o5 k# }" ~- M
  41.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    6 E1 H) v- {. T
  42.     HAL_Delay(2);1 y+ B3 b8 a6 x( S
  43.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
    2 G5 I- S" `( ^: c
  44.     HAL_Delay(2);
    5 l. o- u. ~) S" C
  45. }/ f! b5 H& }. x3 h

  46. : m7 ~) F) c/ p4 ?: }& \  g8 W  V
  47. 0 E$ ^4 n7 e0 I
  48. // 发送一个字节4 t7 z: f0 x! v) ^* V
  49. void IIC_SendByte(uint8_t byte)* t3 C6 X9 ^* H3 Q
  50. {
    5 l% t8 ], M0 V6 O3 v- s
  51.     for (int8_t i = 7; i >= 0; i--)1 a( l" b5 z3 a. N/ P, i
  52.     {( i( c1 b# q2 M8 g& M  t( i4 i
  53.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    ; ~% y. f) i% ?4 m5 [% |
  54.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, (byte & (1 << i)) ? GPIO_PIN_SET : GPIO_PIN_RESET);
    ; Y3 @/ v2 n4 x  {/ w
  55.         HAL_Delay(1); // 稍微延时,确保时序正确
    4 _) U  D( [2 x. G
  56.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    - @1 x1 e' V  X! ]4 C+ j) J
  57.         HAL_Delay(1);$ N+ T3 z* B/ ~4 t5 U, {
  58.     }
      _! D7 {, Q, r8 f% Z) ^
  59.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    : x0 Y/ g- @3 n0 \
  60. }
      A( x" Q" @. h; W! p. @" [

  61. " e! R3 \2 A( G& ]! N8 D8 m

  62. 1 N5 ^, }  U- r2 J4 p
  63. // 读取一个字节' u% u" n% h1 ?; R6 f7 J
  64. uint8_t IIC_ReadByte(uint8_t ack)
    9 l# o: L) u. \- Z
  65. {7 G& |  k) ], Y/ J6 ~9 g6 t
  66.     uint8_t byte = 0;3 H( @& U' l$ V5 O
  67.    
    " a, i5 Q$ f1 m! R% I! V( ~
  68.     HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);1 ?* j! b$ ~0 ~, H
  69.     for (int8_t i = 7; i >= 0; i--)
    8 ]# P% I+ E2 r5 k, Z$ l0 T
  70.     {
    " `4 d% z) y- @- T
  71.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
    " e. g+ V5 N9 A& W$ [
  72.         HAL_Delay(1); // 稍微延时,确保时序正确
    : z2 i( C5 M0 b, ]6 z9 Y
  73.         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
    / }; G  G0 F. A
  74.         HAL_Delay(1);3 W$ |, I) d; e. d) N* Z
  75.         byte |= (HAL_GPIO_ReadPin(IIC_SDA_PORT, IIC_SDA_PIN) << i);
    , P- S0 G+ J4 L3 Z
  76.     }. B! N( u. V- ?: f1 v8 \& W1 K
  77.    8 ^! w$ E; V. A7 Y. X
  78.     if (ack)
    & r: I/ Q& j6 U, b2 ^1 o; j
  79.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET); // 发送应答
    % `/ f2 T$ `0 R% ]0 t2 D  N" b8 x
  80.     else
    5 d# `" \: ^! o' [, y% F. B% g' R5 f
  81.         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);   // 不发送应答5 m- C3 a: p9 M- q% u
  82.    
    : q2 i7 @0 Z9 O/ Q% g2 w
  83.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);9 T5 r: e$ n5 v
  84.     HAL_Delay(1); // 稍微延时,确保时序正确
    9 l% h: h  K% O1 {, x
  85.     HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);# z9 H2 q2 B7 v
  86.     HAL_Delay(1);5 b4 P( k: q0 u3 _( e/ g4 B; }6 ^  U
  87.      Q* }! W% N4 k/ e
  88.     return byte;$ W: V+ s5 s. a: u4 X1 L1 l' N
  89. }
复制代码

! u. V- j: |1 S6 l& _4 R例如IIC的启动信号为:SCL为高电平的时候,SDA从高电平转为低电平。9 P. P- f3 @3 y4 }2 `& R

- j8 `+ `! N' v1 c: h7 f( f
IIC的结束信号为:在SCL线是高电平时,SDA线从低到高的跳变。
! k3 R* t8 |! J: h: k* j
; f4 [# _; n! c6 E, `* s
因此使用这种方法可以模拟IIC时序完成通讯。
6 P( q% G+ \7 }+ J2 \% m3 t) m$ x3 w; ?! D. b: s  w& o" h+ J
但是这种方法的弊端也是非常明显的,需要占用CPU,其次这样子并不能确保I2C时序的正确性。所以无论是稳定性还是可移植性还是IIC的效率都欠妥。6 M7 E% H6 c5 e# |: a

9 J# [7 {1 Y) F/ G0 `; B1 ?
STM32中的硬件IIC   
; r! a$ u- o8 \STM32系列单片机提供了硬件IIC(Inter-Integrated Circuit)模块,用于支持IIC通信协议。硬件IIC通过专门的硬件模块实现了IIC协议的基本功能,包括起始信号、停止信号、时钟同步等,无需用户通过软件模拟实现。2 i5 H8 ]; N' v1 J1 D7 g
, E# }. d/ W2 ^" `- ?& U2 R6 q. G  _& }
STM32硬件IIC优势:
, Y0 o3 K  Y/ s* \* Z. V9 ^! D; F1.高效性: 硬件IIC使用专用硬件模块处理通信,不需要CPU直接参与,提高了通信效率,降低了对CPU的负担。: a$ D7 r! Z  [
2.时序精确控制: 硬件IIC模块能够精确控制时序,确保通信的稳定性,避免了由于软件执行时间不确定性而引起的时序问题。
2 B2 g3 a/ u+ [" J8 \+ H3.多主机模式支持: 硬件IIC模块通常支持多主机模式,能够轻松处理多个设备同时访问总线的情况。1 n! V( Y8 }3 `/ o; q4 E3 V
4.易用性: 由于硬件IIC是芯片内置模块,使用起来相对简单,只需配置相应的寄存器和引脚即可。
& V2 H* \  z/ ^1 E8 A# [& N5 s5.占用资源少: 硬件IIC模块通常占用较少的资源,对于资源有限的嵌入式系统来说,是一种较为理想的选择。
4 b: H8 W/ `% D& L9 F8 D( O1 f$ D* D( c+ a4 ?. i& \
微信图片_20240529192242.png 8 F3 Z! v8 O( j+ X4 {. R0 ^0 X8 r
3 P& y& l1 L7 w, I2 K# T. F
在CubeMX中配置好硬件IIC即可利用HAL库函数进行IIC通讯。
  1. static void MX_I2C1_Init(void)* J# w. ~8 }6 \; o; G7 \% h# R, x
  2. {
    2 X0 n3 v8 @3 s
  3.   hi2c1.Instance = I2C1;
    . y& w/ O) A$ C
  4.   hi2c1.Init.ClockSpeed = 100000;
    - G0 t8 D7 g2 f9 l
  5.   hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;- I1 _$ v. H' o
  6.   hi2c1.Init.OwnAddress1 = 0;
    9 e% o  M5 R: l' v, R
  7.   hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    3 k  e( ~0 I! b$ s  M
  8.   hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;- w7 |7 r; h! R
  9.   hi2c1.Init.OwnAddress2 = 0;# m2 s/ m& a  @8 q- c; f' u
  10.   hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;3 e, }& Q3 O: h* N
  11.   hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;% T8 I$ L* [( U$ G7 P
  12.   HAL_I2C_Init(&hi2c1);7 ?; [! h9 `/ V, Q' k
  13. }
    " z( X$ X9 q7 Y6 i8 W5 e2 G

  14. 8 M8 j7 u0 d2 e7 [& R
  15.   a, ^9 t' G$ M2 s: P
  16. uint8_t deviceAddress = 0x50;//设备地址
    ( r# b- L# E/ l# L! O
  17. uint8_t registerAddress = 0x00;//寄存器地址
    & b* h) ~- ~' H# n  D0 M1 O
  18. HAL_I2C_Master_Transmit(&hi2c1, deviceAddress, &registerAddress, 1, HAL_MAX_DELAY);
复制代码
: s1 T% a/ ?: b2 ]" U3 p
调用CubeMX的初始化函数,之后就可以使用例如HAL_I2C_Master_Transmit,HAL_I2C_Master_Receive等函数来实现IIC通讯。9 e% x3 G! U9 Q% U# R

' Q; }7 X2 J4 N' ^8 x. M0 i( }5 |  w" O% m) t3 ~2 J
STM32硬件IIC缺点:0 x) S( r6 s! u; i
1.资源占用: 相比软件IIC,硬件IIC模块可能会占用一定的硬件资源,因此在资源受限的系统中需要谨慎选择。
1 I2 @* W4 [. k5 x2.灵活性: 硬件IIC通常由芯片内部硬件模块实现,因此在一些特殊场景下可能缺乏一些灵活性,例如无法更改时序。
% t* w% I! G: J: M3 r- J( A- U3.部分限制: 不同型号的STM32芯片的硬件IIC模块可能存在一些差异,不同芯片的IO不一样,所以设计时需要谨慎检查。
6 o3 G' g  x! U5 E
" n/ T+ X) M" h! q  w# g& |1 s总体而言,STM32的硬件IIC是一种高效、稳定的IIC通信方式,特别适用于对性能要求较高的应用场景,同时在易用性和可靠性上有较大优势。在选择IIC通信方式时,可以根据具体需求权衡硬件IIC和软件IIC的优缺点。
6 y* ]6 x# G$ ?% O4 k6 p1 j
! Q; n# ~+ {, @8 |4 k# w* B# T6 O" {

9 D* [+ M+ ?- F2 _转载自:电路小白
& e+ O# Z; f' Z' t+ R如有侵权请联系删除# N( u. I' ]0 {# g, V% q! ~4 {

9 |3 S" U* A3 Z$ C4 Z/ U8 i* v
赞 收藏 评论0 发布时间:2024-5-29 19:23

举报

0个回答

所属标签

相似技术帖

官网相关资源

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