一、使用平台
MCU | GD32F450ZKT6 |
处理器 | Cortex-M4 |
SRAM | 256k |
Flash | 3072k |
SDK | GD32F4xx_Firmware_Library_V2.1.2 |
二、I2C简介
1、I2C总线
是两线式的串行总线、半双工、同一时间只可以单向通信。I2C(内部集成电路总线)模块提供了符合工业标准的两线串行制接口,可用于 MCU 和外部 I2C 设备的通讯。I2C 总线使用两条串行线:串行数据线SDA 和串行时钟线 SCL。
2、 数据有效性
I2C协议对数据的采样发生在SCL线高电平期间,也就是数据高电平有效性。
数据有效性
3、 设备地址
I2C每发送一帧数据,就有8bit数据和1bit应答。起始信号之后要先发送8位设备地址(7位从机地址+1位读写地址)。0表示主设备向从设备写(write)地址,1表示主设备向从设备读(read)地址。
3.1 I2C物理层
I2C由一条双向的串行数据线SDA和一条串行时钟线SCL组成,空闲状态需外接上拉电阻,使其保持稳定性。
3.2 I2C协议层
起始信号:SCL为高电平期间,SDA由高电平变到低电平,产生一个有效的下降沿。
//模拟起始信号
void I2C_start()
{
SDA = 1; //确保SDA被拉高
delay_us(5); //延时5微秒,保证SDA拉高完成
SCL = 1; //确保时钟线被拉高
delay_us(5); //延时5微秒,保证SCL拉高完成
SDA = 0; //在SCL为高电平时,拉低SDA,产生一个有效的下降沿
delay_us(5); //延时5微秒,保证SDA拉低完成
SCL = 0; //拉低SCL,准备收发数据
}
停止信号:SCL为高电平器件,SDA由低电平变到高电平,产生一个有效的上升沿。
//模拟停止信号
void I2C_stop()
{
SCL = 0; //拉低SCL
SDA = 0; //拉低SDA
delay_us(5); //延时5微秒
SCL = 1; //拉高SCL
SDA = 1; //在SCL为高电平时,拉高SDA,产生有效的上升沿
}
应答信号:SCL的第9个时钟周期为高电平期间,SDA处于低电平期间。
//模拟应答信号
void I2C_Ack(void)
{
SCL=0; //先拉低SCL,使得SDA数据可以发生改变
SDA=0; //拉低SDA
delay_us(5);
SCL=1; //拉高SCL
delay_us(5);
SCL=0; //拉低SCL,期间SDA一直保持低电平
}
非应答信号:SCL第9个时钟周期为高电平期间,SDA处于高电平期间。
//模拟非应答信号
void I2C_NAck(void)
{
SCL=0; //先拉低SCL,使得SDA数据可以发生改变
SDA=1; //拉高SDA,不产生应答信号
delay_us(2);
SCL=1; //拉高SCL
delay_us(5);
SCL=0; //拉低SCL,期间SDA一直保持高电平
}
等待应答信号:拉高SCL线,获取SDA的高电平或者低电平。
//等待应答信号
uint8_t IIC_WaitACK(void)//等待应答信号
{
uint8_t temp=0;
SCL_Low; //拉低时钟线
I2C_SDA_In(); //输入模式
SCL_High; //拉高时钟线
Delay_1us(4);
while(SDA_Read){ //检测应答信号
temp++;
if(temp>250){ //判断是否超时
I2C_stop();
return NACK;
}
}
SCL_Low;
return ACK;
}
发送数据信号:SCL为高电平期间,数据稳定发送。SCL为低电平期间,允许改变数据。
//模拟发送数据信号
void IIC_SendByteData(uint8_t data)//发送数据信号
{
uint8_t i;
SCL_Low;
I2C_SDA_OUT(); //输出模式
for(i=0;i<8;i++){
if(data&0x80){ //判断为真,拉高SDA,反之拉低SDA
SDA_High;
}else{
SDA_Low;
}
SCL_High;
Delay_1us(5);
SCL_Low;
Delay_1us(5);
data=data<<1; //data左移一位,接着进行判断,例0111 0011 << 1 为1110 0110
}
SCL_Low;
}
接收数据信号:拉高SCL线读取数据,拉低SCL线,从设备准备数据。
//模拟接收数据信号
uint8_t IIC_RxByteData(uint8_t ackflag)//接收数据信号
{
uint8_t i;
uint8_t txdata=0;
SCL_Low; //拉低时钟线
I2C_SDA_In(); //输入模式
for(i=0;i<8;i++){ //txdata初始值为0
txdata=txdata<<1;
SCL_High; //拉高SCL
Delay_1us(5);
if(SDA_Read){ //如果检测到应答信号,则txdata与0x01置1
txdata=txdata|0x01;
}
SCL_Low;
Delay_1us(5);
}
SCL_Low;
if(ACK==ackflag){ //ack为1,发送ACK,为0,发送NACK
I2C_Ack();
}else{
I2C_NAck();
}
return txdata;
}
三、通信原理
1、原理
通过对SCL和SDA线高低电平时序的控制,来产生I2C总线协议所需信号进行数据的传递。
2、写数据
主机给从机发送数据。首先主机发起通讯信号,然后写入设备地址,主机收到从机发送的应答信号后。开始写入数据(DATA),一次发送的数据包大小为8位,每次发送完数据包后都需要等待应答信号。重复N次此过程。最后写完数据,由主机发起停止信号。
3、读数据
主机读取从机发送来的数据,首先主机发起通讯,然后写入设备地址,主机收到从机回复的应答信号后。从机开始向主机传输数据,一次发送的数据包大小为8位。主机回复应答信号,每次发送完数据包都需要等待应答信号。重复N次此过程。最后写完数据。由主机发起非应答信号,并发送停止信号。
四、I2C主要特点
(1)I2C主设备功能:主要产生时钟,产生起始信号和停止信号。
(2)I2C从设备功能:可编程的I2C地址检测,停止位检测。
(3)I2C的一个优点是它支持多主控, 其中任何一个能够进行发送和接收的设备都可以成为主总线。一个主控能 够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。
(5)每一个连接总线的设备都有一个独立的地址,主机可以通过地址来选择连接总线的设备和通信。
(6)传输速率有三种:标准模式为100kbit/s,快速模式为400kbit/s,高速模式为3.4Mbit/s。