最近一段时间在做I2C通信协议,需要在两块STM32之间做I2C通信,定的是主机用IO口模拟,从机用的是STM32的硬件I2C,我的项目要求是需要主从机之间能够进行一串数据收发而不出错,实验时在主机方面,利用IO口模拟主机,只需要理解时序就够了,同时将速度能够控制在100K(标准)左右,基本的时序理解网上大把的资料,所以主机这一块几个小时就搞定了,而在做从机时,遇到了困难,本来从机也想用IO口模拟的,但是速度达不到那么快,因此只能选择硬件做从机,现就从机用中断方式开说,总结过程中遇到的几点问题: 1、由于STM32的硬件问题,建议在使用I2C时,将其优先级设为最高。 2、针对程序中除了I2C数据收发,还有别的中断程序或者指令要执行而导致I2C数据传输堵塞时,可以在执行完该段程序后重新初始化I2C。 主机程序如下: - #include "Hal_IIC/I2C.h"
( |. ?3 x! e& Y Q+ b - #include "Hal_delay/delay.h"( _6 z; d2 X6 c- K( m' ]7 o& V( }
- #include "common.h"! p# l' F0 N0 n" H# L2 }* H5 x
- #include "gizwits_product.h"
5 _+ Y! G: v6 M+ N' f
3 F4 G! E2 y e& ]! h! i5 k6 y- extern void delayUs(uint32_t nus);
; |$ Q+ Z" l+ ?4 @$ z# G - uint8_t b[5];
$ Q6 f/ b) R( ~ - extern uint8_t Cookr[5];
8 I: o- Z F3 p i. _ - extern uint8_t WR_flag;& N# ?$ f6 a* P* d3 O. @/ K( ]- p; z, V
- uint8_t Wifi_SET; //WIFI状态脚
7 S% S+ D' c9 f1 X! |& z - extern uint8_t Power_flag; //电磁炉开启关闭标志位
% S) R- s' ^ B0 ?5 x0 U, `- h - uint8_t Give_Up;2 F4 M0 S/ Q- q* l2 b* d
- /*--------------------------------------------------------------------------------
( X. g- n/ e! k% X - 调用方式:void IIC_Init(void)
. X% I/ o Q# l: { - 函数说明:私有函数,I2C专用,函数初始化, Y6 C& N* p. E) _
- ---------------------------------------------------------------------------------*/0 b9 N* l# O5 K! `! l% G
- void IIC_Init(void)1 ]9 S2 z" N5 R8 i
- {1 l& }, U9 s9 R! A0 P( b
- GPIO_InitTypeDef GPIO_InitStructure;+ O+ j- Z% g; C7 O) _
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); //使能GPIOA时钟- T1 O0 _* ~$ s8 d; F) e6 g9 X, S
! [/ @/ U* Y+ U' J# m' o- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;6 }" E1 T* h6 g- r8 i5 m
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出( p- e3 U4 C+ g1 z0 T6 I; D# z
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;* S, n8 m$ E0 U, F; ?* O, }
- GPIO_Init(GPIOA, &GPIO_InitStructure);
, Y" X/ [$ J" M- f - GPIO_SetBits(GPIOA,GPIO_Pin_11|GPIO_Pin_12); //PA11,PA12 输出高# N. W: w) M7 S0 }' U0 v+ Q
- }) s- m0 K6 I8 Q* h4 G( i$ C3 D
- /*--------------------------------------------------------------------------------
( h, [2 A1 C2 m - 调用方式:void I2CStart(void)
/ W" g( o& K" J3 Q1 a$ z - 函数说明:私有函数,I2C专用,开始信号: J9 u7 J- l5 W$ ^
- ---------------------------------------------------------------------------------*/
9 r9 r8 n- ~- n2 d - void IIC_Start(void)5 o( [1 g( s$ P1 A: \
- {; K" f# x5 u9 x' X+ X- m" j
- SDA_OUT(); //sda线输出
$ l9 ^6 Y4 E G! t" C4 r - IIC_SDA=1;
: Q6 p h% k+ L# y) I F" o - IIC_SCL=1;+ x' ^! @) T! A% ^
- delayUs(4);! o% ?0 U8 j5 u% t
- IIC_SDA=0;//START:when CLK is high,DATA change form high to low5 k, k6 R( m6 R! V
- delayUs(4);3 v# @( Y: O6 R6 F" G c
- IIC_SCL=0; //钳住I2C总线,准备发送或接收数据
1 A1 p5 q4 _0 h C$ Y" S0 S - }
- |; Z8 _* C. N - /*--------------------------------------------------------------------------------7 @9 n. | p: T+ S2 c# q
- 调用方式:void I2CStop(void)
* k! J+ a3 \' F - 函数说明:私有函数,I2C专用,停止信号1 x# g D! Z2 N2 A( {! y
- ---------------------------------------------------------------------------------*/
2 T6 |7 M. s: B+ J: S: I# v O - void IIC_Stop(void)6 S6 P# r7 O) d2 A; A0 H
- {3 k) e( a) r' P" b7 f' n
- SDA_OUT();//sda线输出
6 w& z4 O- g% U+ R J - IIC_SCL=0;
- j7 ?0 B. Y, [6 K3 O2 X# W - IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
8 T4 K# n+ ~: R* T - delayUs(4);/ v. {& Z% t: I. v. o$ p
- IIC_SCL=1;
1 b2 o" f! h8 Q6 ? ?4 i6 q - IIC_SDA=1;//发送I2C总线结束信号& j5 |8 _6 m$ ^/ F
- delayUs(4);8 E: B" p. W2 S! ^4 s
- }
) H. p5 u6 |* H. P' H+ O* _ - /*--------------------------------------------------------------------------------" Y' b: n' G, u: `4 g! J# \* \
- 调用方式:I2CAck(void)! J' D- {! {1 o+ p3 l b" v* [: S
- 函数说明:私有函数,I2C专用,等待从器件接收方的应答,0表示接受成功,1表示失败
& ]9 h" D) L* }8 ~7 r% l; n - ---------------------------------------------------------------------------------*/2 U. {6 f% x. K R0 ?+ M: y9 G
- uint8_t IIC_Wait_Ack(void)4 i8 ~; @6 y. n2 I! v/ k7 B2 @
- {
: L9 k3 `1 e I( i - uint8_t ucErrTime=0;
1 X4 ?( M, o4 t/ u6 r# i - SDA_IN(); //SDA设置为输入
0 N, [5 W6 {# ]4 K- T1 g - IIC_SDA=1;delayUs(1);
+ ~ y# j2 q$ [3 w; M, J - IIC_SCL=1;delayUs(1);
- p$ u0 I; r4 U2 _/ B1 A6 ~$ k - while(READ_SDA)0 p q. U* u' T; E" e" \" b
- {
7 h4 @ B4 p8 L; C+ F3 z& S& p6 w - ucErrTime++;
6 F P6 E% x) Y1 c5 C - if(ucErrTime>250)
7 A/ B6 l9 q9 Q - {
! n- @9 K3 l) x6 f) h - IIC_Stop();9 X2 p d5 O" `* L4 m, j, @
- return 1;
. k( z6 y6 N- Z \ - }
* b1 w, z; _ B! Z# J7 z% `0 ` - }
# W ]. b8 d1 ?; J) m - IIC_SCL=0;//时钟输出0
w# C$ y1 y; E8 S: m - return 0;
) D- X* y4 G# Z T7 C2 g- k$ B - }- u. t5 u0 {' _/ Q1 Q+ ?7 f
- /*--------------------------------------------------------------------------------9 x2 V8 a5 j+ z
- 调用方式:void SendAck(void). G8 V* O# h# x% b* ]. ?
- 函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,应答信号。
3 G6 w( A- l# F* w- l% k - ---------------------------------------------------------------------------------*/8 c& f* G0 o! a8 N* k
- void IIC_Ack(void)
I) L# A: C7 c: P5 k" k! y - {
+ M; x5 v. Z1 {$ v! ] - IIC_SCL=0;
0 V7 z. x# r& ]4 m' | - SDA_OUT();
/ C" w7 m0 T0 p9 V* i- [ - IIC_SDA=0;0 |( j) {; V, q$ }$ }; l: W4 ^
- delayUs(2);3 p2 V( q$ B. B8 y+ j
- IIC_SCL=1;
) n* M( v* [/ [# s; E. Q - delayUs(2);
; ~" V! H; C1 U6 Y - IIC_SCL=0;+ `$ o/ u$ H2 l ] P( C
- }
5 W1 w1 V) b7 Q8 G' O - /*--------------------------------------------------------------------------------) V$ b0 F9 \6 y B$ {
- 调用方式:void SendAck(void)7 ^ S3 s3 f! q( }7 X+ {7 K0 O, m9 V- s
- 函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,非应答信号。
3 P5 Z7 {, m/ T9 [4 G' ?% u9 g9 L - ---------------------------------------------------------------------------------*/9 H( z5 B* u" J& {9 r
- void IIC_NAck(void)
! P9 Q7 T) A% n3 z/ M/ @ - {
- t$ z1 O( d8 O, m9 d. }. | - IIC_SCL=0;# k0 S2 v# @5 @" Z
- SDA_OUT();! w) i( v: A- _2 p% {( P! ^( X5 @
- IIC_SDA=1;7 v* u/ {* w9 v$ Y7 H3 o7 D
- delayUs(2);, O1 N3 F3 X/ w: S; u
- IIC_SCL=1;
: F/ a9 F; F1 {4 z5 s/ x4 P - delayUs(2);
2 b2 M; J* r: ~+ v$ M, h1 I - IIC_SCL=0;, S$ c: B, U; R0 c
- }
% W* w8 D A% o" b5 Y+ ]" S1 K# Q - /*--------------------------------------------------------------------------------
4 R) w3 Y: T0 F% F - 调用方式:void IIC_Send_Byte(unsigned char ch)
5 K; ~- W0 Q3 M# J$ B - 函数说明:私有函数,I2C专用
9 E* n& C9 ~. A$ V7 z; S - ---------------------------------------------------------------------------------*/
: l- G& G9 f7 z( j/ N - void IIC_Send_Byte(uint8_t txd)
6 ]. U7 ]; [- O0 `# G - {
) b8 W. ]) h- z, L* e+ f - uint8_t t;
% ^+ h- k1 z4 C0 I1 s - SDA_OUT();* w2 N/ U* v" V+ V1 Y
- IIC_SCL=0;//拉低时钟开始数据传输( e7 N9 W9 x0 I% g) P' l/ u. U2 o
- for(t=0;t<8;t++)0 [1 ^; T8 {- E5 c+ }- u5 C
- {5 C2 ?$ \5 S. |$ j. T
- //IIC_SDA=(txd&0x80)>>7;( X0 }: Q- p C- O
- if((txd&0x80)>>7)+ a' m4 C# x( [8 p
- IIC_SDA=1;
W/ I+ {1 k7 |2 L' o - else
; U: H+ Y5 E* K3 `! r5 Y! \ - IIC_SDA=0;3 k* E2 C- w$ E) Y+ v. A0 H2 k4 t
- txd<<=1;
7 i4 Z2 W0 r* x. `9 ~! Q - delayUs(2); //对TEA5767这三个延时都是必须的( Z* O2 v) a7 S, ~0 j
- IIC_SCL=1;
$ @- M5 J& X" N( h( [' P8 [ - delayUs(2);
6 ]. J7 W# a Y& X+ I - IIC_SCL=0;
' J) v1 {& H0 V( O# T - delayUs(2);
0 D5 _( l" I7 H5 |; s) H - }" h+ _) ]( u- W! e( Q
- }
! i' d) m. ?$ o. A8 \* O ] - /*--------------------------------------------------------------------------------: I$ M7 c6 Z8 X$ j8 |' d
- 调用方式:unsigned char IIC_Read_Byte(void)) V. x' B* X, |. M+ e
- 函数说明:私有函数,I2C专用- b8 ?2 }0 Q4 W8 [# B
- ---------------------------------------------------------------------------------*/8 }% X, e2 x4 t8 o' m' k
- //读1个字节,ack=1时,发送ACK,ack=0,发送nACK
" }5 ]* n& j4 D2 [! F( \ - uint8_t IIC_Read_Byte(unsigned char ack)
1 h& O s$ a3 J4 k" ] - {) j' S6 K$ @; b" S
- unsigned char i,receive=0;3 Q$ t2 h, ^3 M$ R
- SDA_IN();//SDA设置为输入
" V# h J5 K0 q& S4 Z& E - for(i=0;i<8;i++ ), n# w0 M; D7 P4 v1 k' x. H
- {1 i. z& B/ l N$ u
- receive<<=1;; G" |( P/ r# d4 Z9 F
- IIC_SCL=0;# J# P* s e7 R! p) D9 a% L3 a
- delayUs(5);. p$ F% r" j+ q g9 a
- IIC_SCL=1;
0 c% q. V; D& q" Z" X! b/ I6 j( k - delayUs(5);
* g/ g9 [3 B p6 n - ! J/ q# |% S, ]8 N& L2 C# E
- if(READ_SDA)receive++;
* A5 K F/ H" U1 _- P0 J; s1 |
' \; Q- ^- D) q1 m- }
6 K9 B% ]4 J. ~& y6 X+ m - if (!ack)
- |- ?& |; K) u7 f - IIC_NAck();//发送nACK
6 H: Q& m% `: N+ B) G& T% E8 x - else/ E( T) i7 }' D2 e/ X$ a
- IIC_Ack(); //发送ACK
& X8 r D& K: ?$ w) j" d - return receive;9 T$ D* M% [) I0 E9 ^: Z" U: }# L
- }2 l3 ^. _7 A# I9 \
- : j9 u+ f+ \2 z- o) d
- M6 ~+ Z$ N7 k7 u" u8 z- //读温度传感器,温度值是由h的高字节和低字节的高四位组成,总共12位,其中负温度值是由补码形式
3 f; j! m; j9 c7 j9 X" C - void T_Read(void)! a; |/ G+ b, H, y) j% J
- {4 D' K& p. q: K4 m* P: Y
! v( C6 o8 ~7 N0 D) U4 [- /***************read start*******************/! [2 z& y# h% j
- if(WR_flag==0x02)
9 A! j* y2 _ L6 I - {$ u+ I/ L% j! H4 D6 f- ~/ C
- + B- B' T) ^9 T U/ W
- IIC_Start();
0 k$ g& R# q) R) p& H1 F, o# R - IIC_Send_Byte( 0x30|0x01); //读操作
, v/ W; x7 b: e3 \1 [- S, D5 n - while(IIC_Wait_Ack());& W7 ]' W: e" }1 D
- // delayMs(500); //等待从机处理一个字节地址位
o5 k8 b6 [! r - Give_Up = IIC_Read_Byte(1);
3 I' V3 _. e6 y7 F6 y$ I s/ C2 V - for(uint8_t i=0;i<4;i++)6 I+ k2 I9 Y) ]
- {
7 V& Z# }9 z6 p* Q - b[i] = IIC_Read_Byte(1);
" H! K$ D; }5 E4 g. h3 w - printf("%c",b[i]);6 @" W+ f2 w6 x* S6 ~, Q6 n7 V* G
- }) \5 g+ P3 L7 E0 L, o3 f
- b[4] = IIC_Read_Byte(0);
: c# H' |" V6 M1 t% X2 Z4 Z8 ~ - printf("%c",b[4]);; z; k+ j, V" \; i: c; d3 ^
- ) \8 v9 s& M5 I$ `9 o+ w. k! A1 E& U
- if((b[0]==0xFA)&&(b[4]==0xFB))# P9 x8 z$ N9 ^, \2 J3 S0 Q e
- {. O1 L4 A, i8 j9 t" |' b
- for(uint8_t i=1;i<6;i++)0 A; B$ U1 H! B- |2 M+ W$ |
- {
3 ^3 U+ c5 l+ e: c+ [8 ^( E% j& H - Cookr[i] = b[i];# v% V' Y( @/ {# Z
- }
0 i9 q/ Q* L7 x, D+ n4 y
+ `# S( k! Y# B! Z4 G' v5 g5 [- }
% f) C/ \1 H* n3 o+ u3 t! | - }
+ r: i8 ~0 d0 n) W1 f v8 ]
. y5 G2 C m" P, j- i7 O' H5 m- /****************read end********************/7 ~8 D" E3 ?' H7 D
- /****************write start*****************/7 l' n7 q" _% ^5 B1 ?
- if(WR_flag==0x01)
& Y) y; y. L7 Q: S* `. ?, n! o8 S) K - {
% |9 [/ v2 ~1 r; l9 q1 i+ {6 V3 _( I - IIC_Start();6 S3 z/ r% K6 M; _5 J$ |
- IIC_Send_Byte(0x30); //写操作, M, T7 Z: T3 j; B
- while(IIC_Wait_Ack());
9 e, T" V! Y8 V7 X r( A$ D# A - IIC_Send_Byte(0xFA);
6 X5 N2 C1 m) X. N1 A v% ?1 z - while(IIC_Wait_Ack());3 x; H' D( j6 {" g8 j
- delayMs(3); //延时太低传输数据会出错,因为从机还没处理完数据6 D$ e) n# O8 }6 f
- IIC_Send_Byte(Cookr[1]);
' A/ r' H1 l3 ~- o$ f7 b7 y - while(IIC_Wait_Ack());
* u9 Q- l7 a" S t5 X6 k - delayMs(3);
0 M! T; ^" E; U* |3 w( I - IIC_Send_Byte(0x03);9 ?* \5 b0 F5 Q0 ]7 h. S+ |
- while(IIC_Wait_Ack());; |7 [ b2 z" Y+ u8 |- {% [# v
- delayMs(3);0 h+ ]9 s& k R
- IIC_Send_Byte(Power_flag);
# \; a4 t/ z5 D - while(IIC_Wait_Ack());
* ~/ c8 p" S( A! c - delayMs(3);
J; H& n, D% A; i$ `7 \4 c% A+ y - IIC_Send_Byte(0xFB);: D; h; ~" R) h+ o
- while(IIC_Wait_Ack());
9 _9 R) ]$ Z L# [7 j$ L - delayMs(3);
5 L, c3 a' M/ z' d" |; L. @ - IIC_Stop();
- I3 H( j1 C0 R S x - WR_flag=0x02;
8 |% k; M! V4 T g9 u. t - }
2 y$ Q) S" U% n! x! `- } - /***************write end*****************/
$ s, y/ h# \. O0 i$ m
6 Y% P$ U; T8 r! a- }
复制代码从机使用中断方式 - #include "myiic.h"5 h) Z1 L4 M4 V$ n$ y# s8 o2 R
- #include "delay.h"
b. i0 H4 }, e) h - #include "led.h" Q9 s3 ~8 M% `
- #include "key.h"' t( m6 f9 a2 p7 i
- #include "usart.h"
4 x# @ j& ~) \2 G2 K
' ^8 Y# `$ j n4 [; V. J3 Y$ ^* r
2 n. f2 B! u9 s- f1 K- #define MY_I2C_ADDRESS 0x30 //模拟从机地址( e3 B0 R( ?# o' g
- unsigned char b[5]={0x00,0x00,0x00,0x00,0x00}; //从机接收操作
* e5 w. \# E* L p& D1 u - uint8_t Wifi_Set=0x00;
7 s8 |, F8 G" H( _5 F - extern u8 flag; //电磁炉开关中断位
7 j& U% w& ^& S9 d5 k: k - unsigned char a[5]={0xFA,0x00,0x00,0x00,0xFB};
$ v2 y, O7 E& E6 c& }- |. b0 h; Q - //初始化IIC
" I$ B5 q2 Z& F K. Q% h3 q - void I2C1_Init(void)/ S9 L. D" }; t! f
- {* j2 `9 \, G" A
- GPIO_InitTypeDef GPIO_InitStructure; a2 _ x1 t5 z% R) l& J
- I2C_InitTypeDef I2C_InitStructure;( a& m n9 y x
- NVIC_InitTypeDef NVIC_InitStructure;) t8 \0 K v& F, Y
- 6 _: B; X- l Y
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); // enable APB1 peripheral clock for I2C1" O$ m, U* D( k3 _+ B
- 0 {& s! \( p- V! m: L9 _+ t; s
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // enable clock for SCL and SDA pins
+ j8 ?% Q& l% F1 _/ n - ( k) s, J* D' \6 I t5 T
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;8 ^' c z) e" E
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
% M9 |" v4 M) s* k3 D - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //I2C必须开漏输出,实现线与逻辑
* i2 e7 a! {! m J' c, f0 T8 v$ J! r- \ - GPIO_Init(GPIOB, &GPIO_InitStructure);
4 T0 D. I# G- X5 r$ \ - H" T; n: ~# A d9 D
- - b% O* Z% g3 ^% z! M+ L! I! _
- I2C_InitStructure.I2C_ClockSpeed = 100000; // configure I2C1
% t# ]+ y n4 P# f1 d: F) \ - I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
: i5 D) { Z# z$ A - I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;, b* ^5 S! k6 Q/ f" o r. q8 \" A9 e
- I2C_InitStructure.I2C_OwnAddress1 = MY_I2C_ADDRESS;
" ?! d) F) x: p N# N( C - I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;2 q( [5 Z6 ]/ K( c2 {
- I2C_InitStructure.I2C_AcknowledgedAddress= I2C_AcknowledgedAddress_7bit;7 L8 z3 f# V+ I5 m, D( R
- I2C_Init(I2C1, &I2C_InitStructure);
. L7 `; w$ J" S4 U) t- J - W( W1 @6 b: y9 E2 m( s
- //setup interrupts
a$ K8 s. Z8 Q6 y8 P8 c2 p- @ - I2C_ITConfig(I2C1, I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF, ENABLE);+ X" q5 d4 w% u# s
9 J8 c# k- f) s( d1 G$ }0 n+ B8 s- 7 {+ ?# p# M$ H! w o0 S4 Q8 `
- // Configure the I2C event priority
! H2 U5 T" q+ z6 u - NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
5 H: R; h: i' ]5 [5 Y" q - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级1) z* o6 |: D# }4 S' k4 s. ]! P
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级0
2 C3 W9 G+ G7 D - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
6 a% T, W+ O. J+ R& p - NVIC_Init(&NVIC_InitStructure);! [, K- U% h: l9 e2 [# @/ ?9 {0 d
3 G5 R# v) B; c; K( y8 z, h- // enable I2C1! l7 r Z" n+ H u; [
- I2C_Cmd(I2C1, ENABLE);
% b0 Z0 u9 W) f) Z, A1 W+ W - }
" \4 Y0 o* R2 P0 I- z- s) Y3 I
) ~6 c2 l! {4 M9 m) _: N
$ i0 {2 ]+ C) @* J- //Clear ADDR by reading SR1, then SR2
+ B$ }1 }, Y# g/ \% \. i0 _& z4 t
$ v0 U; N4 P! V% ?; K" T- void I2C_clear_ADDR(I2C_TypeDef* I2Cx) {
+ ]# G- P9 N0 G2 g* A - I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR);! M& W4 H6 Q% Z# V' d" b
- ((void)(I2Cx->SR2));* ]* E- H* m# h
- }3 I8 O. L% i8 q5 l+ L6 N! d
- & n4 l5 `* P8 S1 _1 j0 i
- //Clear STOPF by reading SR1, then writing CR10 o4 E, z! [2 v3 Q
- 2 }/ ?2 N% h% ?3 p
- void I2C_clear_STOPF(I2C_TypeDef* I2Cx) {
! H8 z- S& F; _; w# g; A - I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF);; w4 n0 K8 I' G0 D5 z
- I2C_Cmd(I2Cx, ENABLE);
- F' N; \5 ^% E3 { - }4 G0 U( D1 v2 l! o
- ; U, H5 \1 s- J3 ^9 [% r! \, ~
- /*--------------------------------------------------------------------------------
h! s8 ]6 ?! {5 f3 I. o, w - 调用方式:void I2C1_EV_IRQHandler(void); N; N/ d& X% k0 K% s
- 函数说明:私有函数,I2C专用,中断按键处理函数,从机中断都在这里面执行# Q# [6 O% h( K, C8 o
- ---------------------------------------------------------------------------------*/
1 G6 c; e/ g; V5 j - e: V3 A* D7 F0 E2 I( U) m; I. x
- uint8_t data = 0;" k3 K& o+ j# d
- uint8_t S_data=0;
* u C5 N. B. l& w - void I2C1_EV_IRQHandler(void)
$ |" P0 I/ g. _2 G# s7 F+ X4 D, k - {0 [% J- R5 r: C& J( i. K: B
- // KV1=0; //只是一个测试灯- d: I: c9 p2 W: [) M
- //Clear AF from slave-transmission end
4 z6 Q* I4 c. ?# R% s9 Q( X - if(I2C_GetITStatus(I2C1, I2C_IT_AF))
4 D2 K: Z: O }: a; e; t - {
4 i* m, f. F; w, E' J - I2C_ClearITPendingBit(I2C1, I2C_IT_AF);4 U6 I5 P. m3 l9 |# E% S0 A
- }) q* J- L1 u% s0 a0 y3 q7 ]& K$ ?; u
- //Big state machine response, since doesn't actually keep state
' @* ]/ k# r) R+ R1 j/ j! | - switch(I2C_GetLastEvent(I2C1))- k9 y- H8 }) S( X* O3 F7 O4 ]$ @
- {" l! g# o1 l6 v- b
- //SLAVE: M* G7 a4 `, \: p2 G
- //Receive& I0 o2 V1 \7 |* G0 g
- case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED: //EV1& M, @$ M p/ M' X; C
- I2C_clear_ADDR(I2C1);; k- w- C7 p" d5 _* E
- break;+ r7 |0 g2 |1 q! D0 O, \, |
- case I2C_EVENT_SLAVE_BYTE_RECEIVED: //EV28 ~7 f4 _3 Q$ G3 Y6 H' t# J
- //Read it, so no one is waiting, clears BTF if necessary, J; C6 R2 M' E5 ^& M! p* j. y: M
- b[data] = I2C_ReceiveData(I2C1);) U! g9 f$ l) b4 z9 |
- // printf("%c",b[data]);
- `. W( p) b3 s" _) b) S - data++;" E s; b2 h) c- F) l$ n6 E) `
- if(data>=5)
! i1 [& s5 [/ } - {% L& M a [7 }$ {+ d
- data=0;
$ W6 u: T# C6 q3 P3 T9 G# s - if((b[0]==0xFA)&&(b[4]==0xFB))
9 u3 E6 j# f) J$ [, S- m. L - {
$ V1 |% M! h& S9 h% U' v8 W5 W - a[1]=b[1];
: q0 q# {2 q4 C) O% S; H) x0 K/ | - Wifi_Set=b[2];
$ x& M: i* D7 _% i# y3 a0 G - flag=b[3];/ H, Q! e7 d# }& ]1 H3 N e: J
- // printf("%c",a[1]);2 k8 X7 o, z1 n6 Z% F
- }
/ G( R% {( O* u s' F. H' J+ n% G
; E% F/ C* p8 w, p/ b3 l1 p- }, n: X$ {% `3 C$ M
- if(I2C_GetFlagStatus(I2C1, I2C_FLAG_DUALF))
' w4 E9 y+ K5 V0 n - {//Secondary Receive
# X9 z# }5 ?* H - }
, O: x9 a2 ]% ?) ]0 E - else if(I2C_GetFlagStatus(I2C1, I2C_FLAG_GENCALL))' N/ S8 v4 K J% O1 x R {) A
- {//General Receive
( K& g9 q/ x9 ^- v+ s( | - }* L% m$ [5 g8 ]0 v9 R% @
- else* Z6 c& d7 h- W3 D& W, D# ^
- {//Normal
/ F+ w) Y7 |. j" ?- s( }, r9 d9 m - }# p* U6 D& j* C* o% z
- break;- t, z( S- \4 k3 v; b
- case I2C_EVENT_SLAVE_STOP_DETECTED: //End of receive, EV4
: c* O# U3 v9 X9 b2 `$ w - I2C_clear_STOPF(I2C1);2 B+ ?" _" m' c% v
- break;: c/ {& @- _& B
- 4 C# @8 X7 o% ?. z+ s7 ~' H+ |
- //Transmit9 V2 S7 X' ~7 m( I
- case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED: //EV1
^9 n n4 B# I8 A6 n$ k2 B) E8 ^2 Q - I2C_clear_ADDR(I2C1);
. h6 H/ g; y; e( H2 z* c - //Send first byte
& O& G4 [. X1 e - I2C_SendData(I2C1, 0x00);! D. I# c' O0 v2 {: ?
- 4 c; ]! K4 `' h% u+ M0 W
- break;
; L& d1 ^* ] q7 n4 F - case I2C_EVENT_SLAVE_BYTE_TRANSMITTED: //EV3
2 x) d; Z5 l( `9 `# \- u: Z; o - //Determine what you want to send/ U/ Z1 R3 U& L0 E' B
- //data = 5;
, q' ~6 C$ E' d: _ - if(I2C_GetFlagStatus(I2C1, I2C_FLAG_DUALF))) C$ H/ ^8 k/ m/ W8 T
- {//Secondary Transmit
5 c4 k) ~3 z# D2 v- M. A - }
% n# F4 z$ I3 A+ j - else if(I2C_GetFlagStatus(I2C1, I2C_FLAG_GENCALL))
; F9 u' a( m. \6 T1 h N5 z - {//General Transmit" l/ J8 z& P3 |- ?5 R' p
- }7 f0 j: o) ~! O" T) f. t: s9 a; P
- else. T# m6 u$ a# k6 B, |+ z
- {//Normal
5 U. P' B( D. V3 Q% j4 I* ? - }5 N; U5 l. ]" @# e. `4 b
- //Read flag and write next byte to clear BTF if present( _% M% M0 U: G' c
- I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF);
9 t3 g' C! Y- b1 M6 o$ t - I2C_SendData(I2C1, a[S_data]);
2 u0 b4 z& `9 F+ w1 d$ t - S_data++;+ Q3 }. \) F/ ^, V: z: M
- if(S_data>=5)3 _, R) t7 P+ j) N. b
- S_data=0;$ Z8 b3 i, q6 }7 \
- break;* v3 R5 m/ |) @4 v" h' [# ^) r( c
- case I2C_EVENT_SLAVE_ACK_FAILURE://End of transmission EV3_2' m0 v; @: [2 _3 I+ C7 ^
- //TODO: Doesn't seem to be getting reached, so just) C. U/ O, S( B% g3 j
- //check at top-level* v) |. V6 I/ V) z" H. j
- I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
* \0 O7 V7 ]) f7 Y. _ - break;
, p" l8 A+ Y; a7 J - //Alternative Cases for address match& I- z% m5 C3 t& X2 x9 ~
- case I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED: //EV1
; A6 |: Q4 @2 [- _+ {9 J - break;
# f W: G6 G2 K- J9 ^" Y - case I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED: //EV14 z. e+ b# t* j' Z6 M$ ~
- break;
" v; H8 Y5 e3 g/ V' a - case I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED: //EV1
0 I8 N. ~ v" f8 K - break;- K6 L! S1 w: W
- 0 D$ j( F0 [: x; T. v
9 {5 v: Q0 N4 L' ^4 J# |- H- //MASTER. `) I/ y" O' c" X
- case I2C_EVENT_MASTER_MODE_SELECT: //EV5, just sent start bit
; @- U; r! x h& U$ s' A" O; [' v - break;- u% ]. r& g) ^8 |3 _4 \% `# L
- //Receive9 A8 @ o' I4 \; |
- case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: //EV6, just sent addr" V Y. H8 ]3 y2 V Y: J' a5 N
- break;
+ L9 C& n3 q3 o1 c( E$ s - case I2C_EVENT_MASTER_BYTE_RECEIVED: //EV7
5 [/ h0 u; Q2 {% s4 [ - break;4 v$ `7 p4 ^ [% b8 q1 D( X
- //Transmit! @; k Q& i! u- a- G& Q
- case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: //EV6, just sent addr
+ P! q, s' F/ S7 c4 M - break;: x Y/ `3 @% v6 ]( S
- case I2C_EVENT_MASTER_BYTE_TRANSMITTING: //EV8, about to send data* h# i& w- y% f. {
- break; k% n. D, ~3 h) X, `1 @9 \
- case I2C_EVENT_MASTER_BYTE_TRANSMITTED: //EV8_2, just sent data
& ?. U; x X, \! E& f+ k" `+ Y - break; S, @' S5 \; P) @% l. A
5 i- `- C" Z2 C+ ]/ H- //Alternative addressing stuff, not going to worry about+ a, z7 t! K' d0 `) D- @% w2 G! R
- case I2C_EVENT_MASTER_MODE_ADDRESS10: //EV9& {' E. F! U! J
- break;
* A+ c' z% [ r - default:& o. O! B$ `. o0 j6 u5 }9 @
- //How the FUCK did you get here?
3 Y3 j! O1 l& u, ^1 z* A - //I should probably raise some error, but fuck it,9 z' p; k+ F+ P# Z0 v
- //it's late
( S, {7 M6 w( \* Z - break;
; n, ?; z) c4 H! g- t2 ]8 \
5 @( f2 O3 h) r( j+ k0 k- }( D- V* {9 |. t
1 l9 r1 x/ Y5 }' m r! J* P) A. Z- 3 p1 D6 T. M) H( Z' ^. q0 p* B3 F
- }
4 E& W2 t+ V$ h1 y2 i: t - ' q- Y1 z6 N2 `
- void I2C1_ER_IRQHandler(void) {% F r: ?. w4 j0 E+ e& k) z. F
- // GPIO_SetBits(GPIOD, RED);
7 J% P8 v7 f! ^8 V - // LED3=0;9 o K% s, `* F n3 \" W1 b
- //Can't use nice switch statement, because no fxn available
8 ^6 I6 u4 {* S* Z3 T - if(I2C_GetITStatus(I2C1, I2C_IT_SMBALERT)) {
! Q/ n0 C4 x) y' ~ - } else if(I2C_GetITStatus(I2C1, I2C_IT_TIMEOUT)) {( h+ G4 p4 p' x: j0 H/ b
- } else if(I2C_GetITStatus(I2C1, I2C_IT_PECERR)) {
; Q& i' O+ i3 D3 Q4 Y: y9 M! `. o/ l - } else if(I2C_GetITStatus(I2C1, I2C_IT_OVR)) {
7 \! k9 }" d$ Z3 h0 r4 X) ? - //Overrun- ~5 }. ~# B# C5 f
- //CLK stretch disabled and receiving
: ~8 Z" J9 f) y - //DR has not been read, b4 next byte comes in3 a2 k& ]5 u9 r' `7 H' [' ~3 }
- //effect: lose byte
8 y* Q4 o7 O: U6 U - //should:clear RxNE and transmitter should retransmit' D, I/ A; N; c
8 r0 N3 `( s0 S( t+ P' Z- //Underrun- K, b2 \& y$ h6 P4 Z2 n
- //CLK stretch disabled and I2C transmitting
( x& U' w! u( p) R - //haven't updated DR since new clock' K8 }& s( b$ C
- //effect: same byte resent
, Y* g9 s, `' M' q% H - //should: make sure discarded, and write next
9 f: ~6 _' O7 d9 e+ D! w0 N - } else if(I2C_GetITStatus(I2C1, I2C_IT_AF)) {
$ G4 d% u- [: X- b. g - //Detected NACK5 n# H1 f/ r" U( U
- //Transmitter must reset com) n/ `/ H' p) Y u. n
- //Slave: lines released
+ u6 o" `' l* b( j9 e& A( A - //Master: Stop or repeated Start must must be generated; \& S Q+ h1 u; R/ w" s
- //Master = MSL bit
: r( _ P. X6 F% ]/ j5 B - //Fixup
- r- V% i* @: v& q5 H3 }% d, W; \; M1 f* P - I2C_ClearITPendingBit(I2C1, I2C_IT_AF);7 s7 j+ Q J8 Y, X
- } else if(I2C_GetITStatus(I2C1, I2C_IT_ARLO)) {; Y* X2 [$ T, h& S3 U% C- A
- //Arbitration Lost! ~ y; B8 f) h, B0 {
- //Goes to slave mode, but can't ack slave address in same transfer6 q. F; d/ Z4 p1 P4 w; l
- //Can after repeat Start though
# X. r" ~( y% n. o+ F) M - } else if(I2C_GetITStatus(I2C1, I2C_IT_BERR)) {5 H* M3 [& J- w R" r9 @
- //Bus Error
1 t- z( a# E. ~ i - //In slave mode: data discarded, lines released, acts like restart# ~, a8 I3 K. k1 m6 v8 K" O! u
- //In master mode: current transmission continues
2 A2 [2 B$ r* v* K6 h - }
1 j3 d$ }$ Y: U2 o/ v6 Y" ^. u - }
复制代码
7 d) [3 r4 R$ N6 O8 A% L3 x( W: s' ?
|