说明:驱动基于STm32G031K6,其他型号需自行做改动。
" w6 ^ d0 _3 j- b" \/ |2 K2 X& }/ j$ [
注:因为之前项目暂未用到LL库的IIC,所以此驱动未经过实机验证。欢迎反馈使用中的问题。) R1 S! T& S% N9 s, Q. J% f
5 j1 w/ l) ]. m% X! rIIC的初始化: CubeMX生成
! L% ^! @# s1 J+ K9 n9 x$ x0 M( b
) n1 F; f& h5 A+ h, D- void STM32LLI2C1_Init(void)5 L( K, m- |+ o4 O; B
- {
9 P3 ]3 H7 z6 q - LL_I2C_InitTypeDef I2C_InitStruct = {0}; P$ I+ W# Y) A; o* U# l) P1 r
- ! x2 j: H4 b# J* u( R
- LL_GPIO_InitTypeDef GPIO_InitStruct = {0};% O |9 _1 O% s% t; f6 C6 R
; U5 I$ @" l8 g' r0 f- LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
6 K4 B( }: S" Z# f. q! C9 Y A - /**I2C1 GPIO Configuration " a, `$ X2 q0 V) _' ]8 R$ b
- PA9 ------> I2C1_SCL. w& R% g& p. O, ~
- PA10 ------> I2C1_SDA
: |; E, X3 c6 Y) V! ] - */
2 A* d+ u% d$ P6 ^" M - GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;
R- D- ~& k" m% q2 s" \ - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
- n* v4 ^8 n9 y, y# Y( _ - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;4 z6 I4 P6 F& b3 g! h/ Z
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;" ?) x. C K8 O- A
- GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
$ J* e6 Z4 P3 D - GPIO_InitStruct.Alternate = LL_GPIO_AF_6;
& D! G. X* e& Y" W" g% q - LL_GPIO_Init(GPIOA, &GPIO_InitStruct);. g. J0 O) q, y! h
- # c+ g3 c3 G" X& I |/ g* P6 _
- /* Peripheral clock enable */. M' e* u; F, e# ^" u3 z
- LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
' \) P& ]* o8 j; j$ O - % e1 K7 F2 o3 t" j
- /** I2C Initialization / {- N. f( ?& [3 A( g7 F6 w
- */2 u+ o7 b3 s) N9 x
- I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;4 E6 \9 h6 d( H Y
- I2C_InitStruct.Timing = 0x00303D5B;& w% b4 y: ?( X- J
- I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
' x6 o+ v s+ I; p( B. z/ z0 v- I - I2C_InitStruct.DigitalFilter = 0;
; V2 R& Y+ t) O0 F - I2C_InitStruct.OwnAddress1 = 0;. z- n. E% \+ A9 i) E/ d5 F6 H
- I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
- d4 z( m6 } ~5 g" `4 G - I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
0 }+ q W' Q) R: l. S7 O2 [4 ?- S* G - LL_I2C_Init(I2C1, &I2C_InitStruct);
; ?" r' S4 ~5 L2 S# } - LL_I2C_EnableAutoEndMode(I2C1);4 Z# m. Q+ Z- ?' y. t* G
- LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);
& B* l! z, u2 S$ D5 A - LL_I2C_DisableOwnAddress2(I2C1);
' c# E2 e- i1 w0 G( f C7 E - LL_I2C_DisableGeneralCall(I2C1);
7 s! a" {- ^; ? - LL_I2C_EnableClockStretching(I2C1);
" {/ E2 T( u4 s; } g+ q4 [ - LL_I2C_Enable(I2C1);
" M/ F- m9 w2 y% R! g - }
复制代码
( D) z1 `" S' G$ G由于LL库未提供与HAL类似的I2C多数据读取的函数接口,所以需要自行编写函数,我这里是参照HAL库内的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read写的LL库可使用的相对应函数。
1 U% }# V2 V0 E% o, Z$ b
* v1 I- B* n3 m6 \/ a- lI2C读多个数据:9 l2 e$ k# {7 X/ b2 \* T8 j
+ b- { l- U2 B) u) _8 Y$ S% D- void STM32I2C1_MasterRead(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length): V$ n" k4 E, P- c/ z; @* H
- {0 K" M) G2 J( P. l
- //等待iic空闲) d, ]1 N0 p) ]( d' a
- while(LL_I2C_IsActiveFlag_BUSY(I2C1));) m/ |, Y4 g8 Q1 t+ Q: v
- //确认iic是否使能4 C4 r6 v& D, M v4 z! p
- if(!LL_I2C_IsEnabled(I2C1))
* v0 J# _+ n% | - {
7 g0 s9 d A1 b- A- ~8 }6 k4 y - LL_I2C_Enable(I2C1);# y( f2 f% l0 Q8 D6 A8 _& Y
- }
) z/ t% W) x5 c/ n& D- G# {- ` - //配置
: d+ {$ U* I4 l7 H! q - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_SOFTEND_MODE,I2C_GENERATE_START_WRITE);
+ C$ r @ F' @% P& F/ I( W; B - while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
! f, T/ z: p/ f- h8 _
2 U0 e/ S1 Y! x* ?0 r8 ~1 j- //写入从设备寄存器地址
! R. r3 h" t- [7 }* ^ - ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
$ M% ~+ t- ~# n6 u% d - while(!LL_I2C_IsActiveFlag_TC(I2C1));
) A# m- Q3 j7 q3 C0 o2 T
. a9 `; V4 c7 N, D! z- //配置
$ `- E. {$ J* C# } - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ);
/ n8 E4 E' Y; Y9 B
. U3 Z" _2 H4 b: X9 B- i8 O- //读取数据 ~' S+ ]" W, k' h2 w3 H8 K. Q8 k) S
- ucBSP_I2C1_ReadMultipleData(pdata,length);
9 k H, H, e" d; C
. r. o, _+ Y4 K. h. v0 @" ?- K, _: u0 _- //等待停止完成1 x, Q5 I) d8 P2 K. e* X: u
- while(!LL_I2C_IsActiveFlag_STOP(I2C1));+ Q! O1 P' t# V$ n2 I' M0 D$ r6 F
- LL_I2C_ClearFlag_STOP(I2C1);0 Q8 p8 }- X4 y; S8 j
- }
复制代码 8 d1 l/ A M: N8 m- A5 k/ Y
I2C写多个数据:
, V( Y- w( K! K1 i& g% p; C
- D) c, P( U* y6 L' e) J# u5 ~# k- void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
: I7 P2 n0 \! @. [& @ - {
5 y& \+ F F. p - //等待iic空闲. Y9 d h2 u$ G" z+ F
- while(LL_I2C_IsActiveFlag_BUSY(I2C1));
$ ]5 t2 _( D4 _1 j) E4 a - //确认iic是否使能
' Z) l6 d4 ^) d Q3 z3 K0 b/ Z - if(!LL_I2C_IsEnabled(I2C1))' j+ E2 z2 w* D9 D# M1 i
- {
8 P5 c/ k0 \7 s- o6 _ p% s - LL_I2C_Enable(I2C1);: S; \6 m5 @" @# h2 e; C& j
- }3 `# a8 }, ~5 n# ?3 N4 c
- //配置为写
8 `: {$ ~" W. D! } - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_RELOAD_MODE,I2C_GENERATE_START_WRITE);
' p) |7 V( I l6 S, ~2 A - while(!LL_I2C_IsActiveFlag_TXIS(I2C1));) N) f6 c6 |+ q' H3 L: ?
) H3 e1 n- Y' V! U ?+ z) m- //写入从设备寄存器地址3 m; O& q7 z' [/ @8 p! `0 D7 \3 W% I
- ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);7 C; l: V- ?- }- C
- while(!LL_I2C_IsActiveFlag_TCR(I2C1));
% `8 A) `0 H; K+ ^2 \
) a+ x* F$ }3 `3 ]7 ^- //重新配置为自动停止模式
7 U, I5 b( z1 O* { - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_NO_STARTSTOP);
b1 y' v; L# E- M2 I8 p8 b# r e& Z
& ~9 n( \) U6 }6 B1 Z- //写数据
% e3 Y- e: h- b, K2 k8 q - ucBSP_I2C1_WriteMultipleData(pdata,length);7 f/ M# _/ i6 P3 O
- 2 l5 B- a* l$ t% ]- l+ f1 }
- //等待停止完成- _* C! h& h4 @; c0 J- x0 K
- while(!LL_I2C_IsActiveFlag_STOP(I2C1));
0 r' M* |1 k3 x0 t" L6 c3 k/ m - LL_I2C_ClearFlag_STOP(I2C1);+ q, J2 n7 a% `9 q; a3 |$ T E( Y' P
- }
复制代码
! ]% m* i( E( O H" f为了减少代码重复和增加可读性,对读写的一些过程另作了函数;
* ]/ r; A3 O% C# v3 q. y) P5 O/ ^. `3 y
写寄存器地址:" S, a) w% U' _4 C; I7 C
& M- Y" [; \8 @% a5 i# J8 s
- void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size)
5 a+ r# T' k7 S3 Q - {- w* R' l3 |$ g
- uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);;
, L o0 J7 A6 u9 I - uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);;
+ `1 ?% l2 P- N" D9 ^# q4 U
, [# C2 E7 L9 x2 Y' n4 g7 e- //发送器件寄存器地址
* S2 J I1 I9 n - if(mem_size == I2C_MEMADD_SIZE_8BIT)
& @( f2 J8 A! k G5 ]) c - {3 H. t5 N2 ^4 \. v9 B2 K' w
- LL_I2C_TransmitData8(I2C1, MemAddrLSB);. q5 c; x+ M/ q9 m4 z
- }else{2 l: h9 h6 p; G7 G
- LL_I2C_TransmitData8(I2C1, MemAddrMSB);9 L6 [- |( T; W: \% t
- //等待发送完成 u9 g r) m8 A* m+ c
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
$ C1 R% M) u8 |2 s( ? - LL_I2C_TransmitData8(I2C1, MemAddrLSB);0 D8 D5 I+ y/ t0 y" G m' O' }& @" B
- }3 O: s4 w" B( J/ ]. i( b- b
- }
复制代码
9 \- ]& S. v- f- D连续写入小于255个数据:- {2 D+ Y% ]5 |9 p9 G% I: z# y
6 C) b! t& k) H. ?
- void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length)) p* C% _% s/ j1 a, Y
- {
9 J$ Q) O/ G( w7 {# d4 p - uint8_t count;3 a C0 i: }, n0 z; \9 M' z
- for(count=0;count<length; count++)" a$ L+ f- I& H: H
- {
* g1 m8 y m$ x1 O; y% J- C0 a - //等待发送完成7 s/ s! @0 w. n' J$ {1 T/ R7 t
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
+ h) l! a c1 g1 ~ - LL_I2C_TransmitData8(I2C1, *(pdata+count));
, P3 z" Z3 g1 H2 X& Q - }
7 {) f+ A$ r( H: U/ C - }
复制代码 7 S1 m/ J6 T8 e3 ~) @
连续读取小于255个数据:; W" o- {, ?* N. X
; E2 a+ @3 | c! P$ G
- void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length)
* i5 X8 c4 _- A* L2 p3 i - {
+ i- I s% r( i - uint8_t count;8 B8 s* v5 c9 J( q
- for(count=0;count<length; count++)
. T' H; d) E1 f: T. u) \. u - {
0 a$ b' B, H0 n; z8 o4 ?0 d" R - //等待接收非空/ }0 b% ^5 z% @7 C8 @% A, P: @4 t
- while(!LL_I2C_IsActiveFlag_RXNE(I2C1));5 B7 H" N. A$ B3 V9 J% x* r& q" ]* e
- *(pdata+count) = LL_I2C_ReceiveData8(I2C1);! D$ j* ~" K* M2 g
- }
$ x% k5 j: J# y7 D0 [/ z - }
9 t# X2 I$ f8 a2 n9 a' X; P
复制代码
& g4 C$ y: J5 E/ I B7 h. v7 S4 w1 w9 W: w- O; C4 I# r0 s1 N
|
有收获,感谢分享。