本帖最后由 背包旅行码农 于 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.  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管脚,代码如下: - /*******************************************************************************
; D% G% C* I! U; B+ d1 j0 z2 J5 h - * Function Name : I2C_DevInit9 u: @' s$ `) Y) S8 Z+ k
- * Description : Initializes peripherals used by the I2C EEPROM driver.6 c6 j- N7 S f$ v3 O' h% _
- * Input : None
q1 `7 y7 X! h - * Output : None; e) ^& k7 _* I9 i. H
- * Return : None
/ f9 {; `4 O8 w: T A - *******************************************************************************/+ w4 O% U+ z: }- B8 x
- void I2C_DevInit(void)4 G: o+ {8 h/ o* J5 u0 i; _5 Z
- {
2 _7 [% ~) O$ U, T( Y - I2C_InitTypeDef I2C_InitStructure;# D8 f" b5 q/ A
- GPIO_InitTypeDef GPIO_InitStructure;
2 o+ k$ C/ [$ H' D) F4 q - " d- e4 B7 L! J
- /** I2C1 GPIO Configuration
0 ?( m; q- ^4 e* B0 t; R( L5 \9 K - PB8 ------> I2C1_SCL 8 `0 E- M& n# [7 g: {
- PB9 ------> I2C1_SDA */ 8 A+ v1 X- I5 x
- /*Enable or disable the AHB peripheral clock */ ( S$ m- D4 ^7 i3 @
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); /*Configure GPIO pin */6 l7 S9 Y& Q; d2 d+ A* K% J
- $ x% G, U" N+ p7 D% v% z% k
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; 2 X5 M* z% y8 K* F6 C3 s! C
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 3 Q) p2 l: \- Q
- GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
) B8 H0 Q9 F3 X8 h8 e7 y( }- i - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
2 t# P4 _# v$ {8 ^% T - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;/ j9 T: F# @5 y' N. ~
-
4 x$ e( F* ^) E' ?1 b; c b- u - GPIO_Init(GPIOB, &GPIO_InitStructure);7 L! [0 i& R0 s O8 q
- ) O$ _8 Q E' C
- /*Configure GPIO pin alternate function */
1 O, Y6 e$ |5 z' Z; M - GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_1);
+ \2 \- ^) i4 F: c: a2 W# V - GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_1);
$ E, k5 ]+ A0 z# A
; J" k* u) l2 y" o5 _- RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
% D7 t7 \, H) L9 O - RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);8 n) B; v1 R$ K3 i8 I' _- s
-
) f0 H5 f# p( f - I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
! V1 B* y2 o7 `9 p - I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
% A3 r9 Y- O7 u8 C5 f - I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;+ q8 }1 s4 n1 R/ G' k6 g/ ^* U+ r; G
- I2C_InitStructure.I2C_DigitalFilter = 0x01;) q1 P% K' Q' ^; t6 O+ G8 Y# I
- I2C_InitStructure.I2C_OwnAddress1=0x00;
8 q% @0 @7 v/ [$ ~* G' g9 Y - //I2C_InitStructure.I2C_Timing = 0x40B22536;//100Khz
0 N! ]- x+ i, ?! h - I2C_InitStructure.I2C_Timing =0x10950C27;//400Khz: D7 j0 o- S i T* J- u+ l
- I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;# R% X8 E! `9 b3 b* O
-
3 W; L, e+ T/ j5 A - I2C_Init(I2C1, &I2C_InitStructure); 0 B. ?( K/ X f' s, c
- I2C_Cmd(I2C1, ENABLE);
; ?$ Y* k, k* Z, ?" K - return;4 S0 J) [" l3 |& t5 ]* ?
- }
复制代码
( P+ m5 q7 C1 t8 M P I2C多字节写实现 - /*******************************************************************************
h$ G: x3 b" a# d- B: T - * Function Name : I2C_Write
, P2 }, M6 [: [ - * Description : Writes more than one byte to the Device with a single WRITE
$ v2 G' s1 Z9 i/ V$ i# q - * cycle. The number of byte can't exceed the Device page size.
, O, u+ c: D1 Z* X0 V3 w - * Input : - pBuffer : pointer to the buffer containing the data to be
6 J& z" {+ q; v6 X. n5 w( Y - * written to the Device.
! F4 i- W. {# n' v2 H5 X - * - WriteAddr : Device's internal address to write to.+ K/ L }: q3 `( H
- * - NumByteToWrite : number of bytes to write to the Device.
/ y5 X6 R/ i9 O* M; I5 M4 D1 R8 V% h - * Output : None
: H+ P' c- y! t- O - * Return : None
2 m s0 X' {0 [ m' z, s9 I8 W - *******************************************************************************/
5 ]. Q& ^' K4 g2 {: ?' Y( f6 j - BOOLEAN I2C_Write(INT8U DevAddr, INT8U RegAddr,INT8U* pBuffer, INT8U NumByteToWrite)0 E: r# p( m3 d" j
- {
+ @8 o, b; `$ Y( V; e - INT16U timeout = I2C_TIMEOUT;; c, @ q' o G% H
- $ V0 z6 \( f, n1 h3 w
- /* While the bus is busy */
1 S8 u) n0 N" Y; a: P - while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)3 `$ g }3 _5 ]3 y- x _$ L8 }# f9 F
- {$ @% D; o2 P" O0 Y% |
- if((timeout--) == 0)
; M4 T% s0 E- d& Y2 p# K$ q' p - {
" @5 W, A6 s/ K2 r- C+ B- p - return false;( V! |# u) I5 C. f/ d( b6 x0 o
- }
# h0 ~& A9 D9 h9 J - }. m7 T0 H/ c! ]! n9 e* u% ]/ B
- * P7 Y' @) i; \5 w
- /* Send Touch address for write */
- S0 a9 O" r6 X8 ?8 U - 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
- ( |; {6 ]0 V; P" \; b9 r% k
- timeout = I2C_TIMEOUT;
' K8 f" G4 a0 z! f4 v - while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS)==RESET)
; J1 f" @' F, s - {& S0 s$ j- J/ \
- if((timeout--) == 0)) c Y9 Y6 q9 q
- {
3 L5 H8 s4 l3 J+ Y! |$ ~8 g3 [ - return false;
: U* Z5 T6 w n# E, G - }/ b+ E. x8 E0 b" h- ?
- }: E4 d, A* ~0 m2 h- F
- $ x- R0 i, [7 s" i2 [
- I2C_SendData(I2C1, RegAddr);4 m2 p( \, _8 q# i# M. c
- " D! `9 A8 ] }/ F% Y
- timeout = I2C_TIMEOUT;% w1 G- G7 P1 l h! Y& J9 W
- while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TCR) == RESET) J# ~2 J9 J! g# \; G; B% ^
- {7 v) o( z1 c f. Y4 `
- if((timeout--) == 0)
q, {6 y P7 X - {
" ^+ j' g1 d; Z0 U5 W; s - return false;
5 ~( N' u" \) M$ {0 E. l; V3 u - }
0 B* C$ h8 n+ D - }
+ G% p1 N' h& d8 ]2 ]/ w) g - ! o. U" B3 a8 G) v/ j' E" V& |
- I2C_TransferHandling(I2C1, (DevAddr<<1), NumByteToWrite, I2C_AutoEnd_Mode, I2C_No_StartStop);
5 I* k) ~" B0 g A, q/ F - & ~8 u8 Q" r8 Y1 X
- /* While there is data to be written */% M7 h& q% F3 u* F- f1 H, B
- while(NumByteToWrite--) 3 O$ `3 c2 ?, P K
- {2 K% V7 _3 f& P
- timeout = I2C_TIMEOUT;& }1 }$ j$ @0 e
- /* Test on EV8 and clear it */
$ U7 L, C" a4 a& o - while (I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET): ~) [" m+ m1 e' c, H/ ]
- {2 Q% \0 j9 q/ @ O
- if((timeout--) == 0): L) Z$ v; Z1 z+ a' q% m% F
- {1 `' D' {% k' _8 E
- return false;. ^2 ^* R, z6 `9 k. k0 V3 F
- }
8 N9 Z6 P0 a# k. M' e7 G- U' | - }8 e' a! g# e. M5 x2 Y' e2 O8 ~
- /* Send the current byte */4 o8 q+ Q. y* t; I
- I2C_SendData(I2C1, *pBuffer); $ [! L, s: G g2 b, d: W
- 3 w! _. M* f) Z: a: a4 ]7 [7 c
- /* Point to the next byte to be written */
1 P% w- C+ s6 c) P9 T0 ^ - pBuffer++;
. J+ t! T. o- D$ |6 a% H" @ - }
$ R/ v7 A/ p( r - /* Send STOP condition */8 J/ [# n5 s H. c9 s7 m
- timeout = I2C_TIMEOUT;1 Q8 m4 ^/ F5 X* d
- while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)
, A3 A) Z$ o8 ?/ Q& a- e o' L - {
. m1 T' L$ s# j- f/ g - if((timeout--) == 0)
9 {3 `- g% j+ B9 b/ b - {
( t, j' _( L# J - return false;2 N2 c7 ] Z" y; Q) L
- }9 ]) h, J, g w8 Q! s
- }1 g# Z7 [2 H) p4 k9 z3 N! e
- 0 w9 O$ I# w: J# N* H. {) d9 |
- return true;
- O9 g( R" P u6 S* G -
# H/ d7 S( t: m, ? - }
复制代码 $ Z" V+ v W% d# c
I2C多字节读实现 - /*******************************************************************************
+ ^6 Z0 B; s) }8 R7 g - * Function Name : I2C_Read# M+ k8 ]5 B+ y+ O
- * Description : Reads a block of data from the Device.
2 r0 }9 O: ?6 M! | - * Input : - pBuffer : pointer to the buffer that receives the data read
& u( [+ f* B m5 j4 } - * from the Device.
8 O$ ?" m* F* ^' A2 p/ _% F - * - ReadAddr : EEPROM's internal address to read from.
$ m6 e. A( B+ a! G+ ?2 Q - * - NumByteToRead : number of bytes to read from the Device.
- {7 U: b5 f, f% j; P - * Output : None
# `6 v. A) D2 ^ W - * Return : None
+ i/ U3 T5 _- m. ^" i - *******************************************************************************/* n& C" V" T8 R' B9 K/ ~( r
- BOOLEAN I2C_Read(INT8U DevAddr, INT8U RegAddr, INT8U* pBuffer, INT8U NumByteToRead)5 ^' J4 R) ^/ v, T# P% X) s
- { , H6 ?' T& A3 L" O+ `6 y' f c" z8 g2 t
- INT16U timeout = 60;1 d+ Z! n* R( g, a
* m( R- C/ }5 {/ l4 E* q- /* While the bus is busy */
/ b2 T4 @) {. o1 A0 A5 u1 I - while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)( n" D7 k& B! U2 ?& B, A
- {
8 ~& S. d/ N1 o$ S - if((timeout--) == 0)# P( N, j' R# S% L
- {; k" z. e/ i3 l. n' t2 E4 @' F" t9 G
- return false;* j1 @8 {# c6 V
- }
7 a0 d2 O! r4 U1 X* O [" z% S - }2 `# o+ d& d) j8 {2 c: i0 o
- : c6 Y- w1 M. A# ]" q9 O
- /* Generate start & wait event detection */0 i/ v# C* |% x' a
- I2C_TransferHandling(I2C1, (DevAddr<<1), 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);' Q& r* R0 n7 e3 z/ ]
) }0 i+ c2 |8 F9 @; x# V5 _- 3 r$ ]# w3 N" z( D3 ]. U
- timeout = I2C_TIMEOUT;
5 }: W% V9 T3 O- ?+ O - while (I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
' M! W4 g% P8 |; \ - {
# _6 ~' q4 J4 J/ G0 s0 l8 W1 y - if((timeout--) == 0)0 a4 f0 m: ?6 i) @2 @6 J
- {
. S; c1 h+ Z0 w- O% T9 V - return false;8 i3 j& y8 H$ {, S% P2 A
- }
2 [ ]2 f% M. P: t9 q - }$ A. m* F, T) o1 ?
2 S8 D9 v4 m+ B* y+ j2 t: R- I2C_SendData(I2C1, RegAddr);+ h* W: M- `# S
9 y. H7 t9 l- U G4 v& N, s1 i- timeout = I2C_TIMEOUT; 5 e" m5 y$ {8 o) @; c& `
- while (I2C_GetFlagStatus(I2C1, I2C_FLAG_TC) == RESET)9 e5 E9 ?0 l# V3 T! Z# i
- {$ V+ a0 L- f: P( h) }3 G
- if((timeout--) == 0)
4 c& g: g3 d" r+ N" R" M$ j3 N- ` - {
r u0 H* H6 T( P: W9 R - return false;
: B$ A! d: n1 b4 B: R9 Q3 x - } f( l0 E) H2 k5 p
- }
) y% E5 g9 J5 }$ T1 l2 X( F
' e: t- w3 f5 b0 p4 a- /* Send STRAT condition a second time */ 5 t2 `& `# z' T$ ^" j& H. f4 R
- I2C_TransferHandling(I2C1, (DevAddr<<1), NumByteToRead, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
7 Z9 {1 P9 z6 z6 ?5 g" x4 D -
$ G2 E4 h0 K D5 [- q9 b- l - /* While there is data to be read */
% z! C- j* |+ \4 v - while(NumByteToRead)
2 \4 `" G* {$ ^: L2 e' ?% q6 Q" u - { # Y$ _0 L! X- Q4 V
- timeout = I2C_TIMEOUT;) S2 f l$ T) |# [* d* y0 ]
-
' |6 i7 F: ]4 d" n" C# N - while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET); [4 T2 Z b8 f- J1 d# b
- {( f; G$ y3 g6 n. W( A2 F5 s1 \. x) H v
- if((timeout--) == 0)9 ?9 A$ K$ M1 g6 W
- {
# Q5 y& D: D( h2 t: Y% |" q - return false;
8 i/ t6 z. t; D& X - }$ F+ N2 L& k5 j5 }+ k1 B
- }
# T& m6 V2 Y. [- g2 V# q) w
# e) M, Z- j- I" y! I+ X+ _/ |7 p- /* Read a byte from the EEPROM */3 d6 d6 j3 e, @
- *pBuffer = I2C_ReceiveData(I2C1);
9 N: y" Y/ F4 K- Y1 c6 C6 A( H7 @ - & S1 ]) @5 o2 M9 s* g! \
- /* Point to the next location where the byte read will be saved */. |2 E. T8 B' O7 R( ^" n, W) u
- pBuffer++; + M" m2 W3 d9 `. T- a- W& _
- y: A' |' n' f: l% U) L& W2 S
- /* Decrement the read bytes counter */
: U2 b; a) ]% M9 Q, A - NumByteToRead--;
1 G0 u, U( x; t2 W# `9 B - }" T9 U [- ]" u
-
# |1 I0 D, t$ E - /* Enable Acknowledgement to be ready for another reception */& c8 K$ X3 \9 U6 V: i
- timeout = I2C_TIMEOUT;
: }& v# L$ ~% v. J) ^ - while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)
" @ ^- ]) D! W$ c1 g& |6 x - {+ v$ u- u4 D: l+ _) k9 n1 L
- if((timeout--) == 0): s3 u5 ~* v, K% q# ^5 C5 _0 I
- {
* b3 D- _( F( T2 J( }7 h0 a. C5 W$ h - return false;3 H+ ~/ V: @9 q( ]9 Z
- }8 i" W5 N( F2 U
- }
1 k" c2 R6 i8 {6 j - return true;
0 S) I1 w4 C& @4 u0 l" v( M2 ~ - }
复制代码 |