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

STM32F030开发日志之I2C

[复制链接]
背包旅行码农 发布时间:2017-4-8 23:28
本帖最后由 背包旅行码农 于 2017-4-8 23:31 编辑
9 I! u7 W/ V' F, n/ M$ ~* _0 J9 d8 \
4 Z4 o) P9 Z6 |( x
最近调试 一款 IQS333 电容触摸按键芯片IC,调了好几天发现I2C端口上没数据。最后追STM Clock tree 和STM 提供的I2C_Timing_Configuration工具解决了这个问题。现在分享给大家。
1. 首先我们观察Clock tree 查看 I2C clock source的缘由。
由 Clock tree可以得出I2C clock source 可以选择使用内部8MHz时钟,还是选用的系统SYSCLK.
本人选用的是STM32F030开发板。开发使用的是8MHz的外部晶振。所以采用外部8MHz时钟为例。
根据下面的 clock source时钟走势进行RCC 模块配置:
从走势我们可以看出我们需要确定PREDIV,PLLSRC,PLLMUL,SW和I2C1的源输入选择。
Clock configuration register 2 (RCC_CFGR2)/ R: o3 o% O$ x1 M' h
Clock configuration register (RCC_CFGR)
( w* S: G9 E5 a$ x
最后配置RCC相应的PREDIV,PLLSRC,PLLMUL,SW得到PLLCLK为48MHz.
并且STM32厂商提供得了I2C时钟配置的工具。I2C_Timing_Configuration_V1.0.0.xls
Note: The “Reset” button resets the input parameters to their default configuration.
6 {; j5 q1 S4 h1 ZTo get the value of the timing register, follow these steps:
' J2 D3 X1 Y9 ~* l1. Select device mode by choosing “Master” or “Slave” in the list box.
% [  ^  {+ K+ Y) i5 a7 @& O* f2. Configure the speed mode by selecting one of the following modes in the list box:, @0 ]2 m& U' ]: ^9 j8 u4 ^0 E
– Standard mode: maximum frequency is 100 KHz.9 V- I; P; v  e% H
– Fast mode: maximum frequency is 400 KHz.1 Y% ?6 s! o+ e3 o
– Fast mode Plus: maximum frequency is 1000 KHz.
% h0 ^& H1 ~$ [! `$ ?) b3. Set the desired I2C speed frequency (master clock).
) ]/ O. h& @6 t9 R4. Set the value of I2C clock source frequency.
* l5 O; K! f" |. Q- T. {- r5 V) C# y5. Specify if analog noise filter is enabled or not.! y. W) [" G* M
6. Specify if digital noise filter is used or not by setting the filter coefficient (this coefficient
# X& R/ {! e% [6 q; H9 y2 K# Z7 gshould be an integer from 0 to 15).
% M3 J" D7 x+ \! h, R$ _/ y- U% r7. Set the value of rise time.9 [" d6 s+ O( ^( [8 i% _" X" w
8. Set the value of fall time.( M5 m% P1 ^( B6 e
9. Click the RUN button:# P* I% a- J% G; G% J6 j3 r4 T
a) If the calculation of the timing register is completed, the following message is
& o% }+ G, U9 @displayed:. O9 ~) s  H# R2 ?) w) K, ?
根据STM32厂商提供的配置I2C时钟说明,根据自己的应用我的配置如下:
因此在配置I2C的使用Timing的值如下
然后配置相应的I2C管脚,代码如下:
  1. /*******************************************************************************
    ; D% G% C* I! U; B+ d1 j0 z2 J5 h
  2. * Function Name  : I2C_DevInit9 u: @' s$ `) Y) S8 Z+ k
  3. * Description    : Initializes peripherals used by the I2C EEPROM driver.6 c6 j- N7 S  f$ v3 O' h% _
  4. * Input          : None
      q1 `7 y7 X! h
  5. * Output         : None; e) ^& k7 _* I9 i. H
  6. * Return         : None
    / f9 {; `4 O8 w: T  A
  7. *******************************************************************************/+ w4 O% U+ z: }- B8 x
  8. void I2C_DevInit(void)4 G: o+ {8 h/ o* J5 u0 i; _5 Z
  9. {       
    2 _7 [% ~) O$ U, T( Y
  10.            I2C_InitTypeDef I2C_InitStructure;# D8 f" b5 q/ A
  11.         GPIO_InitTypeDef GPIO_InitStructure;
    2 o+ k$ C/ [$ H' D) F4 q
  12.         " d- e4 B7 L! J
  13.         /** I2C1 GPIO Configuration                         
    0 ?( m; q- ^4 e* B0 t; R( L5 \9 K
  14.         PB8         ------> I2C1_SCL                 8 `0 E- M& n# [7 g: {
  15.         PB9         ------> I2C1_SDA        */        8 A+ v1 X- I5 x
  16.         /*Enable or disable the AHB peripheral clock */        ( S$ m- D4 ^7 i3 @
  17.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);        /*Configure GPIO pin */6 l7 S9 Y& Q; d2 d+ A* K% J
  18.         $ x% G, U" N+ p7 D% v% z% k
  19.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;        2 X5 M* z% y8 K* F6 C3 s! C
  20.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        3 Q) p2 l: \- Q
  21.         GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;       
    ) B8 H0 Q9 F3 X8 h8 e7 y( }- i
  22.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;       
    2 t# P4 _# v$ {8 ^% T
  23.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;/ j9 T: F# @5 y' N. ~
  24.        
    4 x$ e( F* ^) E' ?1 b; c  b- u
  25.         GPIO_Init(GPIOB, &GPIO_InitStructure);7 L! [0 i& R0 s  O8 q
  26.         ) O$ _8 Q  E' C
  27.         /*Configure GPIO pin alternate function */       
    1 O, Y6 e$ |5 z' Z; M
  28.         GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_1);       
    + \2 \- ^) i4 F: c: a2 W# V
  29.         GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_1);
    $ E, k5 ]+ A0 z# A

  30. ; J" k* u) l2 y" o5 _
  31.         RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
    % D7 t7 \, H) L9 O
  32.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);8 n) B; v1 R$ K3 i8 I' _- s
  33.        
    ) f0 H5 f# p( f
  34.         I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    ! V1 B* y2 o7 `9 p
  35.         I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;       
    % A3 r9 Y- O7 u8 C5 f
  36.         I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;+ q8 }1 s4 n1 R/ G' k6 g/ ^* U+ r; G
  37.         I2C_InitStructure.I2C_DigitalFilter = 0x01;) q1 P% K' Q' ^; t6 O+ G8 Y# I
  38.         I2C_InitStructure.I2C_OwnAddress1=0x00;
    8 q% @0 @7 v/ [$ ~* G' g9 Y
  39.         //I2C_InitStructure.I2C_Timing = 0x40B22536;//100Khz
    0 N! ]- x+ i, ?! h
  40.         I2C_InitStructure.I2C_Timing =0x10950C27;//400Khz: D7 j0 o- S  i  T* J- u+ l
  41.         I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;# R% X8 E! `9 b3 b* O
  42.        
    3 W; L, e+ T/ j5 A
  43.         I2C_Init(I2C1, &I2C_InitStructure);        0 B. ?( K/ X  f' s, c
  44.         I2C_Cmd(I2C1, ENABLE);
    ; ?$ Y* k, k* Z, ?" K
  45.         return;4 S0 J) [" l3 |& t5 ]* ?
  46. }
复制代码

( P+ m5 q7 C1 t8 M  P
I2C多字节写实现
  1. /*******************************************************************************
      h$ G: x3 b" a# d- B: T
  2. * Function Name  : I2C_Write
    , P2 }, M6 [: [
  3. * Description    : Writes more than one byte to the Device with a single WRITE
    $ v2 G' s1 Z9 i/ V$ i# q
  4. *                  cycle. The number of byte can't exceed the Device page size.
    , O, u+ c: D1 Z* X0 V3 w
  5. * Input          : - pBuffer : pointer to the buffer containing the data to be
    6 J& z" {+ q; v6 X. n5 w( Y
  6. *                    written to the Device.
    ! F4 i- W. {# n' v2 H5 X
  7. *                  - WriteAddr : Device's internal address to write to.+ K/ L  }: q3 `( H
  8. *                  - NumByteToWrite : number of bytes to write to the Device.
    / y5 X6 R/ i9 O* M; I5 M4 D1 R8 V% h
  9. * Output         : None
    : H+ P' c- y! t- O
  10. * Return         : None
    2 m  s0 X' {0 [  m' z, s9 I8 W
  11. *******************************************************************************/
    5 ]. Q& ^' K4 g2 {: ?' Y( f6 j
  12. BOOLEAN  I2C_Write(INT8U DevAddr, INT8U RegAddr,INT8U* pBuffer, INT8U NumByteToWrite)0 E: r# p( m3 d" j
  13. {
    + @8 o, b; `$ Y( V; e
  14.         INT16U timeout = I2C_TIMEOUT;; c, @  q' o  G% H
  15.         $ V0 z6 \( f, n1 h3 w
  16.         /* While the bus is busy */
    1 S8 u) n0 N" Y; a: P
  17.         while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)3 `$ g  }3 _5 ]3 y- x  _$ L8 }# f9 F
  18.         {$ @% D; o2 P" O0 Y% |
  19.                 if((timeout--) == 0)
    ; M4 T% s0 E- d& Y2 p# K$ q' p
  20.                 {
    " @5 W, A6 s/ K2 r- C+ B- p
  21.                         return false;( V! |# u) I5 C. f/ d( b6 x0 o
  22.                 }
    # h0 ~& A9 D9 h9 J
  23.         }. m7 T0 H/ c! ]! n9 e* u% ]/ B
  24.         * P7 Y' @) i; \5 w
  25.         /* Send Touch address for write */       
    - S0 a9 O" r6 X8 ?8 U
  26.         I2C_TransferHandling(I2C1, (DevAddr<<1), 1, I2C_Reload_Mode, I2C_Generate_Start_Write);% C6 o# @8 u& e/ N1 {2 @3 z) x$ Q4 M
  27.         ( |; {6 ]0 V; P" \; b9 r% k
  28.         timeout = I2C_TIMEOUT;
    ' K8 f" G4 a0 z! f4 v
  29.         while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS)==RESET)
    ; J1 f" @' F, s
  30.         {& S0 s$ j- J/ \
  31.                 if((timeout--) == 0)) c  Y9 Y6 q9 q
  32.                 {
    3 L5 H8 s4 l3 J+ Y! |$ ~8 g3 [
  33.                         return false;
    : U* Z5 T6 w  n# E, G
  34.                 }/ b+ E. x8 E0 b" h- ?
  35.         }: E4 d, A* ~0 m2 h- F
  36.         $ x- R0 i, [7 s" i2 [
  37.         I2C_SendData(I2C1, RegAddr);4 m2 p( \, _8 q# i# M. c
  38. " D! `9 A8 ]  }/ F% Y
  39.         timeout = I2C_TIMEOUT;% w1 G- G7 P1 l  h! Y& J9 W
  40.         while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TCR) == RESET)  J# ~2 J9 J! g# \; G; B% ^
  41.         {7 v) o( z1 c  f. Y4 `
  42.                 if((timeout--) == 0)
      q, {6 y  P7 X
  43.                 {
    " ^+ j' g1 d; Z0 U5 W; s
  44.                         return false;
    5 ~( N' u" \) M$ {0 E. l; V3 u
  45.                 }
    0 B* C$ h8 n+ D
  46.         }
    + G% p1 N' h& d8 ]2 ]/ w) g
  47.         ! o. U" B3 a8 G) v/ j' E" V& |
  48.         I2C_TransferHandling(I2C1, (DevAddr<<1), NumByteToWrite, I2C_AutoEnd_Mode, I2C_No_StartStop);
    5 I* k) ~" B0 g  A, q/ F
  49.         & ~8 u8 Q" r8 Y1 X
  50.         /* While there is data to be written */% M7 h& q% F3 u* F- f1 H, B
  51.         while(NumByteToWrite--)  3 O$ `3 c2 ?, P  K
  52.         {2 K% V7 _3 f& P
  53.                 timeout = I2C_TIMEOUT;& }1 }$ j$ @0 e
  54.                 /* Test on EV8 and clear it */
    $ U7 L, C" a4 a& o
  55.                 while (I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET): ~) [" m+ m1 e' c, H/ ]
  56.                 {2 Q% \0 j9 q/ @  O
  57.                         if((timeout--) == 0): L) Z$ v; Z1 z+ a' q% m% F
  58.                         {1 `' D' {% k' _8 E
  59.                                 return false;. ^2 ^* R, z6 `9 k. k0 V3 F
  60.                         }
    8 N9 Z6 P0 a# k. M' e7 G- U' |
  61.                 }8 e' a! g# e. M5 x2 Y' e2 O8 ~
  62.                 /* Send the current byte */4 o8 q+ Q. y* t; I
  63.                 I2C_SendData(I2C1, *pBuffer); $ [! L, s: G  g2 b, d: W
  64. 3 w! _. M* f) Z: a: a4 ]7 [7 c
  65.                 /* Point to the next byte to be written */
    1 P% w- C+ s6 c) P9 T0 ^
  66.                 pBuffer++;                
    . J+ t! T. o- D$ |6 a% H" @
  67.         }
    $ R/ v7 A/ p( r
  68.         /* Send STOP condition */8 J/ [# n5 s  H. c9 s7 m
  69.         timeout = I2C_TIMEOUT;1 Q8 m4 ^/ F5 X* d
  70.         while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)
    , A3 A) Z$ o8 ?/ Q& a- e  o' L
  71.         {
    . m1 T' L$ s# j- f/ g
  72.                 if((timeout--) == 0)
    9 {3 `- g% j+ B9 b/ b
  73.                 {
    ( t, j' _( L# J
  74.                         return false;2 N2 c7 ]  Z" y; Q) L
  75.                 }9 ]) h, J, g  w8 Q! s
  76.         }1 g# Z7 [2 H) p4 k9 z3 N! e
  77.         0 w9 O$ I# w: J# N* H. {) d9 |
  78.         return true;
    - O9 g( R" P  u6 S* G
  79.        
    # H/ d7 S( t: m, ?
  80. }
复制代码
$ Z" V+ v  W% d# c
I2C多字节读实现
  1. /*******************************************************************************
    + ^6 Z0 B; s) }8 R7 g
  2. * Function Name  : I2C_Read# M+ k8 ]5 B+ y+ O
  3. * Description    : Reads a block of data from the Device.
    2 r0 }9 O: ?6 M! |
  4. * Input          : - pBuffer : pointer to the buffer that receives the data read
    & u( [+ f* B  m5 j4 }
  5. *                    from the Device.
    8 O$ ?" m* F* ^' A2 p/ _% F
  6. *                  - ReadAddr : EEPROM's internal address to read from.
    $ m6 e. A( B+ a! G+ ?2 Q
  7. *                  - NumByteToRead : number of bytes to read from the Device.
    - {7 U: b5 f, f% j; P
  8. * Output         : None
    # `6 v. A) D2 ^  W
  9. * Return         : None
    + i/ U3 T5 _- m. ^" i
  10. *******************************************************************************/* n& C" V" T8 R' B9 K/ ~( r
  11. BOOLEAN  I2C_Read(INT8U DevAddr, INT8U RegAddr, INT8U* pBuffer, INT8U NumByteToRead)5 ^' J4 R) ^/ v, T# P% X) s
  12. {  , H6 ?' T& A3 L" O+ `6 y' f  c" z8 g2 t
  13.         INT16U timeout = 60;1 d+ Z! n* R( g, a

  14. * m( R- C/ }5 {/ l4 E* q
  15.         /* While the bus is busy */
    / b2 T4 @) {. o1 A0 A5 u1 I
  16.         while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)( n" D7 k& B! U2 ?& B, A
  17.         {
    8 ~& S. d/ N1 o$ S
  18.                 if((timeout--) == 0)# P( N, j' R# S% L
  19.                 {; k" z. e/ i3 l. n' t2 E4 @' F" t9 G
  20.                         return false;* j1 @8 {# c6 V
  21.                 }
    7 a0 d2 O! r4 U1 X* O  [" z% S
  22.         }2 `# o+ d& d) j8 {2 c: i0 o
  23. : c6 Y- w1 M. A# ]" q9 O
  24.         /* Generate start & wait event detection */0 i/ v# C* |% x' a
  25.         I2C_TransferHandling(I2C1, (DevAddr<<1), 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);' Q& r* R0 n7 e3 z/ ]

  26. ) }0 i+ c2 |8 F9 @; x# V5 _
  27. 3 r$ ]# w3 N" z( D3 ]. U
  28.         timeout = I2C_TIMEOUT;
    5 }: W% V9 T3 O- ?+ O
  29.         while (I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
    ' M! W4 g% P8 |; \
  30.         {
    # _6 ~' q4 J4 J/ G0 s0 l8 W1 y
  31.                 if((timeout--) == 0)0 a4 f0 m: ?6 i) @2 @6 J
  32.                 {
    . S; c1 h+ Z0 w- O% T9 V
  33.                         return false;8 i3 j& y8 H$ {, S% P2 A
  34.                 }
    2 [  ]2 f% M. P: t9 q
  35.         }$ A. m* F, T) o1 ?

  36. 2 S8 D9 v4 m+ B* y+ j2 t: R
  37.         I2C_SendData(I2C1, RegAddr);+ h* W: M- `# S

  38. 9 y. H7 t9 l- U  G4 v& N, s1 i
  39.         timeout = I2C_TIMEOUT;        5 e" m5 y$ {8 o) @; c& `
  40.         while (I2C_GetFlagStatus(I2C1, I2C_FLAG_TC) == RESET)9 e5 E9 ?0 l# V3 T! Z# i
  41.         {$ V+ a0 L- f: P( h) }3 G
  42.                 if((timeout--) == 0)
    4 c& g: g3 d" r+ N" R" M$ j3 N- `
  43.                 {
      r  u0 H* H6 T( P: W9 R
  44.                         return false;
    : B$ A! d: n1 b4 B: R9 Q3 x
  45.                 }  f( l0 E) H2 k5 p
  46.         }
    ) y% E5 g9 J5 }$ T1 l2 X( F

  47. ' e: t- w3 f5 b0 p4 a
  48.         /* Send STRAT condition a second time */  5 t2 `& `# z' T$ ^" j& H. f4 R
  49.         I2C_TransferHandling(I2C1, (DevAddr<<1), NumByteToRead,  I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
    7 Z9 {1 P9 z6 z6 ?5 g" x4 D
  50.        
    $ G2 E4 h0 K  D5 [- q9 b- l
  51.         /* While there is data to be read */
    % z! C- j* |+ \4 v
  52.         while(NumByteToRead)  
    2 \4 `" G* {$ ^: L2 e' ?% q6 Q" u
  53.         {        # Y$ _0 L! X- Q4 V
  54.                 timeout = I2C_TIMEOUT;) S2 f  l$ T) |# [* d* y0 ]
  55.                
    ' |6 i7 F: ]4 d" n" C# N
  56.                 while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET); [4 T2 Z  b8 f- J1 d# b
  57.                 {( f; G$ y3 g6 n. W( A2 F5 s1 \. x) H  v
  58.                         if((timeout--) == 0)9 ?9 A$ K$ M1 g6 W
  59.                         {
    # Q5 y& D: D( h2 t: Y% |" q
  60.                                 return false;
    8 i/ t6 z. t; D& X
  61.                         }$ F+ N2 L& k5 j5 }+ k1 B
  62.                 }
    # T& m6 V2 Y. [- g2 V# q) w

  63. # e) M, Z- j- I" y! I+ X+ _/ |7 p
  64.                 /* Read a byte from the EEPROM */3 d6 d6 j3 e, @
  65.                 *pBuffer = I2C_ReceiveData(I2C1);
    9 N: y" Y/ F4 K- Y1 c6 C6 A( H7 @
  66. & S1 ]) @5 o2 M9 s* g! \
  67.                 /* Point to the next location where the byte read will be saved */. |2 E. T8 B' O7 R( ^" n, W) u
  68.                 pBuffer++; + M" m2 W3 d9 `. T- a- W& _
  69.   y: A' |' n' f: l% U) L& W2 S
  70.                 /* Decrement the read bytes counter */
    : U2 b; a) ]% M9 Q, A
  71.                 NumByteToRead--;        
    1 G0 u, U( x; t2 W# `9 B
  72.         }" T9 U  [- ]" u
  73.        
    # |1 I0 D, t$ E
  74.         /* Enable Acknowledgement to be ready for another reception */& c8 K$ X3 \9 U6 V: i
  75.         timeout = I2C_TIMEOUT;
    : }& v# L$ ~% v. J) ^
  76.         while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)
    " @  ^- ]) D! W$ c1 g& |6 x
  77.         {+ v$ u- u4 D: l+ _) k9 n1 L
  78.                 if((timeout--) == 0): s3 u5 ~* v, K% q# ^5 C5 _0 I
  79.                 {
    * b3 D- _( F( T2 J( }7 h0 a. C5 W$ h
  80.                         return false;3 H+ ~/ V: @9 q( ]9 Z
  81.                 }8 i" W5 N( F2 U
  82.         }
    1 k" c2 R6 i8 {6 j
  83.         return true;
    0 S) I1 w4 C& @4 u0 l" v( M2 ~
  84. }
复制代码
赞 收藏 1 评论3 发布时间:2017-4-8 23:28

举报

3个回答
lisingch 回答时间:2017-4-9 08:59:43
图片打不开。
suoma 回答时间:2017-4-9 08:59:57
谢谢分享学习一下
大海-399550 回答时间:2018-1-27 22:30:19
感谢分享。MARK,用到时来取。

所属标签

相似技术帖

官网相关资源

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