一、IIC发送时序图
从上图可以看出:
起始条件:SCL线是高电平时,SDA线从高电平向低电平切换;
停止条件:SCL线是高电平时,SDA线从低电平向高电平切换;
首先SDA和SCL都处于空闲状态(SDA和SCL都为高电平时),
然后,SDA跳变为低电平(可以理解为,SDA向SCL发出通知,我现在要准备发送数据了)
最后,SCL跳变为低电平(因为只有SCL为低电平时,SDA才能跳变进行数据准备)。
这时,启动信号完成,接下来就可以开始发送数据了。
1 void I2C_Start() 2 { 3 I2C_SCL=1; 4 I2C_SDA=1; 5 I2C_SDA=0;
6 delayus(1); 7 I2C_SCL=0;
8 delayus(1);
8 }
首先停止标志是SCL和SDA都处于空闲状态,也就是都处于高电平。
其次,只有当SCL为高电平时,SDA发生跳变才有效。
可以理解为,SCL在高电平期间,SDA从低电平发生跳变到高电平,表示SDA发送一个通知,我发送完成了。
所以停止前,要先确保SDA为低电平,然后SCL在从低电平跳变到高电平。
SCL发生低电平向高电平转换后,SDA在从低电平向高电平切换,这时停止信号完成。
void I2C_Stop(void) { I2C_SCL = 0; I2C_SDA=0; Delayus(1); I2C_SCL=1; Delayus(1); I2C_SDA=1; }
综合来看:
当SCL为高电平:
SDA从高电平跳变到低电平,通知SCL要发送数据了
SDA从低电平跳变到高电平,通知SCL数据发送完成了
二、IIC发送和接收过程
以传输一个字节为例:1010 1010,时序图如下
从上图看出如何发送一个字节:SCL在低电平期间,主机将数据位依次放到SDA线上(高位在前),然后拉高SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA的数据不允许发生变化,依次循环上述过程8次,既可发送一个字节。
发送过程:
1、准备好数据,放到SDA线
2、SCL拉为高电平,即为发数据(从机这个时候读数据)???这里是否要先保证SCL为低电平,然后再准备好数据放到SDA线。是否应该在for循环外部,先给定SCL为低电平。或者说把SCL清零放在for循环内部的第一行
3、SCL拉为低电平,
void I2C_SendByte(unsigned char Byte) { unsigned char i; for(i=0;i<8;i++) { I2C_SDA=Byte&(0x80>>i);//数据先把最高位右移i位,然后与要传输的数据与运算,相当于把数据放到SDA线上 Delayus(1) I2C_SCL=1; //SCL为高电平,这时从机从SDA线读取数据 Delayus(1) I2C_SCL=0; //传输后,再拉为低电平,在低电平期间,SDA在循环的第一句,在放一个数据,依次循环八次,完成数据发送 Delayus(1) } }
接收信号时,首先要确保SDA线处于空闲状态,然后在SCL为高电平的时候,SDA接收1位数据,然后SCL拉低,再一个新的循环时,SCL再被拉为高电平,如此循环。
unsigned char I2C_Receive() { unsigned char i,Byte=0x00; for(i=0;i<8;i++) { I2C_SCL=1;
Delayus(1); if (I2C_SDA) { Byte|= (0X80>>i); }
Delayus(1); I2C_SCL=0; } return Byte; }
三、应答环节
1 void I2C_SendAck(unsigned char AckBit) 2 { 3 I2C_SDA = AckBit;//应答位准备好数据,标签:SCL,高电平,Delayus,51,低电平,单片机,SDA,IIC,I2C From: https://www.cnblogs.com/wanggengwu/p/17350509.html
Delayus(1); 4 I2C_SCL = 1; //SCL为高电平,发送数据
Delayus(1); 5 I2C_SCL = 0; //传输后,再拉为低电平,在低电平期间,
Delayus(1); 6 } 7 unsigned char I2C_ReceiveAck() 8 { 9 unsigned char AckBit; 10 I2C_SCL = 0;//给SDA跳变准备时序 11 I2C_SDA = 1;//释放SDA总线,由从机占用SDA
Delayus(1); 12 AckBit = I2C_SDA; //SCL为高电平,这时从机从SDA线读取数据
Delayus(1);
13 I2C_SCL = 1; //当SCL为高电平时,从SDA读取应答信号
Delayus(1);
14 I2C_SCL = 0; //传输后,再拉为低电平,在低电平期间, 15 Delayus(1); 16 return AckBit; 17 }