IIC(Inter-Integrated Circuit)是一种常见的串行通信协议,广泛应用于各种嵌入式系统中,包括STM32单片机。在STM32中,IIC通信可以通过硬件IIC和软件IIC两种方式实现。本文将介绍IIC的基本原理,然后重点探讨STM32中硬件IIC和软件IIC的区别。
5 [! ? n# C6 ?/ i# I
+ ?3 e& j% I6 [$ A2 Q$ O
- S) t; J# c3 Q/ Q8 x' `
1 P% v3 H# V% O* r% i: v8 Y; b( l- u6 {IIC基本原理:IIC是由飞利浦(Philips)公司提出的一种串行通信协议,适用于在同一电缆上连接多个设备。它采用两根线进行通信,即SDA(数据线)和SCL(时钟线)。设备之间通过这两根线实现数据传输,其中SDA用于传输数据,SCL用于同步时钟。
+ }% ~9 x8 X E" L+ L" Y |9 ^
7 h o6 J' @0 u) k$ e8 i, ?3 N
+ v( D7 e4 R8 P3 m7 g* L% T" X5 s# P+ g$ S7 u* Q
一对IIC总线上面可以挂载多个设备并且多个设备之间有不同的地址,所以我们可以根据不同设备的地址来实现不同设备之间的通信。
$ F8 B. t" W3 I5 Q$ O% G
9 F$ F, c( w( f) t软件IIC
9 ]7 N: R2 J8 I( c在STM32中,软件IIC是一种通过程序控制GPIO口模拟实现IIC通信的方法。这种实现方式常用于一些资源有限的应用场景,或者在需要更灵活控制IIC通信时使用。
9 n/ b, D& }: w7 Z3 p/ f8 Z" E& _8 b4 d( ?# M/ L
: ` S- j3 v& Z% ?7 V
: c& ~! i( f" s( O9 p. q总而言之,软件IIC是利用GPIO的翻转,一个IO模拟SCL线,一个IO模拟SDA线实现IIC通信协议的实现。9 V, x' B3 r# M! Z2 ]7 t
+ ^+ _* s4 ^+ S* {. U; @5 z
软件IIC不需要对IO有特殊的要求,只需要两个普通的GPIO即可实现,因此较为方便也方便移植,不同设备只需要重写IIC的基本通讯即可。9 h9 T: G1 W# z$ x- @
- // 定义IIC的GPIO口和引脚
3 m5 @+ H1 a- Q: d# ` - #define IIC_SCL_PIN GPIO_PIN_6+ {; \" u1 k) q! }1 w. H) J8 p
- #define IIC_SCL_PORT GPIOB
/ L, x- B& d; ^! O/ T - % E; F' Q r0 i5 Z" F: A
& ?* G0 t( @3 a6 p" q" }$ b/ l2 o$ Y- #define IIC_SDA_PIN GPIO_PIN_9
: Z: z: N( j/ `* t; j - #define IIC_SDA_PORT GPIOB
' e8 a2 c* ^; u - v- T. ^9 ~( g* A
* g& g0 y; g I* @7 a) {* }- // 定义读写控制位- Y! @& |! z7 a+ ^, [' O! p5 M
- #define IIC_READ 1
, G3 Q2 w: @- _& k- C4 e P5 E - #define IIC_WRITE 0
. X0 D) Z. H5 I5 X5 x; i" y
9 H+ V. y$ X4 e8 Q! a1 {* Q- # u; A/ g* \4 g. ?% a( Z0 S! S v- L
- // 定义函数
4 b& F5 {& x) e- A' @* d& Z" \ - void IIC_Start(void);
& Y7 y1 T# c2 C4 a6 [; f - void IIC_Stop(void);+ F6 |5 u6 f3 t) _9 U& T
- void IIC_SendByte(uint8_t byte);
' X3 M& {# X- m/ \# | - uint8_t IIC_ReadByte(uint8_t ack);( E. ~$ t8 U1 w" N0 v% h. H2 v% a
$ [% A$ g' J% x/ s, \- 1 J% S6 p% I. m' I% O. L
- 6 j) K. c M: f2 W5 h8 o- i& g" f8 s b
- 3 C) g6 i0 z. B9 b
- // 启动IIC总线
' r/ f; w. ?; w2 y7 F, u1 E1 \ - void IIC_Start(void)# ^2 t: ^' p5 X( ^5 {0 {
- {6 i! _: K+ _; b
- HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
0 \* Z# J( u1 W! v" D - HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
- V6 |2 _8 o: N, _* x. H- e - HAL_Delay(2); // 稍微延时,确保时序正确
: Z1 |& m( Z5 R7 D - HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);
/ B3 t7 G% V, ^; s j0 l9 O0 k; ^8 A - HAL_Delay(2);$ G$ E" f W; |* a6 o$ o, G
- HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);0 G O' N0 S k$ k
- }) D, x% D1 h Z6 i8 `( n
- 0 `% G; E, X* o" |0 \4 a
- 1 {4 K4 J9 A/ c3 z
- // 结束IIC总线
( m, Q, ]2 j& Z* w3 {7 y( i- b" \ - void IIC_Stop(void)
1 ~+ H$ [6 f2 g - {! Q" c5 {! Y: H- U$ b- y
- HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET);
: ]4 T. D/ r' r l& e% N - HAL_Delay(2);
$ Z: r5 T* `2 [ - HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);) ~# X) P# [6 r9 t6 S
- HAL_Delay(2);
' M' F" [4 l' d: E* U; d; V/ | - HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
; X# ~% J: a% U0 c, e$ H - HAL_Delay(2);
1 w5 O' c [5 y# ^& o5 c - }3 \3 k) J/ s& m6 v+ f
- * S' b( |' E U/ g
0 T3 T- Y! Q, f" _/ P+ T7 f- // 发送一个字节
" I/ _8 d: w+ l0 g( n! S4 H - void IIC_SendByte(uint8_t byte)
q [6 B: k7 W4 z2 g - {
1 Z& H5 O5 G6 | b' N' [ - for (int8_t i = 7; i >= 0; i--)
2 C! T. W5 ]0 A4 K# K0 k- ` - {
& `/ C- n) ]6 @ s - HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
" b; Y% B- r3 U3 ^6 w v/ n% ~ - HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, (byte & (1 << i)) ? GPIO_PIN_SET : GPIO_PIN_RESET);
: u. p5 U) i! H7 w% o, @5 K - HAL_Delay(1); // 稍微延时,确保时序正确
) ~, o) }! S7 D {) [' V* { - HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);6 F6 D* ]$ i9 m# L. b4 @9 ^" h- o
- HAL_Delay(1);8 ^! d- I0 h# E& Z: {0 n+ g+ O- c
- }
$ i2 K3 \1 |: u2 ?+ R6 [3 B5 \" I4 K2 g - HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
, R* k$ p$ A' R: N( J( Y8 X J - }
* O) {" S: X1 u ~& K
, W0 H# ~9 Y: O) F
. q ?3 U3 T' P1 Z1 I- // 读取一个字节) F1 I" E- c% |: A
- uint8_t IIC_ReadByte(uint8_t ack); K! F% @8 x( N8 u7 [/ w
- {
# M8 h" @: {0 z# P# U - uint8_t byte = 0; t: ? ^6 z7 m8 f4 w5 i
-
& b) f9 Z9 p8 i6 D, B! j - HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET);
* |/ F+ {' r: g8 N6 O - for (int8_t i = 7; i >= 0; i--)2 o8 S4 s2 |1 B7 z2 {; ~
- {" c' ?$ l, z5 f8 e0 _
- HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);
~' o7 P, A, V1 Q1 w4 U8 k - HAL_Delay(1); // 稍微延时,确保时序正确6 v W# V; |0 i2 _' [1 {
- HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);
* k! ^! {7 p2 o/ V - HAL_Delay(1);7 R4 H, U# \2 e' I O
- byte |= (HAL_GPIO_ReadPin(IIC_SDA_PORT, IIC_SDA_PIN) << i);- E7 e ^2 o6 ]" V$ T8 J. X
- }
- L) u ?4 v7 a& J -
5 q4 J$ ~6 a& j! L$ u% h - if (ack)# u7 ?# B. W$ L1 h" \$ F' O
- HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET); // 发送应答
3 J3 V ?9 S: a7 D1 q0 Q - else
% j, v/ u$ n( A3 d5 Z - HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET); // 不发送应答
( d9 T6 B% i, K8 R7 D6 H+ X - : L7 T1 a9 k' {# @0 l% V
- HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET);! o: \4 Q6 V, V2 T% Q1 x t+ R
- HAL_Delay(1); // 稍微延时,确保时序正确
! \( \/ S4 } \ - HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET);: S$ n# A) k- J9 R" e
- HAL_Delay(1);
; X, j# H4 K( h+ U- k9 B - - B" i" J l4 [3 ?8 E9 z
- return byte;# h8 v, \8 x9 q1 e( k: [% z
- }
复制代码 ! @/ {/ N. b) f3 h4 \8 m1 Z2 ]0 \( l
例如IIC的启动信号为:SCL为高电平的时候,SDA从高电平转为低电平。
7 R( S7 z, x4 A4 L* B9 D
3 c. k6 Y6 r* L' _' E! \; R$ A& h" ~IIC的结束信号为:在SCL线是高电平时,SDA线从低到高的跳变。2 o% h X6 ]" P# s
8 U& K$ `/ d- V4 f- G* ]因此使用这种方法可以模拟IIC时序完成通讯。 L# R) l* v7 B3 g! o
# v( C* t7 G+ V
但是这种方法的弊端也是非常明显的,需要占用CPU,其次这样子并不能确保I2C时序的正确性。所以无论是稳定性还是可移植性还是IIC的效率都欠妥。
# f# Z+ m; v4 f+ N$ p. h, h
$ p8 }2 z7 u, n. I5 P2 W* fSTM32中的硬件IIC
& _* R! K' q1 O; G4 g7 HSTM32系列单片机提供了硬件IIC(Inter-Integrated Circuit)模块,用于支持IIC通信协议。硬件IIC通过专门的硬件模块实现了IIC协议的基本功能,包括起始信号、停止信号、时钟同步等,无需用户通过软件模拟实现。8 G+ z& W1 X$ C+ D8 ^
! n0 C' [( t2 R& C( A3 V VSTM32硬件IIC优势:9 v9 z( t& j+ B6 V+ H; ?
1.高效性: 硬件IIC使用专用硬件模块处理通信,不需要CPU直接参与,提高了通信效率,降低了对CPU的负担。
" ~* \! }! n) E8 g. ]% c0 ] }5 |2.时序精确控制: 硬件IIC模块能够精确控制时序,确保通信的稳定性,避免了由于软件执行时间不确定性而引起的时序问题。
# h' }+ H6 I4 ?# z L. v% T3.多主机模式支持: 硬件IIC模块通常支持多主机模式,能够轻松处理多个设备同时访问总线的情况。* F0 x% D8 ~. r4 q) p" @
4.易用性: 由于硬件IIC是芯片内置模块,使用起来相对简单,只需配置相应的寄存器和引脚即可。
; a0 q+ w) N! O; p5.占用资源少: 硬件IIC模块通常占用较少的资源,对于资源有限的嵌入式系统来说,是一种较为理想的选择。
. X2 G" P3 B' X% m
/ i' u1 U# z* A8 D5 @
* f$ I7 H J* m" f9 L( b5 a) J5 x' p* D0 m6 P0 x4 W
在CubeMX中配置好硬件IIC即可利用HAL库函数进行IIC通讯。- static void MX_I2C1_Init(void)
% X' K: ^+ A Q" s - {
& K4 m3 P; U% Y- |1 S2 z - hi2c1.Instance = I2C1;& j7 f3 D1 {8 @ f% ]# ]
- hi2c1.Init.ClockSpeed = 100000;% R! {& [3 y4 ~9 M h2 y0 r! {
- hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;* f2 M! D4 e# B S3 E4 _" l$ K
- hi2c1.Init.OwnAddress1 = 0;% v# T4 ^5 w& V1 l5 t
- hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;, j( j9 D0 Q0 _4 L7 n. i1 G
- hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;5 n% J( J# w' @9 ^, Z. h
- hi2c1.Init.OwnAddress2 = 0;1 [9 x; n: |5 Y0 G( n
- hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
/ h7 a, P1 h1 L$ ] - hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
" `& s* Z1 f8 G3 w) R' ~ - HAL_I2C_Init(&hi2c1); l# H" m) {0 L
- }9 I) c- o( b# c2 Q, J0 O
3 S9 E4 z! U7 D- W- " a1 t |9 ?2 g% a% G- Z: o; N' z
- uint8_t deviceAddress = 0x50;//设备地址
: x7 r+ G& ?) Y* A - uint8_t registerAddress = 0x00;//寄存器地址
2 o$ Z$ |0 K# L4 N7 O - HAL_I2C_Master_Transmit(&hi2c1, deviceAddress, ®isterAddress, 1, HAL_MAX_DELAY);
复制代码 1 Q; U s" V( a0 }6 ]$ A+ S' u
调用CubeMX的初始化函数,之后就可以使用例如HAL_I2C_Master_Transmit,HAL_I2C_Master_Receive等函数来实现IIC通讯。
: ]* N3 W3 z7 t' P# c: T/ Z5 k- ~7 T; ^; s) p
) A( T; G- Q3 j* L
STM32硬件IIC缺点:
# r8 l0 ^) r" E$ X4 Q" l1 D) Q- H) y1.资源占用: 相比软件IIC,硬件IIC模块可能会占用一定的硬件资源,因此在资源受限的系统中需要谨慎选择。3 ~; u- I8 Y3 `' R8 B# [2 N
2.灵活性: 硬件IIC通常由芯片内部硬件模块实现,因此在一些特殊场景下可能缺乏一些灵活性,例如无法更改时序。1 l( U; \& k6 v
3.部分限制: 不同型号的STM32芯片的硬件IIC模块可能存在一些差异,不同芯片的IO不一样,所以设计时需要谨慎检查。
. d& N, {- w+ `7 |: n8 [4 _ P
总体而言,STM32的硬件IIC是一种高效、稳定的IIC通信方式,特别适用于对性能要求较高的应用场景,同时在易用性和可靠性上有较大优势。在选择IIC通信方式时,可以根据具体需求权衡硬件IIC和软件IIC的优缺点。
- A; p1 I( N$ I
& z1 r( W/ @9 ]! E9 p, |' e3 S9 {- m, F) v4 ?" g
. N ]) F1 v1 t5 ]转载自:电路小白: L' \* P$ O* r* z& \
如有侵权请联系删除
+ G. k! F. ^6 k% M$ W/ c0 w3 }0 o) L% m
|