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

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

[复制链接]
STMCU小助手 发布时间:2021-11-10 22:53
说明:驱动基于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
  1. void STM32LLI2C1_Init(void)5 L( K, m- |+ o4 O; B
  2. {
    9 P3 ]3 H7 z6 q
  3.   LL_I2C_InitTypeDef I2C_InitStruct = {0};  P$ I+ W# Y) A; o* U# l) P1 r
  4. ! x2 j: H4 b# J* u( R
  5.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};% O  |9 _1 O% s% t; f6 C6 R

  6. ; U5 I$ @" l8 g' r0 f
  7.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
    6 K4 B( }: S" Z# f. q! C9 Y  A
  8.   /**I2C1 GPIO Configuration  " a, `$ X2 q0 V) _' ]8 R$ b
  9.   PA9   ------> I2C1_SCL. w& R% g& p. O, ~
  10.   PA10   ------> I2C1_SDA
    : |; E, X3 c6 Y) V! ]
  11.   */
    2 A* d+ u% d$ P6 ^" M
  12.   GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;
      R- D- ~& k" m% q2 s" \
  13.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    - n* v4 ^8 n9 y, y# Y( _
  14.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;4 z6 I4 P6 F& b3 g! h/ Z
  15.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;" ?) x. C  K8 O- A
  16.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
    $ J* e6 Z4 P3 D
  17.   GPIO_InitStruct.Alternate = LL_GPIO_AF_6;
    & D! G. X* e& Y" W" g% q
  18.   LL_GPIO_Init(GPIOA, &GPIO_InitStruct);. g. J0 O) q, y! h
  19. # c+ g3 c3 G" X& I  |/ g* P6 _
  20.   /* Peripheral clock enable */. M' e* u; F, e# ^" u3 z
  21.   LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
    ' \) P& ]* o8 j; j$ O
  22. % e1 K7 F2 o3 t" j
  23.   /** I2C Initialization / {- N. f( ?& [3 A( g7 F6 w
  24.   */2 u+ o7 b3 s) N9 x
  25.   I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;4 E6 \9 h6 d( H  Y
  26.   I2C_InitStruct.Timing = 0x00303D5B;& w% b4 y: ?( X- J
  27.   I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
    ' x6 o+ v  s+ I; p( B. z/ z0 v- I
  28.   I2C_InitStruct.DigitalFilter = 0;
    ; V2 R& Y+ t) O0 F
  29.   I2C_InitStruct.OwnAddress1 = 0;. z- n. E% \+ A9 i) E/ d5 F6 H
  30.   I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
    - d4 z( m6 }  ~5 g" `4 G
  31.   I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
    0 }+ q  W' Q) R: l. S7 O2 [4 ?- S* G
  32.   LL_I2C_Init(I2C1, &I2C_InitStruct);
    ; ?" r' S4 ~5 L2 S# }
  33.   LL_I2C_EnableAutoEndMode(I2C1);4 Z# m. Q+ Z- ?' y. t* G
  34.   LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);
    & B* l! z, u2 S$ D5 A
  35.   LL_I2C_DisableOwnAddress2(I2C1);
    ' c# E2 e- i1 w0 G( f  C7 E
  36.   LL_I2C_DisableGeneralCall(I2C1);
    7 s! a" {- ^; ?
  37.   LL_I2C_EnableClockStretching(I2C1);
    " {/ E2 T( u4 s; }  g+ q4 [
  38.   LL_I2C_Enable(I2C1);
    " M/ F- m9 w2 y% R! g
  39. }
复制代码

( 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
  1. 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
  2. {0 K" M) G2 J( P. l
  3.     //等待iic空闲) d, ]1 N0 p) ]( d' a
  4.     while(LL_I2C_IsActiveFlag_BUSY(I2C1));) m/ |, Y4 g8 Q1 t+ Q: v
  5.     //确认iic是否使能4 C4 r6 v& D, M  v4 z! p
  6.     if(!LL_I2C_IsEnabled(I2C1))
    * v0 J# _+ n% |
  7.     {
    7 g0 s9 d  A1 b- A- ~8 }6 k4 y
  8.         LL_I2C_Enable(I2C1);# y( f2 f% l0 Q8 D6 A8 _& Y
  9.     }
    ) z/ t% W) x5 c/ n& D- G# {- `
  10.     //配置
    : d+ {$ U* I4 l7 H! q
  11.     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
  12.     while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
    ! f, T/ z: p/ f- h8 _

  13. 2 U0 e/ S1 Y! x* ?0 r8 ~1 j
  14.     //写入从设备寄存器地址
    ! R. r3 h" t- [7 }* ^
  15.     ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
    $ M% ~+ t- ~# n6 u% d
  16.     while(!LL_I2C_IsActiveFlag_TC(I2C1));
    ) A# m- Q3 j7 q3 C0 o2 T

  17. . a9 `; V4 c7 N, D! z
  18.     //配置
    $ `- E. {$ J* C# }
  19.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ);
    / n8 E4 E' Y; Y9 B

  20. . U3 Z" _2 H4 b: X9 B- i8 O
  21.     //读取数据  ~' S+ ]" W, k' h2 w3 H8 K. Q8 k) S
  22.     ucBSP_I2C1_ReadMultipleData(pdata,length);
    9 k  H, H, e" d; C

  23. . r. o, _+ Y4 K. h. v0 @" ?- K, _: u0 _
  24.     //等待停止完成1 x, Q5 I) d8 P2 K. e* X: u
  25.     while(!LL_I2C_IsActiveFlag_STOP(I2C1));+ Q! O1 P' t# V$ n2 I' M0 D$ r6 F
  26.     LL_I2C_ClearFlag_STOP(I2C1);0 Q8 p8 }- X4 y; S8 j
  27. }
复制代码
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
  1. void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
    : I7 P2 n0 \! @. [& @
  2. {
    5 y& \+ F  F. p
  3.     //等待iic空闲. Y9 d  h2 u$ G" z+ F
  4.     while(LL_I2C_IsActiveFlag_BUSY(I2C1));
    $ ]5 t2 _( D4 _1 j) E4 a
  5.     //确认iic是否使能
    ' Z) l6 d4 ^) d  Q3 z3 K0 b/ Z
  6.     if(!LL_I2C_IsEnabled(I2C1))' j+ E2 z2 w* D9 D# M1 i
  7.     {
    8 P5 c/ k0 \7 s- o6 _  p% s
  8.         LL_I2C_Enable(I2C1);: S; \6 m5 @" @# h2 e; C& j
  9.     }3 `# a8 }, ~5 n# ?3 N4 c
  10.     //配置为写
    8 `: {$ ~" W. D! }
  11.     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
  12.     while(!LL_I2C_IsActiveFlag_TXIS(I2C1));) N) f6 c6 |+ q' H3 L: ?

  13. ) H3 e1 n- Y' V! U  ?+ z) m
  14.     //写入从设备寄存器地址3 m; O& q7 z' [/ @8 p! `0 D7 \3 W% I
  15.     ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);7 C; l: V- ?- }- C
  16.     while(!LL_I2C_IsActiveFlag_TCR(I2C1));
    % `8 A) `0 H; K+ ^2 \

  17. ) a+ x* F$ }3 `3 ]7 ^
  18.     //重新配置为自动停止模式
    7 U, I5 b( z1 O* {
  19.     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

  20. & ~9 n( \) U6 }6 B1 Z
  21.     //写数据
    % e3 Y- e: h- b, K2 k8 q
  22.     ucBSP_I2C1_WriteMultipleData(pdata,length);7 f/ M# _/ i6 P3 O
  23. 2 l5 B- a* l$ t% ]- l+ f1 }
  24.     //等待停止完成- _* C! h& h4 @; c0 J- x0 K
  25.     while(!LL_I2C_IsActiveFlag_STOP(I2C1));
    0 r' M* |1 k3 x0 t" L6 c3 k/ m
  26.     LL_I2C_ClearFlag_STOP(I2C1);+ q, J2 n7 a% `9 q; a3 |$ T  E( Y' P
  27. }
复制代码

! ]% 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
  1. void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size)
    5 a+ r# T' k7 S3 Q
  2. {- w* R' l3 |$ g
  3.     uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);;
    , L  o0 J7 A6 u9 I
  4.     uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);;
    + `1 ?% l2 P- N" D9 ^# q4 U

  5. , [# C2 E7 L9 x2 Y' n4 g7 e
  6.     //发送器件寄存器地址
    * S2 J  I1 I9 n
  7.     if(mem_size == I2C_MEMADD_SIZE_8BIT)
    & @( f2 J8 A! k  G5 ]) c
  8.     {3 H. t5 N2 ^4 \. v9 B2 K' w
  9.         LL_I2C_TransmitData8(I2C1, MemAddrLSB);. q5 c; x+ M/ q9 m4 z
  10.     }else{2 l: h9 h6 p; G7 G
  11.         LL_I2C_TransmitData8(I2C1, MemAddrMSB);9 L6 [- |( T; W: \% t
  12.         //等待发送完成  u9 g  r) m8 A* m+ c
  13.         while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
    $ C1 R% M) u8 |2 s( ?
  14.         LL_I2C_TransmitData8(I2C1, MemAddrLSB);0 D8 D5 I+ y/ t0 y" G  m' O' }& @" B
  15.     }3 O: s4 w" B( J/ ]. i( b- b
  16. }
复制代码

9 \- ]& S. v- f- D连续写入小于255个数据:- {2 D+ Y% ]5 |9 p9 G% I: z# y
6 C) b! t& k) H. ?
  1. void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length)) p* C% _% s/ j1 a, Y
  2. {
    9 J$ Q) O/ G( w7 {# d4 p
  3.     uint8_t count;3 a  C0 i: }, n0 z; \9 M' z
  4.     for(count=0;count<length; count++)" a$ L+ f- I& H: H
  5.     {
    * g1 m8 y  m$ x1 O; y% J- C0 a
  6.         //等待发送完成7 s/ s! @0 w. n' J$ {1 T/ R7 t
  7.         while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
    + h) l! a  c1 g1 ~
  8.         LL_I2C_TransmitData8(I2C1, *(pdata+count));
    , P3 z" Z3 g1 H2 X& Q
  9.     }
    7 {) f+ A$ r( H: U/ C
  10. }
复制代码
7 S1 m/ J6 T8 e3 ~) @
连续读取小于255个数据:; W" o- {, ?* N. X
; E2 a+ @3 |  c! P$ G
  1. void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length)
    * i5 X8 c4 _- A* L2 p3 i
  2. {
    + i- I  s% r( i
  3.     uint8_t count;8 B8 s* v5 c9 J( q
  4.     for(count=0;count<length; count++)
    . T' H; d) E1 f: T. u) \. u
  5.     {
    0 a$ b' B, H0 n; z8 o4 ?0 d" R
  6.         //等待接收非空/ }0 b% ^5 z% @7 C8 @% A, P: @4 t
  7.         while(!LL_I2C_IsActiveFlag_RXNE(I2C1));5 B7 H" N. A$ B3 V9 J% x* r& q" ]* e
  8.         *(pdata+count) = LL_I2C_ReceiveData8(I2C1);! D$ j* ~" K* M2 g
  9.     }
    $ x% k5 j: J# y7 D0 [/ z
  10. }
    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
收藏 评论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管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版