说明:驱动基于STm32G031K6,其他型号需自行做改动。
( Q9 O& C, d4 W4 o8 o4 H9 E. X+ s* k& A- P) q
注:因为之前项目暂未用到LL库的IIC,所以此驱动未经过实机验证。欢迎反馈使用中的问题。
0 E4 c/ u6 }- N
: h0 n+ ^2 G4 i6 w( }* s, }IIC的初始化: CubeMX生成
2 x! Q9 \ a b1 Q# z9 X3 i8 v
! V9 e7 ?5 {1 F- void STM32LLI2C1_Init(void)
. B+ U6 Y7 d: z, N7 o3 j - {4 L1 `% y. N" q% o" \3 s
- LL_I2C_InitTypeDef I2C_InitStruct = {0};, a% a9 _, i- C8 ~
- + F3 z u) s6 B: s
- LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
+ @) a( Q$ I% }; ?; s7 k
$ I1 T2 ]# n* O$ o% L- ?- LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);. `+ _9 R- I" d" V9 K# t$ _3 e
- /**I2C1 GPIO Configuration
8 @9 Z, y8 e4 `5 T - PA9 ------> I2C1_SCL2 B1 Q, H0 v8 b s; x# J: e. Z6 p
- PA10 ------> I2C1_SDA 5 |, }' T2 k) o0 A7 Q5 E+ H; p
- */
( h+ Q% U* B8 O3 C2 z, } u - GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;+ [5 p- ]/ g5 C. r' I' f
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;: U; P$ u: o- ^3 q# F5 @
- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;0 ^ S+ q, X2 p
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;9 T9 u* A4 i/ E3 Q# G3 h
- GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;8 D, w* G# ?/ r7 w U9 V# i
- GPIO_InitStruct.Alternate = LL_GPIO_AF_6;
- K3 I$ t( J/ K' W! @ - LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
6 o3 o8 V$ l" w3 M( L0 N. q0 B
! g L- X6 |! _- /* Peripheral clock enable */
0 P3 q2 [; @1 l+ J1 x5 q - LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
6 }* b! ]6 g* \ - + S# r5 G* l, r" F7 O
- /** I2C Initialization % M' w, r- L" C8 y
- */3 Q+ B: R6 X- e' I0 a
- I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;5 J9 V! d9 C0 |
- I2C_InitStruct.Timing = 0x00303D5B;
) B; z7 H: n0 z1 i9 q) C2 F - I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;7 e# K7 n) l4 y1 g: t* W3 T" W
- I2C_InitStruct.DigitalFilter = 0;
; N$ B& f) B5 t, A: H% P! G - I2C_InitStruct.OwnAddress1 = 0;6 f0 t9 h% Y% {0 Y
- I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;2 w1 R+ N) ?; W, Q" R+ ~1 }
- I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
/ M% t% n# W! ^1 I, A - LL_I2C_Init(I2C1, &I2C_InitStruct);* U& {4 W3 ^/ X9 ?
- LL_I2C_EnableAutoEndMode(I2C1);
4 c. @& k2 J1 K% p - LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);
4 J' [3 T% R# I/ h$ Z& X2 G3 h - LL_I2C_DisableOwnAddress2(I2C1);
) H1 ^; S7 T2 D+ @8 z1 D. E) g - LL_I2C_DisableGeneralCall(I2C1);
, \3 U8 H0 ^. x0 F9 k9 d/ m - LL_I2C_EnableClockStretching(I2C1);) }9 {) C% S/ o, w, f% T; |) r
- LL_I2C_Enable(I2C1);
$ r6 e! q: X( M0 ~" r - }
复制代码 4 S- l/ ^" X5 U1 o
由于LL库未提供与HAL类似的I2C多数据读取的函数接口,所以需要自行编写函数,我这里是参照HAL库内的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read写的LL库可使用的相对应函数。
& G) u$ Z2 v- `. y. k4 Z" K8 t o6 O# W$ ^1 j
I2C读多个数据:
+ N. @. F+ F5 b" N, }. G, t4 b9 H, P0 ]9 S
- void STM32I2C1_MasterRead(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
. @* ~5 I- i- a - {
5 |8 E( Q& ] ]! b! \- B - //等待iic空闲$ t h# t7 `( \
- while(LL_I2C_IsActiveFlag_BUSY(I2C1));6 i$ l: ?+ m8 _& V% u% P
- //确认iic是否使能
. {! `2 Y( n' X- s( q$ x) ~: ? - if(!LL_I2C_IsEnabled(I2C1))% W( _! `( r+ n4 k- g; S% E+ {
- {* B I2 I" H. H! `7 [1 l8 t
- LL_I2C_Enable(I2C1);
2 ]3 H" q3 z4 Z; x T" m A - }( S7 R& Y4 D6 w1 S' f
- //配置! G+ H: k. a! t* a! ~" \& m$ M
- LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_SOFTEND_MODE,I2C_GENERATE_START_WRITE);
; K: t2 H7 O) I' B - while(!LL_I2C_IsActiveFlag_TXIS(I2C1)); H( |" V; A# s
- # w+ ]4 k7 V8 C8 V4 l
- //写入从设备寄存器地址
4 T2 n2 v3 U1 _7 r - ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
6 Y+ z+ w' i+ g: c - while(!LL_I2C_IsActiveFlag_TC(I2C1));
/ O+ A! u. w3 r* r - : G, J x8 o/ d" o5 z" T
- //配置/ E6 D$ v# s8 q, `* a# N
- LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ);
. l$ p S* m6 q3 K+ | - 0 b+ Q/ P8 U8 k) g$ S( J
- //读取数据1 `' `0 R0 X8 a+ ~8 ~# z
- ucBSP_I2C1_ReadMultipleData(pdata,length);' W) O! ]4 w2 d4 D- t! `% s! q2 d5 z
/ D8 j7 v* l, D4 M- //等待停止完成: ~1 L3 a1 t' f/ g+ k! D
- while(!LL_I2C_IsActiveFlag_STOP(I2C1));
" w0 x- B4 y, ]% k8 d* ` x0 b3 \# V - LL_I2C_ClearFlag_STOP(I2C1);
' E7 f& Q) T& Q4 ^6 k7 m - }
复制代码
) A9 ~5 e( ], f- ~/ vI2C写多个数据:9 M% J, a7 G" ?6 ~( d$ v3 s& g4 L* U, g
+ z' R! j# J6 a
- void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)* W; T0 h6 O$ W3 o+ f9 b9 z: b
- {: n& c) o( Y- h4 g% W
- //等待iic空闲
3 x/ N" y4 f6 j" Q" t; B, f ` - while(LL_I2C_IsActiveFlag_BUSY(I2C1));
6 [+ Q3 [" K' D' q- _0 D+ r - //确认iic是否使能
, ]) k) P8 W4 F" h" A! }7 _ - if(!LL_I2C_IsEnabled(I2C1))
9 w" c; z7 s3 K" _" J2 T7 S& n0 h# U - {
$ P, c/ Y) s% F4 S# e: a - LL_I2C_Enable(I2C1);
7 C y: O6 B+ v% P - }
: v% o2 L ? E6 u4 g. B! n/ | - //配置为写1 U5 f3 t+ `( \8 d7 z6 q
- LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_RELOAD_MODE,I2C_GENERATE_START_WRITE);
, S( M# [) Z( p. S# ~ - while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
& j6 f% i- }4 I. D0 } - / d( b6 r8 b6 o9 i, d6 a
- //写入从设备寄存器地址" O1 g1 M$ l" J4 t8 D! r( w
- ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);2 u( J3 R5 x4 a: k8 E& i
- while(!LL_I2C_IsActiveFlag_TCR(I2C1));
1 w7 H( S1 P% f1 ]' J0 v4 { j - 6 d; Z; b' P; l$ O: `$ {# P
- //重新配置为自动停止模式+ L6 m. G: |) q! Z/ W3 i
- LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_NO_STARTSTOP);
5 A9 K/ H' w1 n6 W: z
1 F( b% b, x1 `' W- //写数据6 o9 m# h. C, _" e+ l, |
- ucBSP_I2C1_WriteMultipleData(pdata,length);2 X$ E: W. j! ~5 [* M9 D9 K
0 G' F2 P' Z# K4 o- //等待停止完成( O, `, h4 o/ a% e$ l2 P: E2 |
- while(!LL_I2C_IsActiveFlag_STOP(I2C1));; y g8 X& M! y7 R! O. a( K! s- n
- LL_I2C_ClearFlag_STOP(I2C1);4 U# v$ @( _0 h/ d7 {' N) s! u
- }
复制代码 8 ~+ V* M+ j6 d! N! q/ S
为了减少代码重复和增加可读性,对读写的一些过程另作了函数;
# Q1 t- H. v& ]6 X- x
k1 Y; Z6 A5 s9 ]* L写寄存器地址:- a V) x/ z: j8 I
% O0 X: U0 q( N
- void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size)
( ]8 r7 {! t3 j6 f8 e2 M - {
. } M* J+ f5 b - uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);;
+ s* g$ F0 I2 j# T8 H. t - uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);;
4 C: [: N3 W: j$ I
+ X6 N- H. B. H0 I: q; ?$ W- //发送器件寄存器地址
6 d. N0 B9 }5 l - if(mem_size == I2C_MEMADD_SIZE_8BIT)3 l# }1 ?) p2 ], g7 Z# w* f! U/ W
- {
' F$ y8 n1 O' f. M( x- |. ] - LL_I2C_TransmitData8(I2C1, MemAddrLSB);/ J2 p8 u. \* ?' z7 ^4 `# O- t6 a
- }else{
+ p# P o5 `$ x2 O9 S+ X& @! D - LL_I2C_TransmitData8(I2C1, MemAddrMSB);
, t* d {# }5 |! o: o2 { - //等待发送完成# G3 b: J, x7 f% Q0 d/ V- \. f
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
8 I+ [# s' }' N5 [ x% ~; b - LL_I2C_TransmitData8(I2C1, MemAddrLSB);- I1 Z$ Q' t4 a( o' n* f
- }
# I# d( k g! W! e3 _; |" ^! G - }
复制代码
7 L1 b) l' G0 j5 ?# @& W! y连续写入小于255个数据:
6 K5 A4 ], \. E; J+ J
7 ?0 W$ n# @, ?$ h- void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length)/ o3 I' r1 |7 B7 l4 }
- {/ X' n6 _$ C- p& t6 {- E( q6 A3 D
- uint8_t count;
- @$ a: R; I$ O& V1 A - for(count=0;count<length; count++)
0 ^6 F/ ^+ C7 D! s% G - {( a$ _9 O% r% a! n8 X; `# J+ `
- //等待发送完成
2 U# _" q. z4 p& M - while(!LL_I2C_IsActiveFlag_TXIS(I2C1));( f; [5 ^* V4 y2 U/ l. X
- LL_I2C_TransmitData8(I2C1, *(pdata+count));
; x! q3 w$ `, N - }3 d/ j& I. j2 m5 R3 V1 E! s
- }
复制代码
) J( y8 \" ?9 ~( D: I连续读取小于255个数据:
5 v3 [1 R# Q4 C: M y/ l7 K+ b) I( B$ z9 P9 W: L+ k( u
- void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length)7 }" j M1 i) N
- {
& u# m W' G' V - uint8_t count;
6 D' [* I ^! k; ?, @6 B - for(count=0;count<length; count++)' G5 t1 o* g9 \+ H+ ?
- {# Y$ v: c& ?) b I
- //等待接收非空
2 R0 ~( O) F: J# N$ y* U/ [ - while(!LL_I2C_IsActiveFlag_RXNE(I2C1));. h2 i' B$ R& B! W4 @
- *(pdata+count) = LL_I2C_ReceiveData8(I2C1);
" u& O6 X. ?2 t$ |& E: q! ] - }2 v* z* o9 g" Q( k" {; i
- }
# U- X( Y: Y# }0 y
复制代码
1 Z- g8 q: k# t' s# W# n$ c8 n* S3 p1 b( c3 D5 c( b
|
有收获,感谢分享。