说明:驱动基于STm32G031K6,其他型号需自行做改动。/ m+ K5 W7 t' v! o1 e K3 J$ x
! L' W9 E9 N& Z3 }
注:因为之前项目暂未用到LL库的IIC,所以此驱动未经过实机验证。欢迎反馈使用中的问题。# s0 t) W3 E+ S2 |8 W
: A% e$ ~, D1 k$ n9 P$ J7 z% ZIIC的初始化: CubeMX生成
' f- v0 |* x7 C2 q; W5 r: z- ?* K2 J$ t3 ?
- void STM32LLI2C1_Init(void)) _& {' e* b; P! E0 D7 T- r
- {. y3 A) j4 x1 O. x, a
- LL_I2C_InitTypeDef I2C_InitStruct = {0};- ]' [ b: t4 d5 o
- - E+ x$ b ?( r N: N5 c3 i
- LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
% I! K7 C8 p* Z - 0 [# \; y* c& E+ I, K2 W
- LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
$ P% I, a" L1 c1 R( a& B8 i" j2 d - /**I2C1 GPIO Configuration
# e9 h% u% j' a8 N0 c u - PA9 ------> I2C1_SCL, W2 D$ u; H7 i
- PA10 ------> I2C1_SDA , d8 I; m) [; X+ E$ P) y
- */ y' C+ `( m9 R5 q- u4 r) Z
- GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;" n3 p; w$ t i; e+ p/ _
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
: W. `0 g' n' P3 x5 p z - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;$ v: p$ J1 ]! C! | U% ?7 S" L: d
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
1 _) k8 |6 y4 f) U3 ~ - GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; I& p5 k0 r* p5 D
- GPIO_InitStruct.Alternate = LL_GPIO_AF_6;
4 W E% j w* d3 Q5 I3 Q, u! U - LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
$ M A8 C% O7 V3 Y; F. K - 5 f, C8 c. ^9 |: Y' m/ Q
- /* Peripheral clock enable */
$ x" N2 D# z% { - LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
0 w2 y; @# m- h) e- J. f/ O- I4 R
& s. J6 w) _6 W0 U1 P9 ~- /** I2C Initialization ) e' c ?# ^# n0 m
- */& {* ~# s; g$ X+ E: `. `5 q9 l
- I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;' |# i+ p3 G, V2 J
- I2C_InitStruct.Timing = 0x00303D5B; d7 M \$ M5 [, k' _2 m
- I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;; P i; {" w# E" B
- I2C_InitStruct.DigitalFilter = 0;
! }. e y+ X' @% Q/ {9 m3 r& L8 d- K - I2C_InitStruct.OwnAddress1 = 0; Y7 g9 @- E! C' F
- I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
3 m2 D4 U$ y2 k9 L- S% I - I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;0 l* u) q4 E$ G4 t/ F6 ]
- LL_I2C_Init(I2C1, &I2C_InitStruct);
6 E6 Q8 _7 t1 u2 q G- A: s$ ~# ~ - LL_I2C_EnableAutoEndMode(I2C1);2 o, m& P. |* L6 D5 ~5 T' L) Z7 r/ u% l
- LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);! ]9 u( d% F: B. N
- LL_I2C_DisableOwnAddress2(I2C1);% \2 d# l3 g; r4 y; ?
- LL_I2C_DisableGeneralCall(I2C1);
6 a2 Y3 `! n' Y) A& M) g" s - LL_I2C_EnableClockStretching(I2C1);& x! P2 l* U0 M( U
- LL_I2C_Enable(I2C1);/ J9 g: G0 W& z% m
- }
复制代码 , y2 K4 k* X" d7 d; F
由于LL库未提供与HAL类似的I2C多数据读取的函数接口,所以需要自行编写函数,我这里是参照HAL库内的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read写的LL库可使用的相对应函数。
0 q- S7 d, i' b8 }6 M+ Q
4 F0 M; D4 ?0 T( w" B$ DI2C读多个数据:, j/ Y9 \; p9 H9 O. N( d7 v
& d6 H, T5 }" I( t" `4 L) n
- void STM32I2C1_MasterRead(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
- G; d( d- D7 g/ n$ ` - {' L# a& }- ]) } r2 h8 o: {$ z. {9 ^
- //等待iic空闲
& @5 w |/ Y- J8 E7 E - while(LL_I2C_IsActiveFlag_BUSY(I2C1));/ D3 H( l% R# t! M& m$ E
- //确认iic是否使能
* P$ Q+ B0 {/ L: C9 E+ k9 d - if(!LL_I2C_IsEnabled(I2C1))
. x8 M" V2 U! G3 W' c - {( W0 F+ a2 Q y9 b
- LL_I2C_Enable(I2C1);2 d @, s# ]& I$ U& S6 c# O
- }
m' U% w5 K; A3 t0 [2 S - //配置+ Z3 Q8 p" ?, [- r/ _+ W
- LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_SOFTEND_MODE,I2C_GENERATE_START_WRITE);
' J h7 N# r( P% F4 e2 H4 U - while(!LL_I2C_IsActiveFlag_TXIS(I2C1));; H0 n, _% p) x2 b
: A1 v8 \! L" `5 H$ U- //写入从设备寄存器地址4 p* l# x. d s& f+ L
- ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
3 d6 K( t( l2 l' l7 V - while(!LL_I2C_IsActiveFlag_TC(I2C1));2 N2 i0 ?8 A5 v3 R5 e a, q1 g
# l* m8 l6 k9 M! ^% }- //配置
" [6 \- n; Z0 y8 ~/ C5 r5 c+ y( u6 i - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ);
9 B( v/ ? @4 J! w u" m2 Q - * ^: ?1 p3 e- X& x1 n1 n0 F) z
- //读取数据
) A! f+ V' G% k' t) F/ C - ucBSP_I2C1_ReadMultipleData(pdata,length); o* {$ O3 ~* i" ]
, ^4 o2 `) W8 B7 K# r- //等待停止完成 R$ v$ l( n9 T0 E% V$ x
- while(!LL_I2C_IsActiveFlag_STOP(I2C1));- t. s$ T3 Z$ Q# C" |' `* U, \
- LL_I2C_ClearFlag_STOP(I2C1);/ P8 q8 H9 K( {% a: ^
- }
复制代码 / t: A7 k* _! ^
I2C写多个数据:. x6 C1 D" j. ?0 R0 b5 P
5 {- }( D7 U5 @. \- Z+ }- void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
7 V5 K$ H: G. s - {% Q& R8 d8 y- k" T' D
- //等待iic空闲
; R7 Z/ r& b+ y, Q - while(LL_I2C_IsActiveFlag_BUSY(I2C1));; _3 R- ?1 L, n4 g, z
- //确认iic是否使能
& O3 q0 A4 z: x J - if(!LL_I2C_IsEnabled(I2C1))+ ?. h- t, ]- N6 b$ `" A5 ?+ }
- {! G+ \. J4 A7 |8 L& O& R$ l
- LL_I2C_Enable(I2C1);. v+ [( v* `) R! F$ n
- }2 l+ d4 I3 e# t% v! Q
- //配置为写0 `7 T. l; t1 d9 E. m
- LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_RELOAD_MODE,I2C_GENERATE_START_WRITE);2 v Q* m# G# @- t- r
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));4 M1 }9 @6 k+ F3 D" w7 P. x
- 8 J2 x& v$ T- V7 v
- //写入从设备寄存器地址: ~( j4 F4 Z. D. g" O+ r9 {
- ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
/ M- e4 P/ U# ?. ?. i, t8 { - while(!LL_I2C_IsActiveFlag_TCR(I2C1));
& a' f) ~0 B' F
" e9 ^' D' ? k) Z- //重新配置为自动停止模式
0 @% o5 J. i9 ]2 Z - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_NO_STARTSTOP);
8 O0 Y# F: |. I+ q) B; z
( i s% \* j, T: o4 K- //写数据
8 h8 d1 ]9 L/ F7 i - ucBSP_I2C1_WriteMultipleData(pdata,length);! K7 ]: u1 d0 G s
+ f; e4 B% `" O, i/ }1 a9 b- //等待停止完成* p2 C+ C( b5 s; ^+ J
- while(!LL_I2C_IsActiveFlag_STOP(I2C1));. V' v: r! J( {
- LL_I2C_ClearFlag_STOP(I2C1);
U( G ~) i* |% x" Z0 a7 F - }
复制代码 # B( k' |* y: n' y
为了减少代码重复和增加可读性,对读写的一些过程另作了函数;: D+ V# M3 e: Z. s- L. o
+ q$ N; X9 K- V6 r写寄存器地址:, ^6 N) y% l' U5 C5 {% e5 ]
9 S6 S1 q, c3 ~) v" E/ h0 f
- void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size)
6 L6 t$ \6 p& ?( P( `/ p& p2 U - {0 K2 I' t6 C# _3 O& E
- uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);;
4 Q! J3 r/ D0 ]& I - uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);;7 O2 B, A8 M. m2 W$ N
- - G1 j$ A( y2 C }- m
- //发送器件寄存器地址. o" G$ j( z: \" b6 v* {9 X6 @
- if(mem_size == I2C_MEMADD_SIZE_8BIT)
: G, V$ y3 k9 ?' I4 j% u/ f S - {
n' y0 g2 L& x$ S% m K, K+ T - LL_I2C_TransmitData8(I2C1, MemAddrLSB);0 H6 G, `/ i- r3 L# p3 F. }
- }else{
& }4 I. u q- F' P - LL_I2C_TransmitData8(I2C1, MemAddrMSB);
( g+ b1 y2 n) R1 D; n# |; @( C - //等待发送完成
s8 E) U6 K" I$ C' ~ - while(!LL_I2C_IsActiveFlag_TXIS(I2C1));5 g4 o- w9 F( ]
- LL_I2C_TransmitData8(I2C1, MemAddrLSB);
* G8 t6 B2 R5 C+ ^/ I - }
! Z; y4 J8 h. Y$ a; H0 X/ s - }
复制代码
6 d, z1 u) o( ]. l* Y5 p) ~; g% ~连续写入小于255个数据:
! A' @; G, |2 X+ O* T$ A$ q5 U1 W$ X0 c- Z3 M" K0 n" l# E# |
- void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length)
% p/ p" A l% Y+ a" e. ^ - {2 [' a' {, S2 z) M4 S8 O; x
- uint8_t count;
# E; y+ T6 c3 i1 D- W' s - for(count=0;count<length; count++)
1 @5 j' p( S' U; G6 z( B - {6 u7 `, i8 `' O1 O$ V1 [$ S# ?
- //等待发送完成 C2 u; k& _% [0 Z
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
9 ?" D2 n( W7 ]/ n6 P/ _' e; J - LL_I2C_TransmitData8(I2C1, *(pdata+count));! f- E: H. z( @& b
- }
0 ]' R# F% z4 n" Q ? - }
复制代码 % {1 C4 z6 l2 \( Z8 I( O
连续读取小于255个数据:) B" v; ?+ D- U- J2 M
8 X/ n y* S S& Z7 n' @- void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length)5 s* a. H* E7 B8 v
- {
+ p& b. n- Y t6 m- A0 C* \ - uint8_t count;3 `$ p5 J, A) \' x. J
- for(count=0;count<length; count++)
$ y& C% v6 T" ^, p1 l4 y' O - {
) @( _2 H1 L' z7 h* N" ]5 ~- m+ u - //等待接收非空
* D, H- p( n8 `$ L6 d G" K - while(!LL_I2C_IsActiveFlag_RXNE(I2C1));
4 k! V( X; p) i; G" } - *(pdata+count) = LL_I2C_ReceiveData8(I2C1);
) s- ]% W9 f& T$ ~2 K - }
" k2 h) P$ v. O0 H0 K* Z - }
6 V. V4 Y# D8 k9 l% R0 @. T! v$ k. S
复制代码
& Q2 _* k. q1 [
& E ]! J5 }# p |
有收获,感谢分享。