说明:驱动基于STm32G031K6,其他型号需自行做改动。
/ d$ e4 B* @: Z( v: {) |; l* q7 q- G
注:因为之前项目暂未用到LL库的IIC,所以此驱动未经过实机验证。欢迎反馈使用中的问题。
( m! u( m; R' V( Z0 H
5 y5 c* n" G' Z- @' ], yIIC的初始化: CubeMX生成
, H& _7 H9 q3 R5 e2 G; C5 U6 F( M5 |4 z- h K! F
- void STM32LLI2C1_Init(void)3 h. T% k' r* d9 S
- {; k- U8 f+ d3 N8 f
- LL_I2C_InitTypeDef I2C_InitStruct = {0};
6 E3 E! C5 u& J
~0 p( M: C Z/ h- LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
9 q: Q* Q+ B; V+ j - % K4 s2 x- j, n; ^3 G$ W
- LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);$ c2 d( P1 [' M$ Y2 E8 Q
- /**I2C1 GPIO Configuration 6 C- A/ o5 K3 r* o) _+ x
- PA9 ------> I2C1_SCL
1 a- A6 F3 b1 n; c6 n! n2 G - PA10 ------> I2C1_SDA
5 Y% h" }! `# h - */" f5 y% A, [6 @2 F8 N0 w- v
- GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;
) D1 G# G$ O5 ?9 ?" a! z - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
* C! h+ J8 y" e" P0 `+ d6 }$ j - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; o7 {7 q& y. ^1 w; N# A
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;* M- `8 M1 G& ~# a; Q; e
- GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;6 t) U G# p9 C% h e" b! V# \
- GPIO_InitStruct.Alternate = LL_GPIO_AF_6;
" y+ K% [. v# ^7 n' x8 Q - LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
: E* D, L! i9 |7 l. O4 I - ; k' ], G E" g1 v( e3 u$ ^. [9 j
- /* Peripheral clock enable */4 n" f) f. _5 ]1 h5 l; e
- LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
# h. l% e/ A1 F' L: U - ) H' `1 P% a6 \. m# Y
- /** I2C Initialization " m. C) K/ P) @' N
- */5 [6 ~+ t8 R# a' Y1 A( ~; Q
- I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
0 o/ k, g& T0 L4 K$ @0 l - I2C_InitStruct.Timing = 0x00303D5B;
1 K1 K8 K# A3 a1 ^ - I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
! q. _" L# U- C0 q - I2C_InitStruct.DigitalFilter = 0;
8 [, s# Q2 {# l) H% y - I2C_InitStruct.OwnAddress1 = 0;
; d; l: _6 W# G - I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;+ Y2 s2 l ^* f5 Q( L
- I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
: b% N' {8 ]6 U+ u' F( T% `- { q - LL_I2C_Init(I2C1, &I2C_InitStruct);: r4 _' G8 e1 D- v! S
- LL_I2C_EnableAutoEndMode(I2C1);
" t- W, n: H) B% N - LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);* |9 C- d" f% D1 B9 J2 x! F: T
- LL_I2C_DisableOwnAddress2(I2C1);
+ I" N, e, w# n9 D) o1 h1 T5 e - LL_I2C_DisableGeneralCall(I2C1);, [: o% A; b. w/ ^& v, l4 ~
- LL_I2C_EnableClockStretching(I2C1);4 C4 L1 w7 g) A+ {- ]: n
- LL_I2C_Enable(I2C1);& h" d) B. B. e, M
- }
复制代码 : F/ y* C; L7 r3 K9 s
由于LL库未提供与HAL类似的I2C多数据读取的函数接口,所以需要自行编写函数,我这里是参照HAL库内的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read写的LL库可使用的相对应函数。
1 x4 \/ g2 W! o1 [6 P5 q: w+ a0 L+ s7 z4 c
I2C读多个数据:" @ t5 o/ k1 o E, D J1 p4 s
6 F4 r4 G, r, w( V ]' L1 o7 N w
- void STM32I2C1_MasterRead(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
3 ~, J5 D0 q3 q8 l% j - {3 _, D. t* r; \% I% l
- //等待iic空闲
& I$ C# \3 _+ y! K! @/ m+ Z7 h( p8 B" H - while(LL_I2C_IsActiveFlag_BUSY(I2C1));3 d; w# [, o1 Z* m8 A! V5 C
- //确认iic是否使能/ j) ?8 ?- H3 [/ @
- if(!LL_I2C_IsEnabled(I2C1))) a X% @4 w" b. A/ v8 O2 u% d
- {
& \0 s, r# E2 K5 t4 j( c! g - LL_I2C_Enable(I2C1);
' N/ _+ l5 Z9 M) S t - }
* T* \4 ]/ |) o9 N3 u n; P - //配置
, N" T; m- ^5 M$ M! a - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_SOFTEND_MODE,I2C_GENERATE_START_WRITE);
) J' a0 p0 x1 Z5 o - while(!LL_I2C_IsActiveFlag_TXIS(I2C1));6 P6 j# c9 M! @( Y
- " A+ ~* A5 o% `; e
- //写入从设备寄存器地址
& m6 g3 L& ?& Y( a) T/ N( v. z6 S - ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
, P P' m$ w8 z, x! K, L - while(!LL_I2C_IsActiveFlag_TC(I2C1));
0 A" V( E/ i( w/ l- t+ B+ R - & g. I; F! ?0 R8 ?, q
- //配置
6 p+ N$ f- c- z! L# R" o - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ);6 D, _8 M! u/ S
- - z7 G* x, U& Z* w. x6 W$ ?! N
- //读取数据
" `% i/ X+ Y+ C, y6 J. L - ucBSP_I2C1_ReadMultipleData(pdata,length);
1 ]0 l8 o( I! H - : P4 k. E1 Z a: b
- //等待停止完成8 o' ~, R4 M) t+ p# V$ S
- while(!LL_I2C_IsActiveFlag_STOP(I2C1));, _, r% e" S4 h8 R0 Y% d+ M9 R
- LL_I2C_ClearFlag_STOP(I2C1);
- l! Q+ G% u/ K& ^ - }
复制代码
( N% J$ A" `( E% L9 [I2C写多个数据:# x: Y& J- s" K0 L2 @
C9 h* _0 L. q% B$ D) G- void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)) [9 S# |4 G! C
- {3 j1 m% ^' A1 _ W w
- //等待iic空闲0 V$ d+ F# S0 d, v" p
- while(LL_I2C_IsActiveFlag_BUSY(I2C1));* [! ]# r4 X9 Q% F j
- //确认iic是否使能% o, J5 G( b: b
- if(!LL_I2C_IsEnabled(I2C1))0 T. c( h( w/ }% O% _
- {8 X0 S. ^* _2 c- V8 z5 O
- LL_I2C_Enable(I2C1);, U5 D2 W: u0 n# B
- }
+ V- ]1 N5 W0 N" p6 x - //配置为写( Q& Y( q3 J5 ?. G) L7 m& g0 k8 y
- LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_RELOAD_MODE,I2C_GENERATE_START_WRITE);5 O3 L( i( \1 u' }& w
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));) E- \6 J" H- n& Y8 c+ T
- ; E6 r: ?/ X @$ T8 V
- //写入从设备寄存器地址
3 Q7 s5 r; H* X" M - ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);# z/ D8 c! |' K' M5 o
- while(!LL_I2C_IsActiveFlag_TCR(I2C1));) e. m* x, Q9 S4 D6 Y
. q- \6 M/ G; z6 Z _5 z- //重新配置为自动停止模式3 ]" ~! K9 h/ ]( Y; y+ L4 L8 M. ^
- LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_NO_STARTSTOP);
& M. [9 ~ W( d( m! n5 n' i - # q, ]4 ~# `8 R3 A3 N
- //写数据( W( \+ @. z, F
- ucBSP_I2C1_WriteMultipleData(pdata,length);( s t4 A: I; J8 f4 Y
- 6 w: K* N- r; |# p
- //等待停止完成& t* x" w$ a& @
- while(!LL_I2C_IsActiveFlag_STOP(I2C1));) { f& \7 n/ {, I
- LL_I2C_ClearFlag_STOP(I2C1);
* H5 m( d( `; x7 n - }
复制代码
6 b X s& ]3 g+ \; K* o2 Z+ D为了减少代码重复和增加可读性,对读写的一些过程另作了函数;; V4 b8 Q/ W& |8 H- }1 I% U- J* c
+ ^; H' f$ d6 A
写寄存器地址:: ^$ z: n' H& y* M3 }6 F8 y
! T& {- g( q: c6 @9 }
- void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size)- `- p& K- v$ J: X' X
- {8 F3 I' d r! t
- uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);;
8 B$ R4 c; N4 j g9 h - uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);;
( z) k, m& @+ z: o - 1 i. W6 x' D0 P& h" Q9 X4 f
- //发送器件寄存器地址
2 `$ b+ ?1 ?- m7 p# ` - if(mem_size == I2C_MEMADD_SIZE_8BIT)
8 E: y% h$ a7 | - {
% C& @9 y/ ~( S* S; N# }( w; c3 X - LL_I2C_TransmitData8(I2C1, MemAddrLSB);
4 L, S9 j; e" e" I$ K: r - }else{
* g( t! t! r- O2 z2 Z6 m - LL_I2C_TransmitData8(I2C1, MemAddrMSB);7 r! ]7 _: f7 o1 {& ]' v( y/ A
- //等待发送完成, O M8 ]8 H* L( z
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
1 d3 V1 s: u1 x$ J5 z - LL_I2C_TransmitData8(I2C1, MemAddrLSB);
4 f8 W/ |% Y' p" T& Y a - }
. ]3 A/ T/ P3 o" @ - }
复制代码
. s& A) j/ J, d( U* C连续写入小于255个数据:' n8 V) K1 q: f1 I
9 m& \5 Z& M) {! N% R! j) \- void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length)8 b" L* O9 B1 O2 n0 U( W
- {
- k& q5 X7 U( I ? - uint8_t count;# J4 i3 q, x+ j) \7 P) L0 b
- for(count=0;count<length; count++)$ O# l( Y7 c m* ?, a( ?8 D
- {
2 X$ X( w0 Y6 ?$ r. `) M! U - //等待发送完成. \4 Q' X& ^5 h/ q' U
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));8 S3 k4 X x0 N0 c! x
- LL_I2C_TransmitData8(I2C1, *(pdata+count));
/ z1 @9 `: z& H6 G - }+ [. h8 g2 }7 m7 [0 B! J( T! o
- }
复制代码
+ h' w7 ^ a s- h. ]: E4 C连续读取小于255个数据:
+ y* G8 p! S* V
: u2 {. h2 x+ p, c+ N& J- void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length)3 ?$ [4 e" }% d. S9 x0 ? A
- {
" I [4 W2 D, j \ - uint8_t count;& v G9 Y" s& h9 G
- for(count=0;count<length; count++)
m/ ~0 ]; i/ G0 e - {
) H. C) m* D& p, `9 M - //等待接收非空
) b7 P; ~8 A& j4 t. s+ n - while(!LL_I2C_IsActiveFlag_RXNE(I2C1));: F0 M( h& C% x. S
- *(pdata+count) = LL_I2C_ReceiveData8(I2C1);0 U; ^. ]# w4 R6 ~' i) O9 Z9 s
- }& J- ^" E) `; s
- }6 L u" C6 ^8 ^" ?/ v( H; D/ k# T. r
复制代码
5 c! i! _# \& A9 C7 ]& ~$ J9 I& A6 f/ Z& S1 {# O. |9 o
|
有收获,感谢分享。