I²C(Inter-Integrated Circuit)总线是一种两线式串行总线,用于连接微控制器及其外设,是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。
IIC总线在传送数据过程中共有3种类型信号,分别是开始信号、结束信号和应答信号。
SCL |
SDA |
|
开始信号 |
高电平 |
由高电平向低电平跳变,开始传送数据 |
结束信号 |
高电平 |
由低电平向高电平跳变,结束传送数据 |
应答信号 |
接收数据的IC在接收到8bit数据后向发送数据的IC发出特定的低电平脉冲,表示已经收到数据;CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断;若未收到应答信号,则判断为受控单元出现故障。 |
1.初始化IIC
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //初始化IIC 2 void IIC_Init(void) 3 { 4 RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟 5 GPIOC->CRH&=0XFFF00FFF;//PC11/12 推挽输出 6 GPIOC->CRH|=0X00033000; 7 GPIOC->ODR|=3<<11; //PC11,12 输出高 8 }
2.IIC
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //产生IIC起始信号 2 void IIC_Start(void) 3 { 4 SDA_OUT(); //sda线输出 5 IIC_SDA=1; 6 IIC_SCL=1; 7 delay_us(4); 8 IIC_SDA=0;//START:when CLK is high,DATA change form high to low 9 delay_us(4); 10 IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 11 } 12 //产生IIC停止信号 13 void IIC_Stop(void) 14 { 15 SDA_OUT();//sda线输出 16 IIC_SCL=0; 17 IIC_SDA=0; 18 delay_us(4); 19 IIC_SCL=1;//STOP:when CLK is high DATA change form low to high 20 delay_us(4); 21 IIC_SDA=1;//发送I2C总线结束信号 22 } 23 //等待应答信号到来 24 //返回值:1,接收应答失败 25 // 0,接收应答成功 26 u8 IIC_Wait_Ack(void) 27 { 28 u8 ucErrTime=0; 29 SDA_IN(); //SDA设置为输入 30 IIC_SDA=1;delay_us(1); 31 IIC_SCL=1;delay_us(1); 32 while(READ_SDA) 33 { 34 ucErrTime++; 35 if(ucErrTime>250) 36 { 37 IIC_Stop(); 38 return 1; 39 } 40 } 41 IIC_SCL=0;//时钟输出0 42 return 0; 43 } 44 //产生ACK应答 45 void IIC_Ack(void) 46 { 47 IIC_SCL=0; 48 SDA_OUT(); 49 IIC_SDA=0; 50 delay_us(2); 51 IIC_SCL=1; 52 delay_us(2); 53 IIC_SCL=0; 54 } 55 //不产生ACK应答 56 void IIC_NAck(void) 57 { 58 IIC_SCL=0; 59 SDA_OUT(); 60 IIC_SDA=1; 61 delay_us(2); 62 IIC_SCL=1; 63 delay_us(2); 64 IIC_SCL=0; 65 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //IIC发送一个字节 2 //返回从机有无应答 3 //1,有应答 4 //0,无应答 5 void IIC_Send_Byte(u8 txd) 6 { 7 u8 t; 8 SDA_OUT(); 9 IIC_SCL=0;//拉低时钟开始数据传输 10 for(t=0;t<8;t++) 11 { 12 IIC_SDA=(txd&0x80)>>7; 13 txd<<=1; 14 delay_us(2); //对TEA5767这三个延时都是必须的 15 IIC_SCL=1; 16 delay_us(2); 17 IIC_SCL=0; 18 delay_us(2); 19 } 20 } 21 //读1个字节,ack=1时,发送ACK,ack=0,发送nACK 22 u8 IIC_Read_Byte(unsigned char ack) 23 { 24 unsigned char i,receive=0; 25 SDA_IN();//SDA设置为输入 26 for(i=0;i<8;i++ ) 27 { 28 IIC_SCL=0; 29 delay_us(2); 30 IIC_SCL=1; 31 receive<<=1; 32 if(READ_SDA)receive++; 33 delay_us(1); 34 } 35 if (!ack) 36 IIC_NAck();//发送nACK 37 else 38 IIC_Ack(); //发送ACK 39 return receive; 40 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //IO方向设置 2 #define SDA_IN() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;} 3 #define SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;} 4 5 //IO操作函数 6 #define IIC_SCL PCout(12) //SCL 7 #define IIC_SDA PCout(11) //SDA 8 #define READ_SDA PCin(11) //输入SDA