I2C配置顺序引发的异常案例
& W4 I+ N- g* a1 k# ?1 W
1 L( |" H; Y# e, D基于stm32的I2C总线通讯简介及使用操作(附代码)
3 D k% R9 p ]- k# I9 ]- N: _& A& \8 \2 ~( n
分享关于STM32f103 的硬件IIC I2C 调试心得
# l( P; g/ X+ p5 g0 h' q e' e0 q, _+ t
; Y* T6 D) F( V" m
楼主前段时间苦调UV传感器,无奈硬件I2C怎么也用不起来,楼主水平还是太弱,无奈只好转入软件模拟I2C,不过话说模拟I2C的波形似乎要比硬件I2C的要好很多呢。调好的代码与大家分享下。。。源模板是哥们做好的读取E2的代码。
0 V' f6 {8 e7 ~/ p- #include "stm32f10x.h"
8 `; _) g; H% x! L - //=============================================================================== 5 _5 L" T8 F5 L3 w
- //GPIO 模拟I2C ,操作EP2ROM IC(AT24C02) : H! F0 l4 Q' b5 G
- #define E2PROM_SDA GPIO_Pin_77 x. x+ ?$ W8 w# e
- #define E2PROM_SCL GPIO_Pin_6) b) W$ _# D4 \- B5 V* X# V
- #define E2PROM_CMD_WRITE 0xa0
* W8 R6 ^! t" s6 f) L# O5 w8 ` - #define E2PROM_CMD_READ 0xa1
0 X( p$ E1 d n4 k7 o+ H- y7 I. Y9 z - #define I2C_DELAY 254 //
2 O& @$ }. t( N8 t" J: {
; @% {, H& H: H: P( l$ o8 _. v6 W2 H- I2C延时
9 E; t+ T0 [! z3 P9 z3 e7 \7 Q2 o - 5 X- Z1 A9 d$ T; f/ T0 E- b7 |
- static void
/ t) y4 B$ L0 v, y6 a! R3 h* i - DelayMs(uint8_t uc) H: z! y$ ^' z+ }/ K+ A
- {
; V! ]# K. D6 i( d( ^ - uint8_t i, j;, V# O' g, _2 \+ X2 ~1 a" s
- 3 a" M8 \8 C( \; p5 W0 L, J
- for (i=0; i<uc; i++) {
# Z1 L1 p" U6 R; }. t3 o9 h& C) d - for (j=0; j<I2C_DELAY; j++);
' a U0 y0 I7 R5 k h, F - }- u' v* ~0 O% B2 d
- }
) @5 ~5 k, p/ v% C+ W+ X& o - /************************************************************* + E. ^1 c9 f! O* r
- *函数名称:I2CStart
5 }+ v- v2 X; S9 O: w. k& N - *函数功能:I2C开始信号
' Y" R6 ]9 C1 Q- c0 W) `- S4 | - *输入参数: * e; Q( A) j# O! m% [- ^
- *输出参数: & l' ^3 H2 i3 { q M7 h: d
- *备 注:时钟线高时,数据线由高到低的跳变,表示I2C开始信号 ! j3 J0 i3 @9 |: W$ G
- **************************************************************/
. z1 S6 Z0 ~- Z& A - void I2CStart( void ) * a5 J# F0 x9 P0 A3 H O
- {
v, [) M# S/ |& F1 e# B ~ - GPIO_SetBits( GPIOB, E2PROM_SDA ); $ A1 p+ p- c4 e& W
- DelayMs(1);
9 U( h% C! }! i/ K0 ?% D - GPIO_SetBits( GPIOB, E2PROM_SCL ); & \2 I0 x1 V1 C# M u6 B. P
- DelayMs(1); W; w' \0 r U! H8 v
- GPIO_ResetBits( GPIOB, E2PROM_SDA ); + I7 ^! ?' ~7 F1 J
- DelayMs(1); 4 }4 m; W6 w v/ T* W$ s
- ) f* A0 Q/ z4 P+ m( q& r
- GPIO_ResetBits( GPIOB, E2PROM_SCL ); " W1 s' d7 [( @ g9 Z. A
- } ' }2 e: y: s+ k3 w# D3 q9 L
6 Z) M0 B( W! N- /*************************************************************
# e! T7 h0 r7 J/ x - *函数名称:I2CStop ; q; ^% I. f7 v: [. ~$ D8 e, n
- *函数功能:I2C停止信号 4 ^' A' {$ ^, O* |
- *输入参数: 9 t2 P' y/ e4 }7 J1 J' W# P
- *输出参数:
$ u; W# e# V1 K, S/ U7 d - *备 注:时钟线高时,数据线由低到高的跳变,表示I2C停止信号 7 H) h% d! n8 Y8 X# T
- **************************************************************/
7 H$ S$ u/ P. N i2 x8 \ - void I2CStop( void ) 7 K1 ~+ r. K) P( m9 ?# }+ `& l
- {
0 R! U6 j3 [6 E q) |4 p - GPIO_ResetBits( GPIOB, E2PROM_SDA ); 8 n0 J/ S% c9 o3 ` l& F" g' B
- DelayMs(1);
, o. s+ t) h) E8 q5 O* l - GPIO_SetBits( GPIOB, E2PROM_SCL ); ; E0 [" D" v9 ~, J- t$ y# {/ u$ M
- DelayMs(1);
$ f8 {/ [) U5 L- c3 B- E* @1 F - GPIO_SetBits( GPIOB, E2PROM_SDA ); & K T' v. @4 _: K, o
- DelayMs(1);
# `, b# l# U5 X" u2 |
1 u' \# }' H) Z8 x0 d _- GPIO_ResetBits( GPIOB, E2PROM_SCL );
4 H+ ]# y" j' g. X - }
, S: C( q, S& K# Q/ A c; Q, c. O - : P$ }+ _0 @/ q# E3 [! N
- /************************************************************* 3 B8 C0 y" a/ C6 k" w
- *函数名称:I2CSlaveAck + L$ z3 Z0 h' k9 R( y
- *函数功能:I2C从机设备应答查询 6 B' ]$ c5 Z. e ]$ ^8 k6 }
- *输入参数: : E" V5 [6 ?) T3 `7 B- O5 P
- *输出参数:
) p8 ~) I$ V. B - *备 注:
1 m5 w: S- _$ }, a, k% d - **************************************************************/
! i3 Q! o1 x Z9 x @0 R - unsigned char I2CSlaveAck( void )
9 k2 @3 M. }2 u ]. i - {
1 ]& U4 u) Z' Y/ I - GPIO_InitTypeDef GPIO_InitStruct; 1 `) ~+ u5 U% _7 |
- unsigned int TimeOut;
9 I) `) W, C* y# Z - unsigned char RetValue;
) M& S; t5 s1 |' c0 i
& i0 p8 w7 s+ [- ~: i. G- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; /*这里一定要设成输入上拉,否则不能读出数据*/ 8 [0 S. F; [9 ?7 z
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; $ z1 C6 R7 b/ b: S7 `
- GPIO_InitStruct.GPIO_Pin = E2PROM_SDA;
p9 b3 ^2 A5 ?5 w6 J% e - GPIO_Init( GPIOB, &GPIO_InitStruct );
3 B) I! d/ w% _. n* g- d - - B9 j$ z; I" T/ n6 Y8 d2 v+ I* A
- GPIO_SetBits( GPIOB, E2PROM_SCL ); ; Z5 q, Z6 F; b7 d
- TimeOut = 10000; # w* @& X+ R3 @
- while( TimeOut-- > 0 ) , ^& R1 ` S/ X' f& ]* v" C" y
- { % A ?& A$ i/ }. U
- if( SET == GPIO_ReadInputDataBit( GPIOB, E2PROM_SDA ) )
' Y' j( O7 ?& b! X! o( h# B - {
, A$ _, z: d" G6 J. q - RetValue = RESET; ) [8 s" A3 Y4 T; z! v. |3 n K" z- Z8 y$ V
- break; + y. O2 f2 h% D6 p
- } # O' q' V: s! ~$ I
- else 0 j; ?, T# s/ r* K/ K/ }
- {
0 g8 c \: `- o# Y- v% g! C* a - RetValue = SET;
8 `( v( G1 W+ Y0 z" @2 I4 l - } / G3 y2 F0 L& M H' W& [; i( f& y
- }
% q( v+ `3 F+ r# [! T4 N - GPIO_ResetBits( GPIOB, E2PROM_SCL );
, u+ r& H& \$ J5 l -
$ o: h9 O1 k' M - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; , U; @1 G' q- b7 o* k9 ]9 M) v& X. ^
- GPIO_Init( GPIOB, &GPIO_InitStruct );
; D1 W8 [8 E9 [) H; R6 I) \/ V - return RetValue; " l" O" t- ]% t8 V9 J0 d2 M" J
- }
+ n ?; D0 ]7 {+ N - & ]: E3 u; \. ^ o: R
- /*************************************************************
, _7 ]% i6 L$ V8 [5 _ - *函数名称:I2CWriteByte
2 ~- s" D2 @: Y" Q- f - *函数功能:I2C写一字节数据 " | g6 T4 D l
- *输入参数: - X& _: Q" w) M7 t
- *输出参数:
9 j: m1 }$ \5 {9 ] \" S# T - *备 注: - R+ s8 v. u! k6 z
- **************************************************************/
- K8 Y' {( C5 Z- _. T4 G: n - void I2CWriteByte( unsigned char byte )
+ L% V3 t' u3 s% N$ |# g5 y7 y7 A - { $ d6 G; Z- H `% g h
- unsigned char i;
7 J6 z& ]2 q! M) [& @$ c
, l* [6 H# L0 A6 b# F* Z% o9 p- for( i=0; i<8; i++ ) 2 r# H' i" Z) S( f( w
- { ( ]# {. Y4 p' `5 Y& {
- if( 0X80 & byte ) 7 ` f! \$ ?$ z3 D8 ~
- GPIO_SetBits( GPIOB, E2PROM_SDA );
+ n6 y! q& \9 R j! N) F7 z. ]4 w - else 6 D( ]2 b& k/ U& u
- GPIO_ResetBits( GPIOB, E2PROM_SDA );
) B# U+ h6 r5 B- w4 _- I% V - byte <<= 1; $ T$ _+ {1 |* v+ J1 a" ~3 @: q
- DelayMs(1);
% M9 ? ?& w' ^1 o( J& ?
6 \! v' i* |2 |4 d% y5 f1 Z- GPIO_SetBits( GPIOB, E2PROM_SCL );
$ n$ b ? @( P4 e" n - DelayMs(1); 4 f7 v% c3 b% Q! l4 j
- GPIO_ResetBits( GPIOB, E2PROM_SCL );
: M: L3 e# S' d- } - DelayMs(1); 1 F5 `9 y9 }# p i9 D9 K" l
- } 9 j% t& L) h6 b4 c2 o6 t. b
- }
3 \5 K" d5 [/ y5 y4 l3 f8 y - ' T# n4 y$ [2 [/ Q5 t$ Z
- /*************************************************************
$ s# w8 Q! c& M- m0 Z - *函数名称:I2CReadByte : J- C9 e" B& A
- *函数功能:I2C读一字节数据
U/ m7 @ r4 R& V3 | `8 | - *输入参数:
1 ]6 Z* @3 E: j - *输出参数: & ^! x8 F& ]3 b
- *备 注:
7 X6 x2 [$ w9 s: h% } - **************************************************************/ * A1 z7 O- j7 H
- unsigned char I2CReadByte( void )
}- k* R8 y5 d - {
( B2 V- R# I7 p7 }6 |% W1 f% B" C$ K - unsigned char i;
' e' V# Y* l4 @$ a* B - unsigned char ReadValue = 0; 9 c- T% H9 m }) ]/ P( |+ Z& w
- GPIO_InitTypeDef GPIO_InitStruct; & Y8 }8 m$ o/ c! r+ Q; Q$ K
- unsigned char bit;
; b/ e- F$ o Q$ h4 w0 e w
6 \- H* z+ H q0 ]- |6 ~- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; /*这里一定要设成输入上拉,否则不能读出数据*/ ! J7 g9 D0 a* O5 G5 ^ ?: `
- GPIO_InitStruct.GPIO_Pin = E2PROM_SDA;
1 {8 Q% i' `: ]$ _1 ]5 Z8 V2 h/ r% v - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; 0 L$ y' S$ g% y: ~
- GPIO_Init( GPIOB, &GPIO_InitStruct );
6 k- E0 Q4 C' E6 j+ A - for( i=0; i<8; i++ )
4 M) g2 u) A; \1 U" g - {
; `4 K# i5 D0 c' E8 q9 H9 R - GPIO_SetBits( GPIOB, E2PROM_SCL ); y- ]" h4 s1 g4 o: N# ^ I, t
- DelayMs(1);
; Y/ Z( r# D6 F' |! v Y& ^ - if( SET == GPIO_ReadInputDataBit( GPIOB, E2PROM_SDA ) )
, P; h% x# C* E4 [* b - bit = 0X01;
6 c2 a5 d$ J8 B$ Q, E4 O - else
! f+ m4 \* L& ^* ]* K" ~ - bit = 0x00; - B# X. [& V+ l' k3 w8 J6 R
-
$ t: g9 X8 }- {# P9 e5 o7 h - ReadValue = (ReadValue<<1)|bit;
6 c# o- _9 u+ n - GPIO_ResetBits( GPIOB, E2PROM_SCL );
0 V4 i$ e& y8 v3 A0 r& S r$ D - DelayMs(1);
4 M- Z( \7 d- s( o9 ?% x: T - } / i: z) }: K7 I v: J* X5 t: k7 p" D
' x3 C. W$ L. C. \4 r- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; 1 O5 y1 `* _+ R% d
- GPIO_Init( GPIOB, &GPIO_InitStruct ); 5 F* E' K( F% ]
- return ReadValue;
. Q9 y. W J- F - }
2 b4 Q* P: L' x6 y: T6 `3 | - ) C; C/ b+ f% |: e v, v1 ?. V
- /************************************************************* , g3 a: I' c4 ~3 K. ] n3 `
- *函数名称:E2promWriteByte 8 u2 @) F& ]; R6 z! \
- *函数功能:E2PROM指定地址写一字节数据 . j7 ^. x$ a& e! G3 O
- *输入参数:addr E2PROM地址 3 y& {' k* l, _ M. x; Z# G9 L
- data 写入的数据
0 n; N4 C9 d9 o) a1 K% ^ - *输出参数:SET: 写入正常;RESET:写入错误 - ?7 H8 T- T" v& l0 v8 U, S2 J8 {
- *备 注: / ]3 p& P9 E2 n3 ]+ G; ]% J
- **************************************************************/ + L4 U3 K2 w( J
- uint8_t E2promWriteByte( uint16_t addr, uint8_t data ) ! F! b9 _0 M) p& Y
- {
, W/ u! U, _# E9 |3 y7 { - //asm("CPSID I"); //关中断
& ^: w: U2 b& f# Q9 L - I2CStart();
% L x0 E( ?% n" X! L( w
4 r, O V0 f1 v1 _* J. p- I2CWriteByte( E2PROM_CMD_WRITE );
- D0 {) E- O: \1 M* s - if( RESET == I2CSlaveAck() ) ' D/ Z1 J" h3 f2 o: S# m, r1 \+ ~2 d
- { ) k+ l' C$ S" u2 N# l* V
- return RESET;
. o& h C% k9 c* ?: M - }/*
d) q( Z4 u+ c0 U0 h$ Q X; A - I2CWriteByte( (addr >> 8) & 0xFF ); { {3 z5 B% o' l0 Y/ h
- if( RESET == I2CSlaveAck() )
8 L; X# h% O4 C+ D7 r" T9 j { - {
2 R: m" [" |2 X2 A! a/ `' z' r - return RESET; - ~( ?# }8 x D7 A5 W2 _. F* G. ^, b
- } */7 X2 @% _7 Y% J' _8 V
- I2CWriteByte( addr & 0xFF); * M7 @, X# }$ p
- if( RESET == I2CSlaveAck() ) $ u6 v1 i6 o1 o r
- { $ `5 A k6 q: j3 H. j Y8 N, `/ ~
- return RESET; 3 |: j6 I- J4 R- |3 o
- }
2 ]% `! u, `# |7 U) K4 }' c/ O - I2CWriteByte( data );
- d9 R# J. K# Q8 M% a* A- R( p3 M - if( RESET == I2CSlaveAck() )
$ a% _& ~; C3 W; X/ c* T; x - { 1 L, P7 [3 n, P$ ^' {( q h
- return RESET;
8 g- c2 ~( d$ m; J7 O - } " e8 L% X' ~: c1 m- o
- I2CStop();
& }9 `, i' K1 T# F/ y( g - //asm("CPSIE I"); //关中断
/ v4 D# k0 w4 N m3 [$ d - 8 @4 b& y& H, `
- return SET;
) g+ `3 b6 D! p - } 1 @) J: j/ o3 g; b) V
& r2 j7 _4 y i/ Y; Q- /************************************************************* 7 C/ U. L* g& b2 k
- *函数名称:E2promReadByte
1 \6 t, F- A: ~( P( x$ `7 w - *函数功能:E2PROM指定地址读一字节数据
$ `1 G$ p; K& i6 T; Q2 T - *输入参数:addr E2PROM地址 M4 ?' n7 Z# Y
- *输出参数:返回读出的数据 " Q. G$ t; s! b1 {6 ~
- *备 注: 2 S7 j' @0 P3 [1 [3 o6 a, t8 y
- **************************************************************/
8 ?! |( l" j6 A2 p - uint8_t E2promReadByte( unsigned short int addr )
4 V& e% s) ]) m - {
- N1 c* ]/ r* i - unsigned char ReadValue; 2 I/ |8 x8 @5 h" U
* y) k+ J5 e! H1 O- I2CStart();
& x; C2 `% e: S' d6 _3 @" [2 n* R
" t2 j ?" |6 n2 ~& F- I2CWriteByte( E2PROM_CMD_WRITE ); . s' r4 i# B9 N- B# d# n
- if( RESET == I2CSlaveAck() )
- s$ x! V5 o6 Y4 ^6 ]. o - { 3 j3 u9 q" a1 I! g7 O5 q/ {. x2 D
- return RESET;
7 c" |- m# K, k/ { - }/*, J/ V. \# x9 E9 Y1 b& P1 L
- I2CWriteByte( (addr >> 8) & 0xFF ); 4 Q" x) f/ T y
- if( RESET == I2CSlaveAck() )
]% }& ?5 [. C0 }9 I, n4 B' I - { * s: L0 Q! N/ W
- return RESET;
. C+ z3 c h' r4 l - } */0 c* X L7 w+ _" {% C. d, h
- I2CWriteByte( addr & 0xFF );
9 Z9 R/ x8 x& R! Z8 ?$ j0 i - if( RESET == I2CSlaveAck() ) ' r1 K: I6 [: N$ v8 V M
- {
% {( z% w, I! k. [ - return RESET;
* o! M' z2 `. G- o3 B - } % H( }5 K, o8 A. }6 I# ^
- I2CStart(); % t$ D" P" j3 o @
- I2CWriteByte( E2PROM_CMD_READ );
5 I* t8 B' {7 [, ] - if( RESET == I2CSlaveAck() ) ( A6 A& t. U. h4 L
- { ! f0 F- I& N" I" H. E. D" _1 G
- return RESET; 8 z0 a. ^) Z e2 v; J5 J
- } , ~! c$ A7 p: @( K \
- ReadValue = I2CReadByte(); 3 |3 k" @( a' |
- I2CStop(); ; b1 j2 V# b5 J& D. P8 q# V5 d
- , y5 N/ j4 I& m S! M
- return ReadValue; ! I: r- f% O9 Y( p) w4 Z/ D; N
- }
复制代码
' H* d- I# @& ?, @0 S# D, O6 G; F- O h" r8 P3 Y
|
41.*函数名称:I2CStop
) e8 |% \1 |1 _2 i$ R
42.*函数功能:I2C停止信号 : ?' |5 `3 ~3 }, x
& m3 G3 K/ p' _2 B
43.*输入参数:
44.*输出参数: # G+ M" P; v- w6 `+ z
45.*备 注:时钟线高时,数据线由低到高的跳变,表示I2C停止信号 { [1 k4 X9 H
46.**************************************************************/
47.void I2CStop( void ) ) o. }0 G$ V" L1 z9 t" `
4 g' m, `' {* ~. C; k2 m
48.{ ! O9 r. ^0 B4 {+ B; ^7 Q
49. GPIO_ResetBits( GPIOB, E2PROM_SDA );
50. DelayMs(1); 4 u2 J' P# h# Z! h8 o
51. GPIO_SetBits( GPIOB, E2PROM_SCL ); , q' n+ r) }# C) D( d
* M* V+ N$ C. ~2 ?
52. DelayMs(1); 9 J1 S- s" {& F7 b* k. T3 G
53. GPIO_SetBits( GPIOB, E2PROM_SDA ); 0 T. ?/ ?0 |% w$ I
54. DelayMs(1);
55.: I: B: G/ o! ^
///这句不要56. GPIO_ResetBits( GPIOB, E2PROM_SCL );
' o5 T, {6 g l- w& o. |
57.}
嗯,十分感谢。。。
以后还是得和大家多交流,不能闭门造车,我那个硬件I2C自己吭哧吭哧搞了半个多月,也没结果
F4上的可用?/ [+ W6 c- U% q0 [3 L- k9 J- n) i
为什么我的就死活调试不通呢,从器件无法响应?
嗯,分享下经验2 b& Z* [3 Z) e# l/ W
我们不能屈从权威
额,我一个4系列的也用的是模拟I2C,硬件的死活不通,记得有人给我说过是有问题,可是我的就是硬硬的不通,怎么破
每个人对资料的理解不通,你理解估计有极限
确实,所以还得仔细揣摩下,到底哪儿出问题了
嗯,多多交流
我是在加ST币的