IIC总线收发信息框架分析I2C协议特点 1.只有两条总线,一条时钟线SCL,一条数据线SDA,所有挂载在总线上的设备共用一个时钟信息。
2.每个挂载在总线上的设备都是使用软件根据它的地址来识别。
3.I2C是电平触发方式,在时钟信号SCL电平高时数据SDA是稳定的,也就是在电平高时进行数据的接收与发送,在电平低时进行数据的准备,即在电平低时可以进行数据的改变。
4.I2C有3种类型的信号值得注意:(1)开始信号:SCL为高电平时,SDA从高电平向低电平跳变,此时代表要开始传输数据(2)结束信号:SCL为高电平时,SDA由低电平向高电平跳变,此时代表结束传输数据(3)响应信号ACK:由于I2C总线是以8bit为单位进行数据的收发的,所以,接收器在接收到8位数据后,需要进行响应以表示自己准确无误的接收到数据,则需要在第9个时钟周期,发送ACK响应信号,即拉低SDA的电平。
从开始信号和结束信号的定义我们也不难看出为何SCL电平为高时信号是稳定的,因为此时数据线进行任何数据的改变都将被视为开始或者结束信号。
IIC发送信息框架伪代码
有了I2C的硬件层与协议层的基本概述后,首先进行发送数据伪代码的编写,如下所示:
void i2c_send(unsigned char *buf,unsigned char reg, int len){
开始信号;
发送器地址(包括读写标志,这里是写标志);
接收应答;
发送数据存放的寄存器地址;
接收应答;
while(1){
发送数据;
接收应答;
}
终止信号;
}
//
对于上述伪代码的的每一个动作,我们都可以通过封装一个函数来实现。
开始信号:
void I2c_start(void){
将数据置1;
将时钟置1;
延时;
将数据置0;
延时;
将时钟置0;//空闲时间将时钟置为低电平(视情况而定)
}
终止信号:
void I2C_stop{
将数据置0;
将时钟置1;
延时;
将数据置1;
延时;
将时钟置0;//空闲时间将时钟置为低电平(视情况而定)
}
发送数据:
void I2C_send_byte(unsigned char data){
int i;
将时钟置零;//时钟为低开始准备数据
for (i=0;i<8;i++){
if(data)
将数据置1;
else
将数据置零
延时;//等待准备的数据稳定
将时钟置1;//数据稳定之后接收方便可开始读取
延时;
将时钟置0;
}
}
接受应答:
unsigned char I2C_rec_ack(void){
unsigned char ack = 0;
data_in();
将时钟信号置0;//等待从机开始准备应答信号
延时;//等待从机准备好数据
将时钟信号置1;//开始读取数据;
延时;
ack = data_get_in();
将时钟置0;
return data;
}
如下是读取数据伪代码的编写,比发送信息稍微要复杂那么一些,其实也就是多出来一道步骤:
void i2c_send(unsigned char *buf,unsigned char reg, int len){
开始信号;
发送要读取数据的从机的地址(包括读写标志,这里是写标志);
接收应答;
发送要读取数据的寄存器的地址;
接收应答;
开始信号;
发送要读取数据的从机的地址(包括读写标志,这里是读标志);
接受应答;
while(1){
读取数据;
if(接受完毕)
nack;
else
ack;
}
终止信号;
}
读取数据:
unsigned char I2C_rev_byte(void){
unsigned char data = 0;
data_in();
将时钟置零;//时钟为低开始准备数据
for (i=0;i<8;i++){
延时;//等待要读取的数据稳定
将时钟置1;//数据稳定之后便可开始读取
延时;等数据稳定一段时间再读取
data>>1;
data |= data_get_in();
将时钟置0;
}
}
|