I2C配置顺序引发的异常案例
+ X9 E3 Z/ F# ~6 H$ ~8 a' H( B: g- G3 w
基于stm32的I2C总线通讯简介及使用操作(附代码)
5 Q9 Y S6 m% e, Y7 {! m- J4 m e$ O& M u
分享关于STM32f103 的硬件IIC I2C 调试心得
3 U% g3 {( n3 I; ?
6 n: ? q6 u# G( a+ f7 H1 h0 e
8 [ c) o- O3 i& `. a! k楼主前段时间苦调UV传感器,无奈硬件I2C怎么也用不起来,楼主水平还是太弱,无奈只好转入软件模拟I2C,不过话说模拟I2C的波形似乎要比硬件I2C的要好很多呢。调好的代码与大家分享下。。。源模板是哥们做好的读取E2的代码。$ N% K5 m& F' _9 Z. Y& u& i
- #include "stm32f10x.h"8 s, j& V! C' L/ `+ [- A" c
- //=============================================================================== " D) p1 T! q, m/ k( U
- //GPIO 模拟I2C ,操作EP2ROM IC(AT24C02) + v: ~7 M' Z! b ^) E. Q
- #define E2PROM_SDA GPIO_Pin_7: |( c( D8 S' S: k' P. j4 H
- #define E2PROM_SCL GPIO_Pin_6
! I- r& D" y7 R2 ~. U! Z( J2 R - #define E2PROM_CMD_WRITE 0xa0
( b' J J7 f, |* u2 _, k B - #define E2PROM_CMD_READ 0xa17 D2 e, ~- R; ?" G; p; |
- #define I2C_DELAY 254 // ' W: P% P( X" N1 t, b0 Q
- + z& R- ]% Z+ t; o. @
- I2C延时8 c& B5 M4 {; p' w E! U
3 Q5 |" l+ K$ d9 K- static void1 H# m' m, z1 i& ^
- DelayMs(uint8_t uc)* H: v- w3 A$ {1 O
- {# B# H O6 Y8 p' R1 B2 `6 H8 v% P
- uint8_t i, j;. \+ A4 X: p) h5 O# I
- 7 K* {+ d" L' j5 n
- for (i=0; i<uc; i++) {8 S/ p- S4 W' | A2 ]8 ], \! }1 l
- for (j=0; j<I2C_DELAY; j++);
1 q& I* y0 w" Y/ J$ Q/ } - }: z6 v0 ]5 T/ W# ~. h& ~# Z* K/ n' z
- }
% H$ c: C5 p2 W$ x - /************************************************************* ; t6 N6 r+ J; t5 ?/ y
- *函数名称:I2CStart ! P' j* F* k# F, x3 {
- *函数功能:I2C开始信号
: L/ O4 A: g5 y+ [; L - *输入参数:
1 i$ q' B1 m1 j - *输出参数:
1 Q8 v2 Y; Y0 ^5 }9 f1 J' E$ S - *备 注:时钟线高时,数据线由高到低的跳变,表示I2C开始信号
, H/ J) g m' o0 b7 k: c - **************************************************************/
( y3 B* T6 \. A& W6 ~ - void I2CStart( void )
~9 b* R- e% _( J# \% r2 M! C8 x - { 9 A5 p: }& R, \! M b
- GPIO_SetBits( GPIOB, E2PROM_SDA ); M: k( z+ G: _2 r" F' o2 s
- DelayMs(1); 4 F6 m" r+ P2 o# b+ y" g9 A% t7 u
- GPIO_SetBits( GPIOB, E2PROM_SCL );
4 d7 m. c0 m# [* F - DelayMs(1); 8 m+ i, b, w+ E! G( x1 \( Y
- GPIO_ResetBits( GPIOB, E2PROM_SDA ); + r6 R P% F. p* N7 X
- DelayMs(1);
' e9 ~. Q8 j$ w3 J
" S6 I% y' @0 E9 o5 X/ j1 t- GPIO_ResetBits( GPIOB, E2PROM_SCL ); * g9 u7 r' A% \* k
- }
, K" D8 D: v1 a: w
' R9 X& @+ d3 y- D2 `; Y- /*************************************************************
5 u4 r/ c0 l+ i7 X( k+ d' [. u! z# U - *函数名称:I2CStop
3 m/ j8 ^: G; \! V. Z - *函数功能:I2C停止信号
+ @/ {7 F B+ ~ - *输入参数:
' W* J8 t: O9 `. c$ h. A: }8 W& J - *输出参数:
/ n9 Z% B" J( p: | - *备 注:时钟线高时,数据线由低到高的跳变,表示I2C停止信号 " Y8 Z5 Y( J4 K+ n
- **************************************************************/
6 e3 V0 {7 m$ O' L& ~0 | - void I2CStop( void )
+ h: E& Z8 Y+ N& Q: _/ n6 Q! Y) L - {
+ [ s% V0 L0 r- w ~ - GPIO_ResetBits( GPIOB, E2PROM_SDA );
* T* o; _/ f# E \9 @* X - DelayMs(1);
+ m- q8 \" m& b5 ?- e! g# P - GPIO_SetBits( GPIOB, E2PROM_SCL );
: [5 L6 i3 S/ j7 c3 K; [$ x - DelayMs(1); 6 f/ c3 r7 C1 B& [& R, ^9 [" e
- GPIO_SetBits( GPIOB, E2PROM_SDA );
% Z* ^# N' s& T/ H6 Z0 U - DelayMs(1);
9 L- I8 Y% j% D4 \/ O+ ^
. Q; `7 O8 F; d: R Q, Q% U0 m* O! C0 x- GPIO_ResetBits( GPIOB, E2PROM_SCL );
6 w3 B: I. _8 W% t& v( }$ b" a - }
& i& {# O7 R6 J$ K - ' J* P' f2 ` e- u( D
- /************************************************************* 8 {# R1 p, A5 m( @
- *函数名称:I2CSlaveAck & o) f' H9 \, V
- *函数功能:I2C从机设备应答查询 2 p5 I* E. p; _) {7 f- {+ F- o
- *输入参数:
, x# s, _+ {. w" [% G - *输出参数: 3 L& Z9 }4 ~0 w3 H; l
- *备 注:
6 M- `# b2 ~( ?! y T# q - **************************************************************/
* s$ W! k+ B" _. Z6 _7 f' Q - unsigned char I2CSlaveAck( void )
6 a3 U. `' n$ G1 |* v; k g - {
; G- ?& Q/ F9 r0 a - GPIO_InitTypeDef GPIO_InitStruct; 5 ]2 O6 [' d4 A6 R
- unsigned int TimeOut; * r- H7 S& G5 }# y3 w. R- Q
- unsigned char RetValue;
5 B! \) r. Z5 F7 T0 \ - 6 B4 G: R# D, v0 F
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; /*这里一定要设成输入上拉,否则不能读出数据*/
: T5 }: n2 ]5 A W: v - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; % b2 S+ e" W) I f0 h6 q
- GPIO_InitStruct.GPIO_Pin = E2PROM_SDA;
, Z. q% W" c F9 u8 L2 S - GPIO_Init( GPIOB, &GPIO_InitStruct );
; B! `' D7 Q" N7 w; L - : c' V% |% E- {) D
- GPIO_SetBits( GPIOB, E2PROM_SCL );
6 t: {" j9 }/ y% y( x3 p - TimeOut = 10000; . O+ J" H# [, R6 V: m) I
- while( TimeOut-- > 0 ) 1 W! C2 j! f: B1 `5 c
- { 3 G L6 l) ^) ?% o
- if( SET == GPIO_ReadInputDataBit( GPIOB, E2PROM_SDA ) ) 4 U3 _: j( C2 @3 v$ I
- { 2 Q/ i# j4 j) G% t1 {$ a
- RetValue = RESET; - o U& d4 W, ^2 R" H5 |* ]4 z/ c: e
- break;
/ J# L1 D }3 y7 G' Y - } W" b/ g0 N" j$ [
- else
! s! A# K- a- k) Q1 u) @ - { . A6 F+ |; }' {9 ^9 M! ]+ w( V
- RetValue = SET;
: O) }7 o# J: K& X {, i - } * ]- y% a; N8 n2 A2 t+ q3 ]# X7 F
- } 7 j% H# |) T" M3 D7 _& l
- GPIO_ResetBits( GPIOB, E2PROM_SCL ); 3 `( Z# C' V9 x3 F/ U2 R9 M
-
2 @# w" i/ N" f% {6 K2 o - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
: ?* O3 b. [2 e - GPIO_Init( GPIOB, &GPIO_InitStruct ); 1 F( [% E" T/ J3 u
- return RetValue; & J b5 X6 W0 j; b4 f' a
- }
/ }+ ?) Y; d$ ^ - " x" e( I% D' V) b3 ]. A
- /************************************************************* 2 K/ p# b* |5 V+ U; E! S
- *函数名称:I2CWriteByte 8 Q8 \3 R7 G$ x& R; Q4 b. N
- *函数功能:I2C写一字节数据
5 D2 c& u; o2 n, t W, v- o - *输入参数: 2 a; C1 d- V# K6 P# z( S7 y
- *输出参数:
* y, X' W; F# G3 L$ @ - *备 注:
$ w7 S( z- X) h! l - **************************************************************/ ; l; g- p$ p9 w3 U) {. N
- void I2CWriteByte( unsigned char byte ) 1 q# I2 h3 d; d$ E/ w! R- B
- { , Z. H* g) |( F/ h, f0 C9 u
- unsigned char i; ! L1 I$ v9 l8 K
- 0 K$ H( r4 n* U4 A
- for( i=0; i<8; i++ ) ) w7 e7 v0 ?! m( N
- { ; @7 B; P: d9 H$ r3 _# u6 e
- if( 0X80 & byte ) # J# @4 a% W& Y# W' a- D
- GPIO_SetBits( GPIOB, E2PROM_SDA );
5 `1 l* Z$ u% ?' \( F+ k6 s0 x6 d - else
% E# N- x6 b6 `7 [- P - GPIO_ResetBits( GPIOB, E2PROM_SDA ); ) \& F( K& d. U( \6 L I
- byte <<= 1; ) q e" F9 y, G, N$ p
- DelayMs(1); 9 _0 {! X$ R9 \- G
- + m# L& O' ]8 E, O( n3 a
- GPIO_SetBits( GPIOB, E2PROM_SCL ); 3 T* B) K9 N& u! d* d+ T
- DelayMs(1);
1 X& _4 S8 @3 u: E+ x T1 d - GPIO_ResetBits( GPIOB, E2PROM_SCL );
/ y: O2 H6 U3 m- X5 R* K5 O - DelayMs(1); 5 q2 K9 F- l1 O% U3 @6 L
- }
/ }* L& R0 h# l - } & y8 ~: z: ^) n/ i9 B2 G- a
- 3 c: {$ i Q" ^9 N5 a' x& T
- /************************************************************* 5 o. {* m6 B8 {& b5 O4 Z6 J
- *函数名称:I2CReadByte
. L' H) ?0 O- {1 v6 h - *函数功能:I2C读一字节数据 7 h7 b8 m+ R' \( w* E2 G" j4 t0 Q
- *输入参数: / ]" p+ Y& p% }$ Y
- *输出参数:
; P1 s# F. y/ X: o - *备 注:
' z; Y+ m* \9 l* \( v) m - **************************************************************/
; u/ H7 ^; h/ t" [. \7 V - unsigned char I2CReadByte( void )
' A2 C8 ]: _* c8 f0 X! p6 D+ c) C; a% i - {
1 k; t1 }$ A+ B. A. r - unsigned char i;
8 G) G+ u! [4 U+ ]0 Z+ Y - unsigned char ReadValue = 0;
) R' W1 n$ d# ~4 }% t9 v - GPIO_InitTypeDef GPIO_InitStruct; - b# B- ^" G ]& L# Q& Z
- unsigned char bit; & l) P) s* D4 S* n: E
. t9 _& S% E N9 `- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; /*这里一定要设成输入上拉,否则不能读出数据*/
9 X5 U$ y: s8 _; i - GPIO_InitStruct.GPIO_Pin = E2PROM_SDA;
/ s* X4 [, M I) S9 ] - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
2 v8 q3 z y, V# d R - GPIO_Init( GPIOB, &GPIO_InitStruct );
3 j' g, o1 ^9 q ] H+ {8 o - for( i=0; i<8; i++ )
9 I- Z% g/ u# Z4 u% ?' { - { 1 X* D8 X# t5 K! G# A1 J- ?$ {- p0 O) ~
- GPIO_SetBits( GPIOB, E2PROM_SCL ); 4 d3 x5 ~2 Z( {$ L0 F$ a
- DelayMs(1); : _" s- S$ E4 U9 Y- x/ e3 i3 s
- if( SET == GPIO_ReadInputDataBit( GPIOB, E2PROM_SDA ) )
# i/ D- _' M4 T; o; h( n8 D - bit = 0X01;
# ]+ S8 \5 H/ U7 f2 p - else & V7 [8 Q/ s& s) y8 q$ l$ F
- bit = 0x00; % r7 B$ r1 O3 i1 M! d3 l
-
* J+ ~2 t9 G& c, E5 V3 M6 w - ReadValue = (ReadValue<<1)|bit;
2 T& g% P3 \* g5 h5 v1 J! q, H - GPIO_ResetBits( GPIOB, E2PROM_SCL );
1 ?0 u) o. V$ X* n3 E - DelayMs(1);
% m. \1 G5 \% x/ x3 @ - } ; e7 T& b: |9 u* j- Z
- 4 ] R" l4 l% r( r8 d. }; Q
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
% k Z, H8 J7 I! [4 }; b - GPIO_Init( GPIOB, &GPIO_InitStruct );
# s! D* X9 }# O5 O$ ]( _& x7 J3 S - return ReadValue;
% o/ S4 \9 H$ L; s2 T - } 8 u/ U4 u! U: b. `
$ k2 d7 R; m; v! ?- A% P! b- /*************************************************************
' L. t9 u2 [, d6 B! } - *函数名称:E2promWriteByte , ]! q0 d( `: k o7 K& d8 L
- *函数功能:E2PROM指定地址写一字节数据
; l3 Q3 r4 s0 V - *输入参数:addr E2PROM地址 + p& U2 c0 D( l/ [5 v; }
- data 写入的数据 % l3 K0 V. A: t t9 o' `3 `
- *输出参数:SET: 写入正常;RESET:写入错误 5 q" y& E* M r& l5 {! W# @0 w
- *备 注:
7 T/ c8 a* e# Z1 T. G( o - **************************************************************/ A" y0 g" Z$ V$ [( N" t
- uint8_t E2promWriteByte( uint16_t addr, uint8_t data ) 8 M7 J0 L# R) m* e# W0 B I
- {
2 r4 v4 s- U) M% e7 ?. B/ A- X - //asm("CPSID I"); //关中断
4 U( {) d( S! O# j$ v - I2CStart(); , l2 X* h& O% _1 O7 |0 v/ F9 A
- - f$ F) O- V. x/ w
- I2CWriteByte( E2PROM_CMD_WRITE ); % E/ z2 h4 C w% s
- if( RESET == I2CSlaveAck() )
3 s( a7 O4 Y! ^) o" B, z - { 8 {5 u& A# K( U4 Z. D( W1 i
- return RESET; 5 a/ r% {6 i9 D+ e
- }/*
1 b( _0 R F. O1 k( P- n' J - I2CWriteByte( (addr >> 8) & 0xFF ); ! R q6 o' D; y
- if( RESET == I2CSlaveAck() )
" X" A' y; j: G! _* r: k - { - }- l5 K6 R3 n. {2 n
- return RESET;
% m1 r7 v; R1 S: y* q - } */
" X$ p" K) c( c+ `5 x - I2CWriteByte( addr & 0xFF);
5 c; Z& Y+ c8 R4 @" x- f - if( RESET == I2CSlaveAck() ) y) M% Y9 u/ Q; h- F- Y
- {
/ O) ^6 b) ~" }# |4 }! O - return RESET;
$ w$ R1 Y- a2 ]* |# T - } 6 Y" D# t, ~( ~9 G
- I2CWriteByte( data );
, K* z$ |& C8 _# F- ` - if( RESET == I2CSlaveAck() )
8 E9 D+ |- t" f( f8 g- r# \: n, ~$ e - { & G& A. ~" u3 o1 n+ U* G( b0 U
- return RESET;
& x( p/ w- O( {( W/ Q" z9 r - }
8 h8 B2 K" \) _! D, p5 ^, k - I2CStop();
$ t4 ?7 Y8 d3 B1 b& j - //asm("CPSIE I"); //关中断
& r) _8 p, |% V
# b+ _6 k3 m" f1 S6 H, s$ m- return SET;
* @) y( k7 m2 f - } 5 d# F, i7 g# L+ C
% j" n: P3 c- [8 f: r- /************************************************************* ! ], k, n6 f4 q' O4 e+ B7 M
- *函数名称:E2promReadByte
' V- w) Q' O' |- M2 Q) l - *函数功能:E2PROM指定地址读一字节数据 + T$ O& J, q; T! Z
- *输入参数:addr E2PROM地址
- C8 J9 B9 M, n - *输出参数:返回读出的数据
9 n, z( O, o S9 Q7 s1 v! ^/ q - *备 注:
5 T1 D+ G& _( u5 i* A - **************************************************************/ # K1 q5 H& w! _+ j, s
- uint8_t E2promReadByte( unsigned short int addr ) 7 s; P1 @7 g+ o7 X
- { 9 }) l; s q/ n0 y1 G3 ?
- unsigned char ReadValue; $ j3 d7 \0 ^* t' \
- 5 K$ g! l! R3 f# u
- I2CStart();
8 o e6 P( U/ d/ z l; I9 q7 b
0 b, r' s/ p. X( v) K% [- I2CWriteByte( E2PROM_CMD_WRITE );
) Z, x, ]! Y2 ?% f$ N/ J3 e - if( RESET == I2CSlaveAck() )
j2 ^! C8 K' E9 C/ i - { ) R! D) c% j, n# m6 x
- return RESET; * `) ~. Q" S; p S i G/ _
- }/*
8 X6 h9 i5 h; D7 f0 s s; W - I2CWriteByte( (addr >> 8) & 0xFF ); 6 T1 ^! R$ I( H0 ?3 g' `
- if( RESET == I2CSlaveAck() ) , y6 _, A& V. A X: u4 x
- {
- ]8 z* T8 S8 o2 z - return RESET;
; l1 ]4 f$ \! @" Q% C - } */
% Z7 Z7 V! b2 l4 Q- \4 n" w - I2CWriteByte( addr & 0xFF ); . a( P$ Q, |/ n. L% C. [
- if( RESET == I2CSlaveAck() )
, j$ l+ r& H7 e0 ]1 Y1 }" | - {
7 ? h' ~# ~6 g - return RESET;
+ R! L2 _) d7 t* e: |4 h& J6 g6 I - }
2 a! I9 g6 d3 j, G0 B( E - I2CStart();
1 i. \, G0 ]( x9 G3 n$ a - I2CWriteByte( E2PROM_CMD_READ );
) i' \; q$ a( e7 Z* I8 I. O - if( RESET == I2CSlaveAck() )
. [- N7 e5 b8 s0 Y" S( P - { - \3 l! M. X& X. B. o3 J: e/ U/ ?
- return RESET;
. V4 |) L+ w& f3 t$ V$ W - }
+ j+ K, _7 m5 B - ReadValue = I2CReadByte(); + z7 W; Q/ m* E) ~% w% n
- I2CStop(); 0 D; |! ~ h# ?
- , V9 a( Z/ A; F) Y
- return ReadValue; 3 j+ {0 s, O7 ]4 H1 I1 G8 j/ N
- }
复制代码
4 O0 F0 [! ~4 q, b1 f
- m7 E) S) u1 }5 R |
41.*函数名称:I2CStop % E B+ t8 Q1 B. i6 f, k5 H% H1 t
% i/ X7 p/ N+ x2 p! `% O! k
42.*函数功能:I2C停止信号 " m7 W5 q/ f& ^! p: M
1 l! A" G8 {" z7 g# S/ |! \% O
43.*输入参数: 1 P4 \5 I' @% T* k
5 r- i# x1 j, f4 q0 `
44.*输出参数: # e* v( m* B m+ z2 w2 z
45.*备 注:时钟线高时,数据线由低到高的跳变,表示I2C停止信号 5 N7 W6 v% K# ?+ ~& m8 t
' R8 w5 d+ q$ Z
46.**************************************************************/ . W2 p9 e. T( N8 i2 d! e, R5 J
) D! o/ `1 v+ M
47.void I2CStop( void ) , z+ ~( J7 o" s% s e: I
! V$ Y( h+ {; I
48.{
& V7 |, X( m8 A$ I1 ^
49. GPIO_ResetBits( GPIOB, E2PROM_SDA ); 7 n6 r1 E% x; @
50. DelayMs(1);
) P* g& l- u+ {) ?, O+ v
51. GPIO_SetBits( GPIOB, E2PROM_SCL ); ' T- }! f- |2 j
52. DelayMs(1); 8 H& e' p6 `; O( y
9 v) h( A c! W
53. GPIO_SetBits( GPIOB, E2PROM_SDA );
54. DelayMs(1);
. u% ]: O! m+ V" _) l
55.' L9 q3 R/ G4 l7 n4 _1 f
///这句不要56. GPIO_ResetBits( GPIOB, E2PROM_SCL ); 8 A" c1 y/ G( I4 k; }7 g: [8 @" f' v
" t, H% w% f: N) r* P: `
57.} / D, o1 a7 _7 X* o
1 w8 O: z/ h- A+ d$ Z1 C
嗯,十分感谢。。。
以后还是得和大家多交流,不能闭门造车,我那个硬件I2C自己吭哧吭哧搞了半个多月,也没结果
F4上的可用?
为什么我的就死活调试不通呢,从器件无法响应?
4 t! A0 [4 W0 N( P$ K4 F
嗯,分享下经验
我们不能屈从权威
额,我一个4系列的也用的是模拟I2C,硬件的死活不通,记得有人给我说过是有问题,可是我的就是硬硬的不通,怎么破
每个人对资料的理解不通,你理解估计有极限
确实,所以还得仔细揣摩下,到底哪儿出问题了
嗯,多多交流
我是在加ST币的