你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32G031K LL库的使用 - IIC

[复制链接]
STMCU小助手 发布时间:2021-11-10 22:53
说明:驱动基于STm32G031K6,其他型号需自行做改动。
( Q9 O& C, d4 W4 o8 o4 H9 E. X+ s* k& A- P) q
注:因为之前项目暂未用到LL库的IIC,所以此驱动未经过实机验证。欢迎反馈使用中的问题。
0 E4 c/ u6 }- N
: h0 n+ ^2 G4 i6 w( }* s, }IIC的初始化: CubeMX生成
2 x! Q9 \  a  b1 Q# z9 X3 i8 v
! V9 e7 ?5 {1 F
  1. void STM32LLI2C1_Init(void)
    . B+ U6 Y7 d: z, N7 o3 j
  2. {4 L1 `% y. N" q% o" \3 s
  3.   LL_I2C_InitTypeDef I2C_InitStruct = {0};, a% a9 _, i- C8 ~
  4. + F3 z  u) s6 B: s
  5.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    + @) a( Q$ I% }; ?; s7 k

  6. $ I1 T2 ]# n* O$ o% L- ?
  7.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);. `+ _9 R- I" d" V9 K# t$ _3 e
  8.   /**I2C1 GPIO Configuration  
    8 @9 Z, y8 e4 `5 T
  9.   PA9   ------> I2C1_SCL2 B1 Q, H0 v8 b  s; x# J: e. Z6 p
  10.   PA10   ------> I2C1_SDA 5 |, }' T2 k) o0 A7 Q5 E+ H; p
  11.   */
    ( h+ Q% U* B8 O3 C2 z, }  u
  12.   GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;+ [5 p- ]/ g5 C. r' I' f
  13.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;: U; P$ u: o- ^3 q# F5 @
  14.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;0 ^  S+ q, X2 p
  15.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;9 T9 u* A4 i/ E3 Q# G3 h
  16.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;8 D, w* G# ?/ r7 w  U9 V# i
  17.   GPIO_InitStruct.Alternate = LL_GPIO_AF_6;
    - K3 I$ t( J/ K' W! @
  18.   LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    6 o3 o8 V$ l" w3 M( L0 N. q0 B

  19. ! g  L- X6 |! _
  20.   /* Peripheral clock enable */
    0 P3 q2 [; @1 l+ J1 x5 q
  21.   LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
    6 }* b! ]6 g* \
  22. + S# r5 G* l, r" F7 O
  23.   /** I2C Initialization % M' w, r- L" C8 y
  24.   */3 Q+ B: R6 X- e' I0 a
  25.   I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;5 J9 V! d9 C0 |
  26.   I2C_InitStruct.Timing = 0x00303D5B;
    ) B; z7 H: n0 z1 i9 q) C2 F
  27.   I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;7 e# K7 n) l4 y1 g: t* W3 T" W
  28.   I2C_InitStruct.DigitalFilter = 0;
    ; N$ B& f) B5 t, A: H% P! G
  29.   I2C_InitStruct.OwnAddress1 = 0;6 f0 t9 h% Y% {0 Y
  30.   I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;2 w1 R+ N) ?; W, Q" R+ ~1 }
  31.   I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
    / M% t% n# W! ^1 I, A
  32.   LL_I2C_Init(I2C1, &I2C_InitStruct);* U& {4 W3 ^/ X9 ?
  33.   LL_I2C_EnableAutoEndMode(I2C1);
    4 c. @& k2 J1 K% p
  34.   LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);
    4 J' [3 T% R# I/ h$ Z& X2 G3 h
  35.   LL_I2C_DisableOwnAddress2(I2C1);
    ) H1 ^; S7 T2 D+ @8 z1 D. E) g
  36.   LL_I2C_DisableGeneralCall(I2C1);
    , \3 U8 H0 ^. x0 F9 k9 d/ m
  37.   LL_I2C_EnableClockStretching(I2C1);) }9 {) C% S/ o, w, f% T; |) r
  38.   LL_I2C_Enable(I2C1);
    $ r6 e! q: X( M0 ~" r
  39. }
复制代码
4 S- l/ ^" X5 U1 o
由于LL库未提供与HAL类似的I2C多数据读取的函数接口,所以需要自行编写函数,我这里是参照HAL库内的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read写的LL库可使用的相对应函数。
& G) u$ Z2 v- `. y. k4 Z" K8 t  o6 O# W$ ^1 j
I2C读多个数据:
+ N. @. F+ F5 b" N, }. G, t4 b9 H, P0 ]9 S
  1. void STM32I2C1_MasterRead(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
    . @* ~5 I- i- a
  2. {
    5 |8 E( Q& ]  ]! b! \- B
  3.     //等待iic空闲$ t  h# t7 `( \
  4.     while(LL_I2C_IsActiveFlag_BUSY(I2C1));6 i$ l: ?+ m8 _& V% u% P
  5.     //确认iic是否使能
    . {! `2 Y( n' X- s( q$ x) ~: ?
  6.     if(!LL_I2C_IsEnabled(I2C1))% W( _! `( r+ n4 k- g; S% E+ {
  7.     {* B  I2 I" H. H! `7 [1 l8 t
  8.         LL_I2C_Enable(I2C1);
    2 ]3 H" q3 z4 Z; x  T" m  A
  9.     }( S7 R& Y4 D6 w1 S' f
  10.     //配置! G+ H: k. a! t* a! ~" \& m$ M
  11.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_SOFTEND_MODE,I2C_GENERATE_START_WRITE);
    ; K: t2 H7 O) I' B
  12.     while(!LL_I2C_IsActiveFlag_TXIS(I2C1));  H( |" V; A# s
  13. # w+ ]4 k7 V8 C8 V4 l
  14.     //写入从设备寄存器地址
    4 T2 n2 v3 U1 _7 r
  15.     ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
    6 Y+ z+ w' i+ g: c
  16.     while(!LL_I2C_IsActiveFlag_TC(I2C1));
    / O+ A! u. w3 r* r
  17. : G, J  x8 o/ d" o5 z" T
  18.     //配置/ E6 D$ v# s8 q, `* a# N
  19.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ);
    . l$ p  S* m6 q3 K+ |
  20. 0 b+ Q/ P8 U8 k) g$ S( J
  21.     //读取数据1 `' `0 R0 X8 a+ ~8 ~# z
  22.     ucBSP_I2C1_ReadMultipleData(pdata,length);' W) O! ]4 w2 d4 D- t! `% s! q2 d5 z

  23. / D8 j7 v* l, D4 M
  24.     //等待停止完成: ~1 L3 a1 t' f/ g+ k! D
  25.     while(!LL_I2C_IsActiveFlag_STOP(I2C1));
    " w0 x- B4 y, ]% k8 d* `  x0 b3 \# V
  26.     LL_I2C_ClearFlag_STOP(I2C1);
    ' E7 f& Q) T& Q4 ^6 k7 m
  27. }
复制代码

) A9 ~5 e( ], f- ~/ vI2C写多个数据:9 M% J, a7 G" ?6 ~( d$ v3 s& g4 L* U, g
+ z' R! j# J6 a
  1. void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)* W; T0 h6 O$ W3 o+ f9 b9 z: b
  2. {: n& c) o( Y- h4 g% W
  3.     //等待iic空闲
    3 x/ N" y4 f6 j" Q" t; B, f  `
  4.     while(LL_I2C_IsActiveFlag_BUSY(I2C1));
    6 [+ Q3 [" K' D' q- _0 D+ r
  5.     //确认iic是否使能
    , ]) k) P8 W4 F" h" A! }7 _
  6.     if(!LL_I2C_IsEnabled(I2C1))
    9 w" c; z7 s3 K" _" J2 T7 S& n0 h# U
  7.     {
    $ P, c/ Y) s% F4 S# e: a
  8.         LL_I2C_Enable(I2C1);
    7 C  y: O6 B+ v% P
  9.     }
    : v% o2 L  ?  E6 u4 g. B! n/ |
  10.     //配置为写1 U5 f3 t+ `( \8 d7 z6 q
  11.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_RELOAD_MODE,I2C_GENERATE_START_WRITE);
    , S( M# [) Z( p. S# ~
  12.     while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
    & j6 f% i- }4 I. D0 }
  13. / d( b6 r8 b6 o9 i, d6 a
  14.     //写入从设备寄存器地址" O1 g1 M$ l" J4 t8 D! r( w
  15.     ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);2 u( J3 R5 x4 a: k8 E& i
  16.     while(!LL_I2C_IsActiveFlag_TCR(I2C1));
    1 w7 H( S1 P% f1 ]' J0 v4 {  j
  17. 6 d; Z; b' P; l$ O: `$ {# P
  18.     //重新配置为自动停止模式+ L6 m. G: |) q! Z/ W3 i
  19.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_NO_STARTSTOP);
    5 A9 K/ H' w1 n6 W: z

  20. 1 F( b% b, x1 `' W
  21.     //写数据6 o9 m# h. C, _" e+ l, |
  22.     ucBSP_I2C1_WriteMultipleData(pdata,length);2 X$ E: W. j! ~5 [* M9 D9 K

  23. 0 G' F2 P' Z# K4 o
  24.     //等待停止完成( O, `, h4 o/ a% e$ l2 P: E2 |
  25.     while(!LL_I2C_IsActiveFlag_STOP(I2C1));; y  g8 X& M! y7 R! O. a( K! s- n
  26.     LL_I2C_ClearFlag_STOP(I2C1);4 U# v$ @( _0 h/ d7 {' N) s! u
  27. }
复制代码
8 ~+ V* M+ j6 d! N! q/ S
为了减少代码重复和增加可读性,对读写的一些过程另作了函数;
# Q1 t- H. v& ]6 X- x
  k1 Y; Z6 A5 s9 ]* L写寄存器地址:- a  V) x/ z: j8 I
% O0 X: U0 q( N
  1. void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size)
    ( ]8 r7 {! t3 j6 f8 e2 M
  2. {
    . }  M* J+ f5 b
  3.     uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);;
    + s* g$ F0 I2 j# T8 H. t
  4.     uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);;
    4 C: [: N3 W: j$ I

  5. + X6 N- H. B. H0 I: q; ?$ W
  6.     //发送器件寄存器地址
    6 d. N0 B9 }5 l
  7.     if(mem_size == I2C_MEMADD_SIZE_8BIT)3 l# }1 ?) p2 ], g7 Z# w* f! U/ W
  8.     {
    ' F$ y8 n1 O' f. M( x- |. ]
  9.         LL_I2C_TransmitData8(I2C1, MemAddrLSB);/ J2 p8 u. \* ?' z7 ^4 `# O- t6 a
  10.     }else{
    + p# P  o5 `$ x2 O9 S+ X& @! D
  11.         LL_I2C_TransmitData8(I2C1, MemAddrMSB);
    , t* d  {# }5 |! o: o2 {
  12.         //等待发送完成# G3 b: J, x7 f% Q0 d/ V- \. f
  13.         while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
    8 I+ [# s' }' N5 [  x% ~; b
  14.         LL_I2C_TransmitData8(I2C1, MemAddrLSB);- I1 Z$ Q' t4 a( o' n* f
  15.     }
    # I# d( k  g! W! e3 _; |" ^! G
  16. }
复制代码

7 L1 b) l' G0 j5 ?# @& W! y连续写入小于255个数据:
6 K5 A4 ], \. E; J+ J
7 ?0 W$ n# @, ?$ h
  1. void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length)/ o3 I' r1 |7 B7 l4 }
  2. {/ X' n6 _$ C- p& t6 {- E( q6 A3 D
  3.     uint8_t count;
    - @$ a: R; I$ O& V1 A
  4.     for(count=0;count<length; count++)
    0 ^6 F/ ^+ C7 D! s% G
  5.     {( a$ _9 O% r% a! n8 X; `# J+ `
  6.         //等待发送完成
    2 U# _" q. z4 p& M
  7.         while(!LL_I2C_IsActiveFlag_TXIS(I2C1));( f; [5 ^* V4 y2 U/ l. X
  8.         LL_I2C_TransmitData8(I2C1, *(pdata+count));
    ; x! q3 w$ `, N
  9.     }3 d/ j& I. j2 m5 R3 V1 E! s
  10. }
复制代码

) J( y8 \" ?9 ~( D: I连续读取小于255个数据:
5 v3 [1 R# Q4 C: M  y/ l7 K+ b) I( B$ z9 P9 W: L+ k( u
  1. void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length)7 }" j  M1 i) N
  2. {
    & u# m  W' G' V
  3.     uint8_t count;
    6 D' [* I  ^! k; ?, @6 B
  4.     for(count=0;count<length; count++)' G5 t1 o* g9 \+ H+ ?
  5.     {# Y$ v: c& ?) b  I
  6.         //等待接收非空
    2 R0 ~( O) F: J# N$ y* U/ [
  7.         while(!LL_I2C_IsActiveFlag_RXNE(I2C1));. h2 i' B$ R& B! W4 @
  8.         *(pdata+count) = LL_I2C_ReceiveData8(I2C1);
    " u& O6 X. ?2 t$ |& E: q! ]
  9.     }2 v* z* o9 g" Q( k" {; i
  10. }
    # U- X( Y: Y# }0 y
复制代码

1 Z- g8 q: k# t' s# W# n$ c8 n* S3 p1 b( c3 D5 c( b
赞 收藏 评论2 发布时间:2021-11-10 22:53

举报

2个回答
Spring_ly 回答时间:2023-1-12 13:32:15
你好,我想问一下,HAL库自带的函数可以连续写入256个字节,为什么改写的LL库的这个不能连续写入256个字节?
submer 回答时间:2023-4-27 15:53:32

有收获,感谢分享。

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版