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

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

[复制链接]
STMCU小助手 发布时间:2021-11-10 22:53
说明:驱动基于STm32G031K6,其他型号需自行做改动。
9 ?% u0 U: R0 X2 r# I6 z3 R0 A5 A7 w! I/ b
注:因为之前项目暂未用到LL库的IIC,所以此驱动未经过实机验证。欢迎反馈使用中的问题。  G* O2 Y0 D" x- G, N  z* ~
5 k" d; @6 }, F" x
IIC的初始化: CubeMX生成- B- D1 \: N* E" ^: ~4 Z: X: B3 L

" ]' X, E3 \  n
  1. void STM32LLI2C1_Init(void)
    ; i. f8 @3 W1 ^% b2 s1 w; }5 q
  2. {2 E) ^' a3 n7 {8 Z5 D3 x# D4 J
  3.   LL_I2C_InitTypeDef I2C_InitStruct = {0};
    % b' u& o0 E+ w- v/ i0 ?

  4. ' v( X& ?$ X) b. r3 I
  5.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};, N' G8 |( }$ R; g. X% G+ a
  6. $ C, M; l8 I, a
  7.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);; p# o0 o- }: H) W5 f, ]2 _
  8.   /**I2C1 GPIO Configuration  
    3 J( q+ q* m" I4 K1 y
  9.   PA9   ------> I2C1_SCL
    ' B& t- S0 E  A* n, I& P- n1 K+ b# Y
  10.   PA10   ------> I2C1_SDA - p% J: ]/ ?/ Z( q5 L. {" }8 m. Z8 C4 n
  11.   */
    ' M4 t  H  X2 y3 ~
  12.   GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;- w5 a9 D/ x: b) b$ `# g
  13.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    " B- \+ l5 P: ]( I1 M- N3 k
  14.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;+ w/ K) n* P$ |( h# A
  15.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
    3 r. x" Z+ X& s) N
  16.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
    $ y: ~- W- P$ ~% _# V0 t+ W  Z
  17.   GPIO_InitStruct.Alternate = LL_GPIO_AF_6;5 B3 ~  J9 d7 i* H% C& d) }* D* o
  18.   LL_GPIO_Init(GPIOA, &GPIO_InitStruct);2 u' z( M: u1 d1 @
  19. 7 Z$ V* j) h- f  h0 s! o
  20.   /* Peripheral clock enable */- F* A2 H, t/ c& S0 d; E* ?6 t
  21.   LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);# c3 E" e9 W9 Z' W+ ?7 o1 ]7 r
  22. $ u9 [! e& ]0 f7 h( ?
  23.   /** I2C Initialization ( o9 H* r- v7 s; b" a. d% ]
  24.   */0 c* L$ k$ E8 T2 `
  25.   I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
    , `: s8 \7 k$ `* R# C/ S$ o' x& F
  26.   I2C_InitStruct.Timing = 0x00303D5B;4 |1 X# Q+ C, N
  27.   I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
      @& M* W. h5 I# n  }2 v
  28.   I2C_InitStruct.DigitalFilter = 0;' x" K$ A4 C3 K- R
  29.   I2C_InitStruct.OwnAddress1 = 0;
    5 Z* f6 j% p9 M) j- T( t
  30.   I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
    2 n+ U' C) L2 b/ X% W2 X+ W1 j; j
  31.   I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;% }% h% o) ]# u% {8 M9 m9 q+ q
  32.   LL_I2C_Init(I2C1, &I2C_InitStruct);/ e0 a% |4 b2 f; I- W% W1 n* j
  33.   LL_I2C_EnableAutoEndMode(I2C1);
    ' ^! T; L* ]4 C6 v: }
  34.   LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);
    ! E. R' F" T6 C' T. c
  35.   LL_I2C_DisableOwnAddress2(I2C1);! r3 |; t. N6 O5 z
  36.   LL_I2C_DisableGeneralCall(I2C1);; l( S( W: g8 w% o$ ?
  37.   LL_I2C_EnableClockStretching(I2C1);) [' y0 o; M2 w! [/ n
  38.   LL_I2C_Enable(I2C1);
    , N7 g! J5 b! }6 B' y! ]/ F1 {5 N
  39. }
复制代码
* U6 E( I5 V9 X6 [# C0 J
由于LL库未提供与HAL类似的I2C多数据读取的函数接口,所以需要自行编写函数,我这里是参照HAL库内的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read写的LL库可使用的相对应函数。
9 A. y' |6 E# H: s6 @) O8 M: H6 V/ a3 |: a
I2C读多个数据:8 _# P8 X6 }8 S. v  O8 b% K
' m5 D3 t) N- v4 o
  1. void STM32I2C1_MasterRead(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)9 x7 N0 X; l% J) e9 U
  2. {
    2 W( U3 G2 Q7 L4 X& ~
  3.     //等待iic空闲( {. c% b5 B+ v
  4.     while(LL_I2C_IsActiveFlag_BUSY(I2C1));
    * A0 _7 U0 W& }0 O  C# f# \+ u
  5.     //确认iic是否使能0 e' P# w6 e6 Y1 D
  6.     if(!LL_I2C_IsEnabled(I2C1))
    ' V8 b: Q6 ]# G
  7.     {9 _) c1 w* R( y9 U) x3 z9 ~! ^
  8.         LL_I2C_Enable(I2C1);
    8 g1 Q. x: L  r+ A; V
  9.     }
    8 J/ h. z* Y+ b7 P2 ]" J- V
  10.     //配置
    / q6 O5 x! F6 O2 m
  11.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_SOFTEND_MODE,I2C_GENERATE_START_WRITE);0 }8 O3 [& |% M; C; i3 ?
  12.     while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
    - n5 s' L, x! X7 _3 A

  13. 0 h! S% Q" P" B- C5 k- R5 b1 D
  14.     //写入从设备寄存器地址0 f; \: l5 _. x4 V' y1 V
  15.     ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
      F" t! N8 ]0 Y9 W+ E
  16.     while(!LL_I2C_IsActiveFlag_TC(I2C1));
    + x3 Z* @+ Y3 ]

  17. $ X) \( {# \0 R: S' b
  18.     //配置4 [- k6 f: V7 k; Y: \- l
  19.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ);
    . W- |$ I& ^, B! k/ @% U. L& D# J

  20. $ T& v- ~0 t# v4 d7 {0 ]$ M4 l5 l
  21.     //读取数据# J( _. ^& c  z' s5 L
  22.     ucBSP_I2C1_ReadMultipleData(pdata,length);
    8 R8 m' ^! d5 @2 Z/ C% A
  23. 4 |3 y8 p3 o( y& B+ I7 }
  24.     //等待停止完成' h3 O8 T2 Y. d0 S9 C3 f
  25.     while(!LL_I2C_IsActiveFlag_STOP(I2C1));% g" ]$ `$ d, ]3 o
  26.     LL_I2C_ClearFlag_STOP(I2C1);0 [; F' u) @% P  p, Z% a. H# u# y
  27. }
复制代码
9 `) B. u5 B0 U) K4 ?- b. b3 I
I2C写多个数据:! h# O6 m0 X8 \8 M

& \! _+ Y. l  T; |7 F
  1. void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)" T8 D4 v9 g( H4 I. p% E
  2. {: Q/ X' o  |$ H' |: s3 h
  3.     //等待iic空闲0 z) m2 ~( _, V  Q7 ?
  4.     while(LL_I2C_IsActiveFlag_BUSY(I2C1));$ X2 {3 x# j" ?& G
  5.     //确认iic是否使能
    , Z$ E2 s5 D5 l4 `) i0 l3 g! d1 v
  6.     if(!LL_I2C_IsEnabled(I2C1))
    1 D3 q/ E- q: M, q
  7.     {
    " M& a$ q' l9 }  S) j' B
  8.         LL_I2C_Enable(I2C1);4 p5 y: s! {; }8 f( X) E5 Y+ r
  9.     }& Q) x" d& N5 c2 B  M! C( F) y( T
  10.     //配置为写/ {0 F: U9 j' i; w) h% C
  11.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_RELOAD_MODE,I2C_GENERATE_START_WRITE);
    ( r7 o3 j& R4 }. K) W) y
  12.     while(!LL_I2C_IsActiveFlag_TXIS(I2C1));0 R9 i' U2 [" a  L( n8 e5 r1 F

  13. # ^/ ^" }& B; G% d
  14.     //写入从设备寄存器地址& o: h) X" M, V. ~+ @3 d, O
  15.     ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
    2 r9 \2 t: e" p2 F7 G" A
  16.     while(!LL_I2C_IsActiveFlag_TCR(I2C1));5 c  v! C+ s! G  e7 u, \  j: G
  17. 7 r' {9 f) c  Q0 r7 q' R
  18.     //重新配置为自动停止模式% |1 }9 \7 I# c6 D9 G
  19.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_NO_STARTSTOP);" r9 Z# R* Y& i

  20. 9 M7 G  ?2 B# x, W2 I+ c- p' _
  21.     //写数据
    % V8 p# X- f6 ]. u
  22.     ucBSP_I2C1_WriteMultipleData(pdata,length);" o* n3 m; V( ~2 Z  p3 u5 J

  23. 6 ^& w/ p6 S$ l
  24.     //等待停止完成
    8 R$ S+ t+ v/ o$ X% }
  25.     while(!LL_I2C_IsActiveFlag_STOP(I2C1));' O. i7 G2 ?7 f" P2 Y& Y  r
  26.     LL_I2C_ClearFlag_STOP(I2C1);
    " {) m! v9 \8 n$ b4 @$ E
  27. }
复制代码
0 F# |9 z# j$ H' R8 {& G' X7 F/ ?
为了减少代码重复和增加可读性,对读写的一些过程另作了函数;
. z, C6 l3 ?  v0 }' i
+ Z, v% y6 M3 T- P写寄存器地址:
# ^. |! m- L4 ~5 T, h) V0 V: A8 F& ?4 I* T8 D! l
  1. void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size)( b1 c+ a& j+ Y3 K; p: N2 K3 k7 H7 w
  2. {
    ' r2 b' `1 X5 B: }  D
  3.     uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);;: F! a: }+ U' d7 Z
  4.     uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);;
    # Y! ~5 z: s6 y& }6 F

  5. / t' g1 m$ z$ H  ~
  6.     //发送器件寄存器地址
    - g% i8 r6 h9 J( e( V! {, A
  7.     if(mem_size == I2C_MEMADD_SIZE_8BIT)
    ' Q- A( F# V  |2 i
  8.     {" F7 X* N) V5 c3 n
  9.         LL_I2C_TransmitData8(I2C1, MemAddrLSB);" c; D% K3 a5 }  U2 s
  10.     }else{
    3 J! c+ f3 f- Z1 L( m9 g2 \
  11.         LL_I2C_TransmitData8(I2C1, MemAddrMSB);
    5 e! o0 z" Y, ?0 D# V' N
  12.         //等待发送完成
    5 k! }( R& _+ E: \9 q: M
  13.         while(!LL_I2C_IsActiveFlag_TXIS(I2C1));3 o: ]+ ?  j# k0 R
  14.         LL_I2C_TransmitData8(I2C1, MemAddrLSB);
    7 A0 Z% R) `( H! g. n
  15.     }% ]2 q( @. S( t7 R/ M
  16. }
复制代码

8 g0 E: }8 l& e$ a2 s" }连续写入小于255个数据:
6 v( a' j0 q- k) Z2 a- ?6 V+ z  Z- v) D/ e% n. G1 x4 g- U; P
  1. void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length)8 Z7 H' s0 q9 M" h$ x
  2. {! E1 T9 h( f3 c6 n4 x* }& \
  3.     uint8_t count;7 ]+ A! V' r6 U. p$ Q% a) s
  4.     for(count=0;count<length; count++)/ ]' }9 X- W) e6 W4 ^0 W4 ]
  5.     {
    6 H' u0 ?6 v1 ^
  6.         //等待发送完成- ~, P5 M7 d/ I* r- y
  7.         while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
    7 ~" m; A0 t0 R) W
  8.         LL_I2C_TransmitData8(I2C1, *(pdata+count));$ Z( `) n  N/ P, ^# z3 y/ p
  9.     }9 u$ \# |8 t; v; O, Y+ z% T
  10. }
复制代码
" e9 _0 }# R! r& ~/ r
连续读取小于255个数据:
7 K* ]9 M) z) b2 |9 @9 E0 ?0 g3 A7 t$ ?7 v, v! G7 Y
  1. void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length)
    : u: s/ E8 s$ Y  `" \0 I
  2. {
    3 l$ g* h1 d; b
  3.     uint8_t count;
    0 \$ h1 O$ {( `! p2 ?
  4.     for(count=0;count<length; count++)3 [- ?% I  d3 P1 A1 u
  5.     {" _- n! w4 h7 \, ?
  6.         //等待接收非空
    & M2 ~  Z6 T! {
  7.         while(!LL_I2C_IsActiveFlag_RXNE(I2C1));
    3 s, l. I6 I4 H7 d3 p% Y( o/ l; v
  8.         *(pdata+count) = LL_I2C_ReceiveData8(I2C1);
    + k, C3 _4 h  q8 s9 f
  9.     }+ W! i& l0 c1 |
  10. }
    ( w- r" ?6 m/ B- ^" V0 M5 J) B0 h- p7 E4 c
复制代码

1 o0 G% j2 J1 `4 z7 `
8 `! g% H  R- k& ]
收藏 评论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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版