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

【STM32G4 NUCLEO G431RB】+ I2C通讯终于完成

[复制链接]
老牛洋车 发布时间:2019-9-20 21:19
    之前完成了GPIO模拟I2C驱动DS1307和AT24C32之后,便继续测试如何使用硬件I2C。在热心版主和坛友的帮助下,经过几天的反复测试,硬件I2C也基本完成,在阻塞方式下完成了对DS1307和AT24C32的操作,下图为测试过程:' a, w! X3 O: [& a" R
I2C_Bus_Ok.jpg
/ c6 J9 \8 ]% P3 b
7 S- J3 C4 I; @( C5 _    屏幕下部的日期和时间是从DS1307芯片读取的,利用systick的毫秒中断进行秒计时,每分钟读取一次DS1307的日期数据,并用秒、分、时数据对AT24C32进行一次先读后写的操作,读出的数据(也就是上次写入的数据)显示在倒数第三行,当前写入的数据显示在倒数第二行。对DS1307读取数据交替采用HAL_I2C_Master_Receive()和HAL_I2C_Mem_Read()函数,读写的代码如下:
" n, \* `2 v$ [; M: z
  1. /****************************************************************************************** / |# \: [- |& i9 E6 j! W8 T! w) T
  2. * 函数名称: DS1307_I2C_Transmit(uint8_t size)
    6 ~, I' b- a" S7 j
  3. * 功能说明: 写数据到DS1307
    ( K2 l2 @* w+ V" s8 L+ i  w* L
  4. * 输    入: size 数据个数(要写入数据在全局数组DS_Buff中)
    6 L  C; {9 d, j
  5. * 输    出: 0 = 成功写入  1 = 写数据过程中出现错误
    2 F, }4 x: ?0 }: ]
  6. ******************************************************************************************/( r% t$ ^2 N8 F  l
  7. uint8_t DS1307_I2C_Transmit(uint8_t size)( }1 c) s* o' n' z6 ?: s2 l; k
  8. {6 _  _) i- F& _
  9.     uint8_t addr = 0;8 L) W; j: U5 X/ G  f* k, g
  10.         DS1307_DataToBuff();      //将时间及日期数据转换到Buff数组中
    1 T/ ^6 s, E: J7 x) g: m
  11.         HAL_I2C_Master_Transmit(&hi2c1,0xD0,&addr,1,10000);//发送起始地址
    ' w. ~( n( `5 u- X0 H3 S
  12.        
    ! h' S) ~/ d5 D
  13.         if(HAL_I2C_Master_Transmit(&hi2c1,0xD0,(uint8_t*)DS_Buff ,size,10000) != HAL_OK)3 ?6 M" g4 \/ a& `, P
  14.     {
    9 A8 q6 D, [- \4 c. {
  15.         return 1;
    0 s6 }* Z. k' k* ]" A4 @! F9 q2 s
  16.     }
    5 U+ U/ x" z5 |4 L7 j$ N; {+ z9 ~
  17.         return 0;. V2 R% F3 X0 q: W( s2 Z: s& ~7 Z
  18. }& \% M% _- A( W+ c1 X' T& [6 Q8 x

  19. ) i  r: D  S4 X
  20. /******************************************************************************************
    8 ]& G# a& o! y0 w3 F/ E! Y* B9 a4 s& A
  21. * 函数名称: DS1307_I2C_Receive(uint8_t size)# q/ ]% i6 C% q- j4 {4 G' P
  22. * 功能说明: 从DS1307读出数据
    + Q) C* l8 q. z3 i1 L0 T7 p
  23. * 输    入: size 数据个数(读出的数据在全局数组DS_Buff中)
    " l, l5 S' Z8 ~5 U6 k) o! v5 E7 p& I
  24. * 输    出: 0 = 成功读出  1 = 读数据过程中出现错误
    + J: A: D; Z2 F; B5 r! R# d
  25. ******************************************************************************************/
    $ R! b' j& J/ l' r' w! {! U
  26. uint8_t DS1307_I2C_Receive(uint8_t size). X4 R3 {; s* s( [
  27. {. D+ V) o% S. G9 r
  28.         uint8_t addr = 0;6 [1 ]2 R' d5 y, N$ q3 \( P
  29.         HAL_I2C_Master_Transmit(&hi2c1,0xD0,&addr,1,10000);//发送起始地址
    + D; [0 m8 y; @
  30.         ) X0 o8 y* J6 H1 V+ R) f
  31.     if(HAL_I2C_Master_Receive(&hi2c1,0xD0,DS_Buff,7,10000) != HAL_OK)
    & W  ]+ T6 d' S) R5 Y
  32.     {
    0 p' h2 v7 A9 t& W. l
  33.         return 1;
    * e* i7 w. i1 M, h! R
  34.     }
    + k, R3 ?' `( I$ x5 k
  35.     if(size == 1){               //检查DS1307是否需要初始化7 s: F. _3 c: b3 H' y% I
  36.                 if(DS_Buff[0]>127){
    - O, z( L% [/ t5 p0 f) ^
  37.             year = 2019;6 a5 W/ I) h8 v4 p' h
  38.                     month = 9;
    1 I5 C' ?+ M7 [# D+ }# |
  39.                     day = 18;
    5 X$ R9 y/ j7 K, o+ S, {
  40.                     week = 3;
    6 Q  f; \. h; h; E( G& ?- b' Z
  41.                     hour = 9;1 Q* f" q) n; T+ Q# x
  42.                     minute = 1;- D. q' n* d8 b
  43.                
    $ w) C) @. q' {2 [
  44.             DS1307_DataToBuff();4 _; L, o/ p2 b* q7 _
  45.                         DS1307_I2C_Transmit(8);
    8 e6 J) v: X/ V& _6 w
  46.                 }
    : C; _  H9 A2 M, h! R, ?9 A7 P
  47.         }& j6 z- j; P$ w* T$ ]# E# [4 \( z
  48.         else{0 Q& `# h" G  W/ J9 W8 B
  49.             DS1307_BuffToData();
    . y7 I8 L+ H: l, r$ K
  50.     }
    # A# f2 m9 n; p/ S9 D  G
  51.         return 0;       
    " _9 x3 ^) B* M6 F; @
  52. }+ [: x8 S' P; Y+ s/ f3 O5 d/ u0 g
  53.                  / u5 r# a3 ~' k! b
  54. /******************************************************************************************
    $ Z, v; L; w& w: F8 F2 D* K
  55. * 函数名称: DS1307_I2C_Read()
    # t6 z+ c; K" Q2 q, w( Y% D
  56. * 功能说明: 读DS1307的日历数据,并转换为各自的变量值
    9 B7 S5 Z3 Z3 U) Q
  57. * 输    入: 无
    ; [) R( M! r) j4 T1 Z
  58. * 输    出: 0 = 成功从DS1307获取数据  >0 = 从DS1307获取数据过程中出现错误) r0 a% Y6 w. @/ A# d) J: k  }
  59. ******************************************************************************************/2 p4 a$ v4 L% W2 j
  60. void DS1307_I2C_Read(void)
    ( }* R. G6 `6 N$ C
  61. {
    : f. O4 F% q4 F/ \- G

  62. 5 I4 T: H; k  G7 O- O  r- \5 E
  63.     while (HAL_I2C_Mem_Read(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,7,10000) != HAL_OK)
    8 I3 u% i# K1 D$ V" r) d1 b# [' @
  64. //        while (HAL_I2C_Master_Receive(&hi2c1, 0, (uint8_t *)DS_Buff, 7, 10000) != HAL_OK)6 _- C. a+ B& g0 T$ C% z# x
  65.     {
    " y+ s8 A& P# Y
  66.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
    $ {0 V% ]9 _8 V* p
  67.         {
    . N# z; d% c" z3 ]
  68.             LCD_write_ASCII(0,3,1,(uint8_t *)"DS_Read_Error!");
    ! ^- q* U1 f) ~! S  N
  69.         }) ^0 ^3 a8 P, [7 f' l
  70.     }  X: D' y6 }) ^- c* H
  71. 8 u; Q- ~" J, ]* T- n, a
  72.         DS1307_BuffToData();
    ! e7 ~5 `" c1 n2 S3 |& x8 `
  73.        
    6 y+ f5 V- c8 h$ k) P& H2 R# F# j6 U
  74. }5 h2 F& _- f! \1 D6 C
  75. & u7 z* Z) U9 @+ t4 X9 q
  76. /****************************************************************************************** / Q, C4 r, K- y- c
  77. * 函数名称: DS1307_I2C_Write()9 N! U5 M  D/ F4 b- \( ~# F/ e: _
  78. * 功能说明: 将当前的日历数据写入DS1307
    3 x# l/ w7 k3 {5 {, g' Q5 g. c, B5 }3 A
  79. * 输    入: 无; Q3 O# R( N: ^/ ^& r: \
  80. * 输    出: 0 = 成功写入数据  >0 = DS1307写入数据过程中出现错误
    ! Z6 P: C1 A0 [6 j. I5 T
  81. ******************************************************************************************/
    ' B( c8 g) _* h; R* N
  82. void DS1307_I2C_Write(void); v& q0 Z3 a9 @5 D
  83. {
    & B2 y7 o( T5 Y2 Y# G! t
  84.     DS1307_DataToBuff();           //时间日期数据转换存入Buff数组中
    3 ~6 O# m- [9 T5 j
  85.         + i& L1 j& z/ C( ]+ m
  86.     while (HAL_I2C_Mem_Write(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,7,10000) != HAL_OK)! |( \# t2 d3 t7 w. b5 U3 Q
  87. //    while (HAL_I2C_Master_Transmit(&hi2c1, 0, (uint8_t *)DS_Buff, 7, 10000) != HAL_OK)
    9 M) `9 q) o! l4 r% {3 x
  88.     {6 E9 A& w( m! S6 B3 f3 g8 K
  89.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)- J2 v8 e* B0 q" X5 v
  90.         {
    1 ~, W" ]8 V+ L. P5 [
  91.             LCD_write_ASCII(0,3,1,(uint8_t *)"DS_Write_Erro!");
    8 ~* |$ d& G, D2 W+ R: I
  92. //                        return 2;! s  M: z9 W# M4 [/ y! c* F+ b
  93.         }
    6 [  @1 ~3 o6 x
  94.     }1 {& ^% ~8 l1 v* X* R+ I2 S
  95. //        return 0;* S. o+ Z! V& U1 T7 f
  96. }2 M/ X4 P" P3 j
  97. # \# w% o! D6 v3 C& @  x7 g
  98. /******************************************************************************************
    ) q7 A* o" A6 b
  99. * 函数名称: DS1307_Chick()8 x; d  y1 y$ N- N% L
  100. * 功能说明: 检查DS1307是否已经初始化,若未初始化则用特写日期进行初始化
    6 \: z3 k# b, E' E
  101. * 输    入: 无
    - s# w# r! @. r6 x) g) w
  102. * 输    出: 无0 t. l% P0 m$ }8 {2 Y) z# Z
  103. ******************************************************************************************/
    % p+ `) F2 ~/ E/ y
  104. void DS1307_Check(void)
    ' M9 I/ f, y8 O/ M! Q
  105. {. m0 j6 r2 i: \& j

  106. 8 a1 N2 N6 s0 I* d0 m
  107. //        LCD_write_ASCII(0,3,1,(uint8_t *)"Check_Begin...");3 \5 u: O$ h/ Z& H3 r. |
  108.     while (HAL_I2C_Mem_Read(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,1,10000) != HAL_OK)
    ; k) V: G/ Z4 |$ |# c+ U* i
  109.     while (HAL_I2C_Master_Receive(&hi2c1, 0, (uint8_t *)DS_Buff, 1, 10000) != HAL_OK)
    % i; t9 Q7 P! O
  110.     {( r' ]0 W( J: W7 N0 r
  111.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)/ q$ Q( i, _& d' e& A) X+ `
  112.                 {
    + F) g" c& x: m  J
  113.                     LCD_write_ASCII(0,3,1,(uint8_t *)"CheckReadErro!");
    2 Z1 d  ?( q/ j' q/ b
  114.                 }: ^, K( Y% v/ }' Q
  115.         }) f. M" @5 C  W4 k# e) h
  116.         LCD_write_value(0,4,3,0,1,DS_Buff[0]);' }  ~) F9 z& r; {$ Z$ _
  117.         if(DS_Buff[0]> 127){* b& B; I  t4 u8 X# N( I
  118.         year = 2019;
    6 C5 p/ l) |  w+ `7 S; x
  119.                 month = 9;
    ( A% [4 x. Z6 D$ R: j! |* @
  120.                 day = 18;
    ! X$ P7 T  K' W" g4 e/ [
  121.                 week = 3;. T7 T4 T, \% d% ^
  122.                 hour = 9;
    + c7 ]( |% Z# O' l
  123.                 minute = 1;
    5 I# L  U( [. x6 @2 o  u. a. U- n
  124.                 " W1 [. D- z8 e( D6 \
  125.         DS1307_DataToBuff();% v; G* t7 I* z9 }, p
  126. 1 O$ L" e& D# y% c. U8 `1 O
  127.         while (HAL_I2C_Mem_Write(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,1,10000) != HAL_OK)
    ! z% y% |& {# _; c/ e; N( A
  128. //        while (HAL_I2C_Master_Transmit(&hi2c1, 0, (uint8_t *)DS_Buff, 8, 10000) != HAL_OK)+ c. g' Z5 `: ^% Y" M; X
  129.         {
    2 D# h6 W0 T/ F; g. w
  130.             if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
    + A/ V" v7 W1 s
  131.             {3 O2 {. {- x8 B# x
  132.                 LCD_write_ASCII(0,3,1,(uint8_t *)"CheckWriteErr!");
    & x9 Z. _5 x' v+ B
  133.             }
    ! A+ E6 ~/ u8 i1 i/ Z
  134.         }- {4 s0 I* D, B5 U
  135.         }- p9 [8 z1 P* M, u
  136. }. y5 D8 V" a8 @9 |/ b: p
  137. - i; a' G+ s4 A: r& o5 b% t) `
  138. /******************************************************************************************
    , b) z; G7 Z& `9 E0 m
  139. * 函数名称: DS1307_DataToBuff()
    6 M! B6 U- [# p; R
  140. * 功能说明: 将时间日期变量数据转换到数组Buff中
    * {+ w+ E; G9 o% S) f7 Z
  141. * 输    入: 无7 }/ s* A0 c6 u! b& K
  142. * 输    出: 无
    " I0 S8 R! _! g* @' f9 v; \
  143. ******************************************************************************************/$ v$ ?" ^) g; j: b! y9 A) A/ e
  144. void DS1307_DataToBuff(void)  V7 m# D0 b' a2 g% V2 M; r
  145. {) V$ g6 J5 K/ ^
  146.     uint8_t temp;
    4 x5 B" u: Z( V, p
  147.         DS_Buff[0] = 0;                  //秒
    % q  X2 B* [' w' R; w5 q
  148.     temp = ((minute/10)<<4|(minute%10));
    , b% J! R/ n' v# R$ {
  149.     DS_Buff[1] = temp;               //分
    7 I: N' P: Z- h5 t! r6 H
  150.     temp = ((hour/10)<<4|(hour%10));" W2 K6 {% H6 {- t) X% z' N. g
  151.     DS_Buff[2] = temp;               //时
    ( ?8 J& C  h$ V& J) P* a' I, h0 [

  152. " x1 Q% w) o9 u4 b
  153.     DS_Buff[3] = week;               //星期6 I1 Z6 f1 k3 D$ l- `% C

  154. 9 ?4 k. C  C6 l' D" J) B" i9 N
  155.     temp = ((day/10)<<4|(day%10));. q) q; u3 ^! k9 U
  156.     DS_Buff[4] = temp;               //日8 n$ v; }/ d8 }3 \5 j! R2 J. `: U
  157.     temp = ((month/10)<<4|(month%10));
    2 L2 R% W' r0 C1 y) {  S& s
  158.     DS_Buff[5] = temp;               //月
    2 \3 T9 p9 I/ I  o
  159.     temp = ((year%100)/10<<4|(year%10));
      [& V, {0 ~9 o1 B5 f
  160.     DS_Buff[6] = temp;               //年
    + r# R$ q& t6 d! @
  161.     DS_Buff[7] = 32;                 //0010 0000 = 允许按1Hz输出方波
    ( v1 y( C' `7 P8 Z
  162. }
    * Y( Y* ^9 I. D3 `
  163. # f- h% n  d! ?. C
  164. 5 o9 _7 ]  l6 o' R/ o
  165. /****************************************************************************************** / d: m8 ~7 D3 N$ V, _3 ^8 m
  166. * 函数名称: DS1307_BuffToData()$ x. s: s4 p$ @$ V" ?* ]
  167. * 功能说明: 将数组Buff数据转换到时间日期变量中
    7 s2 h( @2 x" k3 ]7 S
  168. * 输    入: 无
    $ D( c* H5 [1 J3 m1 ]( K4 u. P) W
  169. * 输    出: 无  k& y3 u. a4 C3 m- `7 b
  170. ******************************************************************************************/
    % m. }* h7 g) G! s  o
  171. void DS1307_BuffToData(void)
    * C3 p  E8 ]$ e1 y
  172. {
      ?& v1 K! }- Q! E9 r- @( G' y
  173.     second = ((DS_Buff[0]&0x70)>>4)*10 + (DS_Buff[0]&0x0F);//秒,屏蔽秒的第7位的标志, `6 k( {, m; V: f" g9 E/ x
  174.     minute = ((DS_Buff[1]&0x70)>>4)*10 + (DS_Buff[1]&0x0F);//分(取低7位)
    6 E3 D' c) ]$ s3 n, B
  175.            hour = ((DS_Buff[2]&0x30)>>4)*10 + (DS_Buff[2]&0x0F);  //时(取低5位)$ N. ~0 _# h) A  f5 y
  176.            week = (DS_Buff[3]&0x07);                              //周(取低3位)! D$ I0 P4 ~- G2 D
  177.     day = ((DS_Buff[4]&0x30)>>4)*10 + (DS_Buff[4]&0x0F);   //日(取低6位)6 J% G# `3 k7 G
  178.     month = ((DS_Buff[5]&0x10)>>4)*10 + (DS_Buff[5]&0x0F); //月(取低5位)
    4 r" N! K& [! Y  P. A5 J. [
  179.     year = 2000 + (DS_Buff[6]>>4)*10 + (DS_Buff[6]&0x0F);  //年
    ! Y& j% [9 N' i1 ?" c& \9 O
  180. }, s: E3 `* @% `" a
  181. / b) w! N  ~" S9 R) G1 q& F
  182. /****************************************************************************************** " Q3 b( j# S8 j. y& P, o9 I) s
  183. * 函数名称: AT24C32_I2C_Read()
    5 n# u' d" \: `! r# N
  184. * 功能说明: 读取AT24C32的数据(存放在DS_Buff数组中)
    2 f: _: k4 Z  g3 ]: K- L
  185. * 输    入: adrr(起始地址),size(读取的字节长度)
    6 {+ X. v( I# U: I
  186. * 输    出: 无: v) l6 A+ S/ c9 d% u3 T0 H
  187. ******************************************************************************************/+ X: K8 |: b+ l) ~( E, B
  188. void AT24C32_I2C_Read(uint16_t addr,uint8_t size)
    * o5 h$ S- M6 v7 P+ l. @2 u
  189. {" L- j$ m; q% W9 L: [" c

  190. 5 q5 F4 \# B# w! S( S
  191.     while (HAL_I2C_Mem_Read(&hi2c1,0x00A0,addr,I2C_MEMADD_SIZE_16BIT,(uint8_t*)DS_Buff,size,10000) != HAL_OK)+ P1 M' g( Y0 @, I- i
  192.     {. @: s! }5 @/ m, i
  193.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
    % v+ r7 ^# G9 m- h/ o9 j
  194.         {, y6 l5 s3 W6 |" v* P5 h
  195.             LCD_write_ASCII(0,3,1,(uint8_t *)"AT_Read_Error!");6 y. V7 M7 A. G$ r+ V
  196.         }7 L9 U/ m" P6 W8 o: Z
  197.     }
    % n: R6 I) L0 F8 v) Y

  198. . M1 O) {2 M) O
  199. }
    . O( z% L' k$ |. k+ z

  200. * H; p7 U" t! k% [' D" L
  201. /******************************************************************************************
    ' e. ~2 K9 \# z( p
  202. * 函数名称: AT24C32_I2C_Write(uint16_t addr,uint8_t size)
    ' T8 C8 W; y! t2 T1 @; M$ @( H3 A) D
  203. * 功能说明: 写入数据到AT24C32(要写入的数据存放在DS_Buff数组中)
    ! ^; u5 X% d4 K8 L1 G; l$ a
  204. * 输    入: adrr(起始地址),size(写入的字节长度)$ y$ T  |0 \' Z
  205. * 输    出: 无2 h4 i. a  |! v; l
  206. ******************************************************************************************/
    $ @/ d$ F  m! |, B" |" @
  207. void AT24C32_I2C_Write(uint16_t addr,uint8_t size): f( k; ^9 r1 h) u+ F  @
  208. {1 T8 i( u/ Y4 T6 x  Y9 ~
  209.     while (HAL_I2C_Mem_Write(&hi2c1,0x00A0,addr,I2C_MEMADD_SIZE_16BIT,(uint8_t*)DS_Buff,size,10000) != HAL_OK)
      m+ _' ?+ b6 ~1 v3 S
  210.     {
    % B  u$ L- B- w5 W' b
  211.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)8 u, ?# u6 A6 o5 C+ s
  212.         {8 r2 u, |0 a' f# U& b
  213.             LCD_write_ASCII(0,3,1,(uint8_t *)"AT_Write_Erro!");
    5 b) S" k, j) ~
  214.         }
    ( S9 X4 Z. t- t/ p1 P
  215.     }% q* I; {+ h+ _9 ~" U
  216. 3 \3 Z' |1 l3 e- E6 f
  217. }
复制代码

2 L1 C8 a3 @7 q4 X1 U' {
$ Q9 K  ]: ?# v6 r
  ?: B; o! f4 n9 ?* R; X
/ @0 b: y% v5 b# m1 S+ I& M
6 C* T  H7 a6 y! z
收藏 1 评论4 发布时间:2019-9-20 21:19

举报

4个回答
Litthins 回答时间:2019-9-22 22:01:27
DS1307和DS1302区别大吗?
老牛洋车 回答时间:2019-9-23 12:10:18
有区别,DS1307要依靠器件地址来选定,也就是说可以挂在标准的I2C总线上使用,而DS1302则不需要器件地址,直接发送要操作的内存(寄存器)地址就行,按我的理解就是在这个总线上只能一个器件。
香醋 回答时间:2019-9-23 13:50:32
顶一下~~!
kongxiangtong28 回答时间:2019-11-16 12:08:07
您好,能给我发一下G4的pack吗?官网下载老是提示错误,谢谢
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版