说明:驱动基于STm32G031K6,其他型号需自行做改动。
9 ?% u0 U: R0 X2 r# I6 z3 R0 A5 A7 w! I/ b
注:因为之前项目暂未用到LL库的IIC,所以此驱动未经过实机验证。欢迎反馈使用中的问题。 G* O2 Y0 D" x- G, N z* ~
5 k" d; @6 }, F" x
IIC的初始化: CubeMX生成- B- D1 \: N* E" ^: ~4 Z: X: B3 L
" ]' X, E3 \ n- void STM32LLI2C1_Init(void)
; i. f8 @3 W1 ^% b2 s1 w; }5 q - {2 E) ^' a3 n7 {8 Z5 D3 x# D4 J
- LL_I2C_InitTypeDef I2C_InitStruct = {0};
% b' u& o0 E+ w- v/ i0 ?
' v( X& ?$ X) b. r3 I- LL_GPIO_InitTypeDef GPIO_InitStruct = {0};, N' G8 |( }$ R; g. X% G+ a
- $ C, M; l8 I, a
- LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);; p# o0 o- }: H) W5 f, ]2 _
- /**I2C1 GPIO Configuration
3 J( q+ q* m" I4 K1 y - PA9 ------> I2C1_SCL
' B& t- S0 E A* n, I& P- n1 K+ b# Y - PA10 ------> I2C1_SDA - p% J: ]/ ?/ Z( q5 L. {" }8 m. Z8 C4 n
- */
' M4 t H X2 y3 ~ - GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;- w5 a9 D/ x: b) b$ `# g
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
" B- \+ l5 P: ]( I1 M- N3 k - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;+ w/ K) n* P$ |( h# A
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
3 r. x" Z+ X& s) N - GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
$ y: ~- W- P$ ~% _# V0 t+ W Z - GPIO_InitStruct.Alternate = LL_GPIO_AF_6;5 B3 ~ J9 d7 i* H% C& d) }* D* o
- LL_GPIO_Init(GPIOA, &GPIO_InitStruct);2 u' z( M: u1 d1 @
- 7 Z$ V* j) h- f h0 s! o
- /* Peripheral clock enable */- F* A2 H, t/ c& S0 d; E* ?6 t
- LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);# c3 E" e9 W9 Z' W+ ?7 o1 ]7 r
- $ u9 [! e& ]0 f7 h( ?
- /** I2C Initialization ( o9 H* r- v7 s; b" a. d% ]
- */0 c* L$ k$ E8 T2 `
- I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
, `: s8 \7 k$ `* R# C/ S$ o' x& F - I2C_InitStruct.Timing = 0x00303D5B;4 |1 X# Q+ C, N
- I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
@& M* W. h5 I# n }2 v - I2C_InitStruct.DigitalFilter = 0;' x" K$ A4 C3 K- R
- I2C_InitStruct.OwnAddress1 = 0;
5 Z* f6 j% p9 M) j- T( t - I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
2 n+ U' C) L2 b/ X% W2 X+ W1 j; j - I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;% }% h% o) ]# u% {8 M9 m9 q+ q
- LL_I2C_Init(I2C1, &I2C_InitStruct);/ e0 a% |4 b2 f; I- W% W1 n* j
- LL_I2C_EnableAutoEndMode(I2C1);
' ^! T; L* ]4 C6 v: } - LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);
! E. R' F" T6 C' T. c - LL_I2C_DisableOwnAddress2(I2C1);! r3 |; t. N6 O5 z
- LL_I2C_DisableGeneralCall(I2C1);; l( S( W: g8 w% o$ ?
- LL_I2C_EnableClockStretching(I2C1);) [' y0 o; M2 w! [/ n
- LL_I2C_Enable(I2C1);
, N7 g! J5 b! }6 B' y! ]/ F1 {5 N - }
复制代码 * U6 E( I5 V9 X6 [# C0 J
由于LL库未提供与HAL类似的I2C多数据读取的函数接口,所以需要自行编写函数,我这里是参照HAL库内的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read写的LL库可使用的相对应函数。
9 A. y' |6 E# H: s6 @) O8 M: H6 V/ a3 |: a
I2C读多个数据:8 _# P8 X6 }8 S. v O8 b% K
' m5 D3 t) N- v4 o
- void STM32I2C1_MasterRead(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)9 x7 N0 X; l% J) e9 U
- {
2 W( U3 G2 Q7 L4 X& ~ - //等待iic空闲( {. c% b5 B+ v
- while(LL_I2C_IsActiveFlag_BUSY(I2C1));
* A0 _7 U0 W& }0 O C# f# \+ u - //确认iic是否使能0 e' P# w6 e6 Y1 D
- if(!LL_I2C_IsEnabled(I2C1))
' V8 b: Q6 ]# G - {9 _) c1 w* R( y9 U) x3 z9 ~! ^
- LL_I2C_Enable(I2C1);
8 g1 Q. x: L r+ A; V - }
8 J/ h. z* Y+ b7 P2 ]" J- V - //配置
/ q6 O5 x! F6 O2 m - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_SOFTEND_MODE,I2C_GENERATE_START_WRITE);0 }8 O3 [& |% M; C; i3 ?
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
- n5 s' L, x! X7 _3 A
0 h! S% Q" P" B- C5 k- R5 b1 D- //写入从设备寄存器地址0 f; \: l5 _. x4 V' y1 V
- ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
F" t! N8 ]0 Y9 W+ E - while(!LL_I2C_IsActiveFlag_TC(I2C1));
+ x3 Z* @+ Y3 ]
$ X) \( {# \0 R: S' b- //配置4 [- k6 f: V7 k; Y: \- l
- LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ);
. W- |$ I& ^, B! k/ @% U. L& D# J
$ T& v- ~0 t# v4 d7 {0 ]$ M4 l5 l- //读取数据# J( _. ^& c z' s5 L
- ucBSP_I2C1_ReadMultipleData(pdata,length);
8 R8 m' ^! d5 @2 Z/ C% A - 4 |3 y8 p3 o( y& B+ I7 }
- //等待停止完成' h3 O8 T2 Y. d0 S9 C3 f
- while(!LL_I2C_IsActiveFlag_STOP(I2C1));% g" ]$ `$ d, ]3 o
- LL_I2C_ClearFlag_STOP(I2C1);0 [; F' u) @% P p, Z% a. H# u# y
- }
复制代码 9 `) B. u5 B0 U) K4 ?- b. b3 I
I2C写多个数据:! h# O6 m0 X8 \8 M
& \! _+ Y. l T; |7 F- void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)" T8 D4 v9 g( H4 I. p% E
- {: Q/ X' o |$ H' |: s3 h
- //等待iic空闲0 z) m2 ~( _, V Q7 ?
- while(LL_I2C_IsActiveFlag_BUSY(I2C1));$ X2 {3 x# j" ?& G
- //确认iic是否使能
, Z$ E2 s5 D5 l4 `) i0 l3 g! d1 v - if(!LL_I2C_IsEnabled(I2C1))
1 D3 q/ E- q: M, q - {
" M& a$ q' l9 } S) j' B - LL_I2C_Enable(I2C1);4 p5 y: s! {; }8 f( X) E5 Y+ r
- }& Q) x" d& N5 c2 B M! C( F) y( T
- //配置为写/ {0 F: U9 j' i; w) h% C
- LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_RELOAD_MODE,I2C_GENERATE_START_WRITE);
( r7 o3 j& R4 }. K) W) y - while(!LL_I2C_IsActiveFlag_TXIS(I2C1));0 R9 i' U2 [" a L( n8 e5 r1 F
# ^/ ^" }& B; G% d- //写入从设备寄存器地址& o: h) X" M, V. ~+ @3 d, O
- ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
2 r9 \2 t: e" p2 F7 G" A - while(!LL_I2C_IsActiveFlag_TCR(I2C1));5 c v! C+ s! G e7 u, \ j: G
- 7 r' {9 f) c Q0 r7 q' R
- //重新配置为自动停止模式% |1 }9 \7 I# c6 D9 G
- LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_NO_STARTSTOP);" r9 Z# R* Y& i
9 M7 G ?2 B# x, W2 I+ c- p' _- //写数据
% V8 p# X- f6 ]. u - ucBSP_I2C1_WriteMultipleData(pdata,length);" o* n3 m; V( ~2 Z p3 u5 J
6 ^& w/ p6 S$ l- //等待停止完成
8 R$ S+ t+ v/ o$ X% } - while(!LL_I2C_IsActiveFlag_STOP(I2C1));' O. i7 G2 ?7 f" P2 Y& Y r
- LL_I2C_ClearFlag_STOP(I2C1);
" {) m! v9 \8 n$ b4 @$ E - }
复制代码 0 F# |9 z# j$ H' R8 {& G' X7 F/ ?
为了减少代码重复和增加可读性,对读写的一些过程另作了函数;
. z, C6 l3 ? v0 }' i
+ Z, v% y6 M3 T- P写寄存器地址:
# ^. |! m- L4 ~5 T, h) V0 V: A8 F& ?4 I* T8 D! l
- void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size)( b1 c+ a& j+ Y3 K; p: N2 K3 k7 H7 w
- {
' r2 b' `1 X5 B: } D - uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);;: F! a: }+ U' d7 Z
- uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);;
# Y! ~5 z: s6 y& }6 F
/ t' g1 m$ z$ H ~- //发送器件寄存器地址
- g% i8 r6 h9 J( e( V! {, A - if(mem_size == I2C_MEMADD_SIZE_8BIT)
' Q- A( F# V |2 i - {" F7 X* N) V5 c3 n
- LL_I2C_TransmitData8(I2C1, MemAddrLSB);" c; D% K3 a5 } U2 s
- }else{
3 J! c+ f3 f- Z1 L( m9 g2 \ - LL_I2C_TransmitData8(I2C1, MemAddrMSB);
5 e! o0 z" Y, ?0 D# V' N - //等待发送完成
5 k! }( R& _+ E: \9 q: M - while(!LL_I2C_IsActiveFlag_TXIS(I2C1));3 o: ]+ ? j# k0 R
- LL_I2C_TransmitData8(I2C1, MemAddrLSB);
7 A0 Z% R) `( H! g. n - }% ]2 q( @. S( t7 R/ M
- }
复制代码
8 g0 E: }8 l& e$ a2 s" }连续写入小于255个数据:
6 v( a' j0 q- k) Z2 a- ?6 V+ z Z- v) D/ e% n. G1 x4 g- U; P
- void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length)8 Z7 H' s0 q9 M" h$ x
- {! E1 T9 h( f3 c6 n4 x* }& \
- uint8_t count;7 ]+ A! V' r6 U. p$ Q% a) s
- for(count=0;count<length; count++)/ ]' }9 X- W) e6 W4 ^0 W4 ]
- {
6 H' u0 ?6 v1 ^ - //等待发送完成- ~, P5 M7 d/ I* r- y
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
7 ~" m; A0 t0 R) W - LL_I2C_TransmitData8(I2C1, *(pdata+count));$ Z( `) n N/ P, ^# z3 y/ p
- }9 u$ \# |8 t; v; O, Y+ z% T
- }
复制代码 " e9 _0 }# R! r& ~/ r
连续读取小于255个数据:
7 K* ]9 M) z) b2 |9 @9 E0 ?0 g3 A7 t$ ?7 v, v! G7 Y
- void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length)
: u: s/ E8 s$ Y `" \0 I - {
3 l$ g* h1 d; b - uint8_t count;
0 \$ h1 O$ {( `! p2 ? - for(count=0;count<length; count++)3 [- ?% I d3 P1 A1 u
- {" _- n! w4 h7 \, ?
- //等待接收非空
& M2 ~ Z6 T! { - while(!LL_I2C_IsActiveFlag_RXNE(I2C1));
3 s, l. I6 I4 H7 d3 p% Y( o/ l; v - *(pdata+count) = LL_I2C_ReceiveData8(I2C1);
+ k, C3 _4 h q8 s9 f - }+ W! i& l0 c1 |
- }
( w- r" ?6 m/ B- ^" V0 M5 J) B0 h- p7 E4 c
复制代码
1 o0 G% j2 J1 `4 z7 `
8 `! g% H R- k& ] |
有收获,感谢分享。