IIC总线时序基础
概要
IIC: Inter-Integrated circuit 集成电路总线,串行通信,由两根线组成:数据线(SDA),时钟线(SCL)。Open-Drain 结构需接上拉电阻。具有线"与"的逻辑功能,只要一个节点发送低电平,总线上就表现为低电平,所有节点为高才表现高。速度较慢一般为100Kh或者400Khz。
IIC总线地址
常用的的地址结构为7bit+1bit(R/W)。bit0=0 为写,bit0=1 为读。
IIC总线状态
- 空闲:SCL,SDA都为高;
- 启动(Start):SCL为高时,SDA由高向低跳变;
- 停止(Stop):SCL为高时,SDA由低向高跳变;
- 数据传输:SDA的每一位信息状态改变只能发生在SCL低电平期间,即低电平变化高电平读取
- 应答:主机箱从机发送数据,每发送8bit就将SDA置1,从机正确收到就会将SDA置0,表示ACK,所以应答信号是从机将主机拉低;
IIC 时序图
- 启动(start)信号
// 起始条件
void I2C_Start() {
SDA = 1; // SDA 高电平
SCL = 1; // SCL 高电平
I2C_Delay();
SDA = 0; // SDA 拉低,产生起始条件
I2C_Delay();
SCL = 0; // SCL 拉低,准备发送数据
}
- 停止(Stop)
// 停止条件
void I2C_Stop() {
SDA = 0; // SDA 低电平
SCL = 1; // SCL 高电平
I2C_Delay();
SDA = 1; // SDA 拉高,产生停止条件
I2C_Delay();
}
- 数据传输
// 发送一个字节
void I2C_SendByte(uchar dat) {
uchar i;
for (i = 0; i < 8; i++) {
SDA = (dat & 0x80) >> 7; // 从最高位开始发送
dat <<= 1; // 左移一位
SCL = 1; // SCL 高电平
I2C_Delay();
SCL = 0; // SCL 拉低
I2C_Delay();
}
SDA = 1; // 释放 SDA,准备接收应答
}
// 接收一个字节
uchar I2C_ReadByte() {
uchar i, dat = 0;
SDA = 1; // 释放 SDA,准备接收数据
for (i = 0; i < 8; i++) {
SCL = 1; // SCL 高电平
I2C_Delay();
dat <<= 1; // 左移一位
dat |= SDA; // 读取 SDA 状态
SCL = 0; // SCL 拉低
I2C_Delay();
}
return dat;
}
- 应答
// 发送应答信号
void I2C_Ack() {
SDA = 0; // SDA 拉低,表示应答
SCL = 1; // SCL 高电平
I2C_Delay();
SCL = 0; // SCL 拉低,继续通信
SDA = 1; // SDA 释放
}
// 发送非应答信号
void I2C_NAck() {
SDA = 1; // SDA 保持高电平,表示非应答
SCL = 1; // SCL 高电平
I2C_Delay();
SCL = 0; // SCL 拉低,继续通信
}
IIC时序逻辑
- 写入从机
数据传输时,时钟信号为高电平,数据要稳定
时钟信号为低电平,数据才允许发生变化
1、主机发送"start"信号+1字节的从机器件地址,等待从机回发"ACK"信号;
2、主机收到从机"ACK"信号,发生1字节的寄存器地址,等待从机回发"ACK"信号;
3、主机收到从机"ACK"信号,发生1字节的数据,等待从机回发"ACK"信号;
4、主机发送"stop"信号。
- 读取从机
1、主机发送"start"信号+1字节的从机器件地址,等待从机回发"ACK"信号;
2、主机收到从机"ACK"信号,发生1字节的寄存器地址,等待从机回发"ACK"信号;
3、主机收到从机"ACK"信号,发送"stop"信号;
4、主机发送"start"信号+1字节的从机器件地址,此时从机地址的bit0要置1变长读操作,等待从机回发"ACK"信号;
5、主机收到从机"ACK"信号,发生1字节的clk,同时从机发出SDA数据;
6、值得注意的是,读取停止的行为是由主机发出"NACK"控制,主机认为读取结束了就拉高SDA;
7、主机发送"stop"信号。
小结
IIC因一个主机可以控制多个从机且每个从机互不干扰,同时具备握手功能,所以应用十分广泛。