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