说明:驱动基于STm32G031K6,其他型号需自行做改动。
$ Y: W U) x/ k) P* p. ?1 @' \3 G- I3 q7 T G# p/ f# R
注:因为之前项目暂未用到LL库的IIC,所以此驱动未经过实机验证。欢迎反馈使用中的问题。
$ a5 Q, ^; D8 O( H6 U2 m, W" O; P" I9 V% J5 D$ q
IIC的初始化: CubeMX生成
! `( _/ ?4 G4 L" G' C* W1 f/ R$ f u$ Z, [
- void STM32LLI2C1_Init(void)
' j4 }& r, R( v" q- A. E$ g: b. T - {
! C0 o4 N8 t6 u. E* J - LL_I2C_InitTypeDef I2C_InitStruct = {0};9 A4 @2 P3 @ R$ E2 n5 \
- 0 C$ e5 Z% V! r3 T9 Q
- LL_GPIO_InitTypeDef GPIO_InitStruct = {0};4 D: p) @" J* X, B
~6 t+ v0 C# s- LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);, a/ n& Q( z& q1 [" L
- /**I2C1 GPIO Configuration
: g4 ^+ _- z9 g( ]# _" ^7 [7 b - PA9 ------> I2C1_SCL' r& E8 ?" L; d6 X9 a
- PA10 ------> I2C1_SDA . r2 k7 W% k" Q9 ?3 a7 E- j8 w) U
- */2 ]5 w' u# M7 O' J9 `2 v' t% s& h
- GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;
$ n, `8 y" ` y6 c A - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
- g8 i3 w# z W e - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
- C% i, v' ]0 u+ m: m - GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;- {* e+ F- T8 v( @& o" E+ g
- GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
v% X5 o* N. d; l' Z& G - GPIO_InitStruct.Alternate = LL_GPIO_AF_6;6 b0 }+ m/ n( f7 p+ k3 q4 f) \
- LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
! C/ x7 e! D) X7 {: d' l - s% m7 P. r% h
- /* Peripheral clock enable */) @+ ^7 M0 G: N% P# X: ~" @/ V, {
- LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);. V* x1 M/ q2 x
- # Q' J2 V0 ^: S0 _% A
- /** I2C Initialization
% O" _5 N6 o4 E- h E M, D - */
8 t) n, ]% N/ H P+ S0 N; t - I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;0 m- J/ ]" h( s& ? _, z0 ^
- I2C_InitStruct.Timing = 0x00303D5B;
" Y) |# w1 ^# v* m - I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;3 J) h }" t5 V! R, u }4 X5 J
- I2C_InitStruct.DigitalFilter = 0;
* v9 J: l+ \! ?& |& I8 B, M/ v, e) H6 o - I2C_InitStruct.OwnAddress1 = 0;
7 |- m4 ]' V( |3 ~ - I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;3 J1 m6 o! P' m) I+ G. M
- I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
6 ^5 J; |/ X7 G3 ], ]8 \! D - LL_I2C_Init(I2C1, &I2C_InitStruct);
" u) `: P( f [8 C0 f - LL_I2C_EnableAutoEndMode(I2C1);
5 F3 c/ h' N0 G/ a - LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);) |& z4 \1 |6 c5 P G% z
- LL_I2C_DisableOwnAddress2(I2C1);; _, Y- N( m& _
- LL_I2C_DisableGeneralCall(I2C1);: b; M2 X3 @" o' Y. @
- LL_I2C_EnableClockStretching(I2C1);
- v& _$ O) s: l' ?% i$ J" ` - LL_I2C_Enable(I2C1);
8 `% t, n# E! C" E$ J6 b - }
复制代码
3 ]2 F; m, i) t8 o- n8 o4 A4 R由于LL库未提供与HAL类似的I2C多数据读取的函数接口,所以需要自行编写函数,我这里是参照HAL库内的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read写的LL库可使用的相对应函数。
- |9 F$ F. S3 o$ ?% K
: _- X. P, ]6 O( FI2C读多个数据:- a# @( A: b2 [2 t1 y5 T0 [
3 W) S# d$ x% ~7 _1 Y2 j* g
- void STM32I2C1_MasterRead(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)0 W2 T( ~4 r' a: T
- {
8 n& h- s5 W1 g T/ N5 \( S) a. s0 y - //等待iic空闲7 U8 w6 t& w4 b
- while(LL_I2C_IsActiveFlag_BUSY(I2C1));
2 C: l2 [1 n' {' p( p# v - //确认iic是否使能' B- b7 C2 p( ~* Q& v: o$ \# E& o7 I
- if(!LL_I2C_IsEnabled(I2C1))& R6 h2 s: |) r$ Z8 u
- {
6 B, W$ L/ J& j1 R - LL_I2C_Enable(I2C1);
: _" S8 s. t/ O5 } - }
/ B3 v# `0 R8 g - //配置5 C# Q2 e3 \& C) A% g
- LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_SOFTEND_MODE,I2C_GENERATE_START_WRITE);
& E1 ~% F% g4 a: B0 U6 [" D/ J$ J# @ - while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
9 m8 G$ Q! M+ |
& S5 D, Y; h6 p; L4 Q6 J% ]- //写入从设备寄存器地址
( K; Z5 a2 ]4 U1 C - ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);& f2 D* n5 v. ]% R! s
- while(!LL_I2C_IsActiveFlag_TC(I2C1));
* w: W& F& z2 f. O8 |
% `% w5 L) P# z7 P1 Z7 \5 @1 k- //配置
) X9 `5 T+ o7 l2 o: R - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ);
6 v! d1 k6 ]' p+ r - , A+ l6 j3 c [$ D
- //读取数据+ C2 D( @- z V6 c' i2 u/ I1 u
- ucBSP_I2C1_ReadMultipleData(pdata,length);, A, P5 q1 E; ?; @! w+ U; W
- ! c5 e7 Y/ Z) z8 m4 J# L- w0 M( p3 N3 T
- //等待停止完成5 A$ @8 Z$ Z0 a3 d3 k
- while(!LL_I2C_IsActiveFlag_STOP(I2C1));
* m, P$ ]9 A! @* W- d, d3 M - LL_I2C_ClearFlag_STOP(I2C1); b6 J7 l! G( a1 Q
- }
复制代码 " C7 G/ o* g% S2 d! }, d
I2C写多个数据:
4 r$ \& S- s; |& x
, w @6 n$ u4 A1 S- i- X8 w- void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)! V) y7 K. K7 D% e% s+ ~5 ?
- {
0 E, u9 K* i: U: T {/ t8 }! A - //等待iic空闲
: @% e; W$ @( C/ Z9 S - while(LL_I2C_IsActiveFlag_BUSY(I2C1));6 E4 a: d+ `0 ?; x: A# V. y" b4 S
- //确认iic是否使能
$ F! h9 ?$ ]; R% F - if(!LL_I2C_IsEnabled(I2C1))
t0 S- j5 ]. }6 ~ - {
" Y- V# ^. I# P, D/ v - LL_I2C_Enable(I2C1);- a, z( ~/ n; ~3 H
- }1 M" i: g6 y9 T" `: z# A* I
- //配置为写- Q9 F$ m. j4 f! r" c& o
- LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_RELOAD_MODE,I2C_GENERATE_START_WRITE);# T6 f+ _, `# c/ ~1 k* I# C
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));& v+ ]* b: j. _( L! T
- 6 |2 p5 k# s: r" ]3 G) {
- //写入从设备寄存器地址% g( @- e/ p6 B8 P' Q* U; V
- ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
1 o% L" Z. M$ W6 r( |( g, l - while(!LL_I2C_IsActiveFlag_TCR(I2C1));
- Z, A# K5 T) Q9 ]+ X4 W9 k
4 Y$ _8 q4 N1 b- //重新配置为自动停止模式
1 R, b7 `4 A7 x" B2 P5 K - LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_NO_STARTSTOP);
, i& j5 E% ~$ ]9 s' \8 ~3 O - , E: w0 D1 [7 @6 X Q
- //写数据
3 v; y, h# G- | - ucBSP_I2C1_WriteMultipleData(pdata,length);
" h, L2 r- q5 N7 p+ V) }4 j
# Q6 ?: l! ]8 I+ t/ P- //等待停止完成8 f6 @- J3 r: @% D6 S
- while(!LL_I2C_IsActiveFlag_STOP(I2C1));
3 A, Q0 p& ]- u: e* L - LL_I2C_ClearFlag_STOP(I2C1);: }9 F) s6 ?; c) W2 K) j9 z! G8 I) X
- }
复制代码
# c" t3 c" F: g6 e i9 g为了减少代码重复和增加可读性,对读写的一些过程另作了函数;9 U2 E/ Z9 k3 b( N6 C
E1 t" E" \( M2 [
写寄存器地址:
" t$ g1 h' ]7 i1 J, z2 _6 j1 o6 R/ |8 @% b, ?1 k, _5 q
- void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size)2 |! e6 _& J9 F2 k# f' t6 H" L; x7 n
- {. o: @6 {( |8 G+ _4 h' t5 @
- uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);;5 a/ }) H' `! a3 ?2 h! [( @; v
- uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);;
8 W. Z% m& g) X - & E7 F( z% j8 B0 b" m7 h+ M4 p, H
- //发送器件寄存器地址& J: `0 q1 {7 j+ L; H, l$ n
- if(mem_size == I2C_MEMADD_SIZE_8BIT)
6 [, W |! }' x - {
1 I, t$ ~; l$ @% @. r, H1 m - LL_I2C_TransmitData8(I2C1, MemAddrLSB);
- G* L: V5 T' h: e, ~2 @6 P- m2 { - }else{
# E* Q! k* F( a. C: r+ W+ N7 e& A" A - LL_I2C_TransmitData8(I2C1, MemAddrMSB);" \2 P; [( L* c _" Y1 H
- //等待发送完成
3 I7 T/ V) Z! S - while(!LL_I2C_IsActiveFlag_TXIS(I2C1));& L# M5 h* l# Q& G, K0 L- o
- LL_I2C_TransmitData8(I2C1, MemAddrLSB);2 V. j% k6 b3 ]6 m' h
- }
5 R* M. ]" h5 L* S - }
复制代码
3 u- q0 n2 c U连续写入小于255个数据:
* a2 X- K8 F J0 _! ?, C1 {
+ o: T/ Q, Z7 I' s! p) Q+ A- void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length)& T7 T7 O) d) G+ ?4 K5 M
- {& R# N2 Y8 ]7 X4 ^; |
- uint8_t count;! J2 z: N9 s. P
- for(count=0;count<length; count++)
: M& @- x s$ r* G5 e5 z - {
* d! }" A7 Z- U$ F( ~, T - //等待发送完成) g2 j- n# M& S9 s2 T! c2 F
- while(!LL_I2C_IsActiveFlag_TXIS(I2C1));6 q: [5 }) A, g. |
- LL_I2C_TransmitData8(I2C1, *(pdata+count));
6 e4 M5 a" s# u' c2 P6 M0 \ - }2 l$ ?4 z l! V W( {& W* u
- }
复制代码
4 u8 b8 W: p+ r3 Y3 s6 P连续读取小于255个数据:
8 t9 W m C! L) Z! Y2 O$ r8 {8 [) [* O" ?2 u
- void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length)2 y5 b" p6 _& x% C! j, h
- {& A9 c5 T' P' \7 Q+ H1 K% A# o
- uint8_t count;/ ~" [9 W; ^% h9 V* A8 ?; M
- for(count=0;count<length; count++)
) x4 R R. e9 C" J$ i$ L - {
. [$ q* c# H( ~ - //等待接收非空/ ?( g( O. B: ?" {+ J" l0 b
- while(!LL_I2C_IsActiveFlag_RXNE(I2C1));" d2 ]5 r2 v+ n6 t9 V2 D P
- *(pdata+count) = LL_I2C_ReceiveData8(I2C1); R/ X$ | g8 B
- }
4 I4 ]/ c2 o: \+ b - }, m( b x) f$ Y1 v$ Z
复制代码 - A8 i% u% u$ j1 O9 q0 s2 [
, L9 t% c# W9 U7 k/ A& ?
|
有收获,感谢分享。