打印
[学习资料]

IIC接收和发送信息时序

[复制链接]
742|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hilahope|  楼主 | 2024-4-14 21:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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;
        }
}

使用特权

评论回复
沙发
tpgf| | 2024-5-8 08:33 | 只看该作者
为什么iic对时序的要求这么的严格呢

使用特权

评论回复
板凳
guanjiaer| | 2024-5-8 08:50 | 只看该作者
如果使用iic模块来发送接收的话 也需要这么复杂的代码吗

使用特权

评论回复
地板
heimaojingzhang| | 2024-5-8 09:37 | 只看该作者
为什么要使用for语句来做时间的延时呢

使用特权

评论回复
5
keaibukelian| | 2024-5-8 10:39 | 只看该作者
iic通讯方式下 每包数据的时间间隔最小应该是多少啊

使用特权

评论回复
6
renzheshengui| | 2024-5-8 22:51 | 只看该作者
每一条语句的延时时间应该设置成多少比较好呢

使用特权

评论回复
7
paotangsan| | 2024-5-8 23:24 | 只看该作者
楼主的代码好像是使用的io来模拟iic的是吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

1306

帖子

0

粉丝