说明:驱动基于STm32G031K6,其他型号需自行做改动。
" t- f! Z; ^2 c2 ?0 [1 R6 o2 F X/ q$ C: g' V9 H
注:因为之前项目暂未用到LL库的IIC,所以此驱动未经过实机验证。欢迎反馈使用中的问题。
9 c- L/ X8 }- d% X; M+ ^
O( R. ~% Z) g0 V* u+ \( ?6 PIIC的初始化: CubeMX生成. d4 ]; ?$ n/ p& A6 d& I
: F c2 F% e8 r; ]- void STM32LLI2C1_Init(void)
|6 U' j9 v/ i5 N; r - {
0 E" t- v2 L$ ^9 |$ j- z - LL_I2C_InitTypeDef I2C_InitStruct = {0};
& X2 }8 K) u6 Z" D - 2 a/ Y- K, d" V; s/ ]
- LL_GPIO_InitTypeDef GPIO_InitStruct = {0};5 m* H4 X! b7 A8 X: C$ V4 Q
- * H& [* Z1 [0 X# F" W( C/ A
- LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);0 Y4 G8 A: @9 |8 q1 ^6 f
- /**I2C1 GPIO Configuration & Q8 q: `; K( \, w
- PA9 ------> I2C1_SCL! v' \, y$ _0 Q+ S, V+ i. q& H& ]2 L
- PA10 ------> I2C1_SDA
. |& L4 q* j/ r; p) o - *// w3 j& o$ Z+ }. j" T: H3 k
- GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;
# C6 `! }" F" b h5 C2 _ N - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
7 ?/ O7 \# q( c% M0 K5 d8 s" o4 _ - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;) f; O1 D# K! f6 {- t
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;& u' ~/ A+ T6 M' m d% [4 h
- GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
8 Z- E4 A# ^7 t9 s; | - GPIO_InitStruct.Alternate = LL_GPIO_AF_6;9 T4 x2 l1 Q m2 [
- LL_GPIO_Init(GPIOA, &GPIO_InitStruct);+ V0 H& H5 o# f0 ]& r, p N
- . {2 F- l4 G% P
- /* Peripheral clock enable */7 o+ z0 Y# ~: Q+ [5 a% @. t
- LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
8 Z8 J4 E* U) p7 T - 6 a7 @; v: R( O; K
- /** I2C Initialization * A' D' ^/ K A( b! T( n x- B
- */
1 u; f) g' d* W$ Z& j - I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;$ q9 b: [' M1 z3 Q
- I2C_InitStruct.Timing = 0x00303D5B;
1 G0 R- d; P) F: b i! s6 d - I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
& ^1 |+ K# A% M. N* { - I2C_InitStruct.DigitalFilter = 0;
1 ]/ E+ J. m X4 A& B8 v - I2C_InitStruct.OwnAddress1 = 0;& {2 X8 ~4 Q. ?% b4 g/ z+ i% S
- I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
0 ]4 ~ y$ C% Q/ H2 B" d! z: [ - I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;# b/ W8 q4 X, W& @
- LL_I2C_Init(I2C1, &I2C_InitStruct);( q% N7 w6 s' K0 e3 D6 o7 z
- LL_I2C_EnableAutoEndMode(I2C1);
- q# \3 f, n, R+ E& j9 x - LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);
3 \# n& b0 C' |! \: `# n6 t: t - LL_I2C_DisableOwnAddress2(I2C1);. S: [9 T. R$ X! ?
- LL_I2C_DisableGeneralCall(I2C1);
n6 D2 g1 B0 Y& i6 k* G - LL_I2C_EnableClockStretching(I2C1);
8 M; b" l3 K; _) T+ ] - LL_I2C_Enable(I2C1);+ n" a: h/ i) f# E" K
- }
复制代码
! \! X7 w4 d0 h @由于LL库未提供与HAL类似的I2C多数据读取的函数接口,所以需要自行编写函数,我这里是参照HAL库内的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read写的LL库可使用的相对应函数。
3 \4 b2 e0 C9 u2 B+ w& ~* j- z+ Y; A! ~9 ~1 V' t y8 y
I2C读多个数据:
: y& @2 k7 k" s# Y) L4 b
7 o, k/ n* C- M2 o% V2 ]5 E& a- void STM32I2C1_MasterRead(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
' q+ v5 s# J* x# l - {
1 X4 o' a: _" \# X+ D: Q! L4 a8 q - //等待iic空闲3 z6 E& f( D& c& E* U) Z3 D, v
- while(LL_I2C_IsActiveFlag_BUSY(I2C1));
- E! @! E& T0 G2 P) M0 w - //确认iic是否使能5 w5 m- }0 E; E4 C7 n
- if(!LL_I2C_IsEnabled(I2C1))+ z6 _9 S# M1 }& D& F0 S. a
- {9 E3 j4 Z* E) o. Y: @
- LL_I2C_Enable(I2C1);
2 N7 d! ~1 P& Y, E' q2 t4 Y - }
6 v$ ]# ?: C2 s! v# }" h: O - //配置
2 j# L; _) U7 Z4 V) j( F - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_SOFTEND_MODE,I2C_GENERATE_START_WRITE);
' p' C# r7 X. X3 _3 A' Z - while(!LL_I2C_IsActiveFlag_TXIS(I2C1));# ?9 w( D. d8 s# B) w
- * J3 b, B# x$ l0 G4 S
- //写入从设备寄存器地址
8 m9 s4 V1 S, E. D6 n4 h - ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
* O) S! L# I. x$ P, v - while(!LL_I2C_IsActiveFlag_TC(I2C1));
; ]7 K! j6 _6 x W I+ J
" X' c' d+ d5 N8 ^# F' Z8 C- //配置
' x& Y9 a# v8 h1 d - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ);
5 e. r3 u* T0 x$ q. V4 t8 m - 8 B% F* [( {- C% k: D0 k9 p
- //读取数据9 c/ K2 u+ G4 L. L" U
- ucBSP_I2C1_ReadMultipleData(pdata,length);
3 D, N: c; [0 o' L+ N6 H - 6 `; d4 j- @4 I: I7 @7 D6 @; b
- //等待停止完成
! P! Y! `7 Q1 z) s - while(!LL_I2C_IsActiveFlag_STOP(I2C1));% d7 ^) W, @& ^8 L, P
- LL_I2C_ClearFlag_STOP(I2C1);+ K" P9 @- P$ y3 u9 E
- }
复制代码
! E7 I+ K, b) ~" OI2C写多个数据:7 n$ z' @8 j8 A# C
6 o M$ C& j' R6 i4 Y- g
- void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
1 o% M, E `5 V& o+ p; w u - {/ F j& ~# k, X" y; i0 d
- //等待iic空闲7 w! h" }6 W4 C* Y. g
- while(LL_I2C_IsActiveFlag_BUSY(I2C1));: b3 C. j7 D! a/ s% z9 O
- //确认iic是否使能0 p1 x" i2 ] e4 J9 G( y
- if(!LL_I2C_IsEnabled(I2C1))
1 E# ^3 ? j" J - {
3 g5 _: ^" `7 Q2 i - LL_I2C_Enable(I2C1);
7 A3 p6 x7 {) o1 Y - }
, }2 U \3 D7 x3 i; w! F m - //配置为写
( K, Q. l% u; T1 n7 j: X - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_RELOAD_MODE,I2C_GENERATE_START_WRITE);1 R+ ?, M9 \) b S
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));6 J" p" b1 V4 Y3 P. @+ t
9 S8 N( k! Y9 ~1 g- //写入从设备寄存器地址
) V1 u# B$ X! y1 r% Y' Z - ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
4 D! R% P- p8 `/ Q( f* V - while(!LL_I2C_IsActiveFlag_TCR(I2C1));
* E; C+ ~. g- G" D4 n9 P2 ~ - + y0 `; Q) o8 d) ?7 A) t' R
- //重新配置为自动停止模式
, F5 ]+ L: j/ @& V9 n2 [) W - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_NO_STARTSTOP);( }0 S2 x4 s: G$ z
& V7 l9 ]9 m$ L3 M* F5 t- //写数据5 ^1 i+ s" o+ M+ |- u
- ucBSP_I2C1_WriteMultipleData(pdata,length);
+ x- u2 I# j5 ]) r( {" j1 w R - ' H) \3 w5 E; S: {5 u, P
- //等待停止完成
5 X0 r5 X* \$ H - while(!LL_I2C_IsActiveFlag_STOP(I2C1));" r9 d- m7 `( f
- LL_I2C_ClearFlag_STOP(I2C1);
9 q! \) }# a0 k) P6 | - }
复制代码 3 |0 h* M2 X+ r+ e8 y9 B+ ~* H
为了减少代码重复和增加可读性,对读写的一些过程另作了函数;
8 @5 t1 p) \+ j. x0 x, O+ G5 f$ j; ]% t1 o
写寄存器地址:" I3 }: a5 p( K* f1 s
$ ]3 P5 w4 }& Z+ c% q
- void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size)' T( v6 g u* {- a( M3 E3 a
- {! i" ]* q) V4 n2 d/ L
- uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);;7 G4 U0 a9 R# g) R0 [9 j2 A- h5 r# S
- uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);;" G- e) t `8 a9 ?7 i8 R, ^
- 1 j; ~& H: s$ U6 r3 k9 p
- //发送器件寄存器地址
u' }, W0 I) c8 e8 ]5 R - if(mem_size == I2C_MEMADD_SIZE_8BIT)3 \' E8 o- i8 n/ M x
- {) m* {: h, P) k. z
- LL_I2C_TransmitData8(I2C1, MemAddrLSB);
5 d3 N/ H9 m( n7 Q - }else{
1 t. N) s- V7 D3 y- E - LL_I2C_TransmitData8(I2C1, MemAddrMSB);
/ P' n8 Z; C/ c# ?: N - //等待发送完成; y. W' p/ N4 p' f( f) D7 n
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));4 f1 i+ C6 p+ M: G
- LL_I2C_TransmitData8(I2C1, MemAddrLSB);4 K+ _' ]/ I, u
- }. b4 O) }% I, h
- }
复制代码
. F( ^$ k1 i7 n& N连续写入小于255个数据:
0 j3 \0 T+ a6 o% o$ w/ c
* Z3 x9 c# k$ {+ X5 o4 a- void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length)) t$ k0 |4 h2 E. U" @: x, _6 \
- {
+ B4 h- X( \ x* R( Q& I - uint8_t count;5 f! s2 E8 S, `4 d" x
- for(count=0;count<length; count++)
: _% D9 x6 S8 @- } - {3 b; v8 [! H0 U7 r: o" B
- //等待发送完成1 n" m. U2 p. G2 G4 ]7 A4 q: P
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
: H6 n! [/ j8 E% t0 X - LL_I2C_TransmitData8(I2C1, *(pdata+count)); b7 H8 p4 }" P. K/ g. n; y
- }
8 S( Y4 m# A2 o% I* S5 d8 s1 b% B @ - }
复制代码 5 L! R) F& R# h9 Y
连续读取小于255个数据:8 i( ]& X! N# t5 A9 d; Z0 p9 V; V+ m
% w/ R- s, x- l1 M# o- void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length)
/ k1 N" H5 p8 Z2 q# A, z) S: K - {
, ~$ A" L7 |+ V$ l - uint8_t count;/ ~& j+ T/ M' n# N
- for(count=0;count<length; count++)0 L6 L! u; s9 C, q6 x. y
- {3 m: |; x+ z% k7 R. u6 |5 d
- //等待接收非空
, _. ^) v' N" R: F# D5 Z+ u* g, H" V - while(!LL_I2C_IsActiveFlag_RXNE(I2C1));5 N5 h( R8 Z0 i2 V0 K3 Z
- *(pdata+count) = LL_I2C_ReceiveData8(I2C1);- D) U# Z+ O" A2 P4 L
- }
8 i8 a' L0 _* }1 i - }( I" e7 G; |1 O. H4 E
复制代码
1 x3 F s. x* m0 o; a9 f
- B% A" j# O/ Z2 @ |
有收获,感谢分享。