前言
IIc总线是单片机与外部模块进行通讯常用的协议,由两根线组成,分别是SCL,SDA组成,主机驱动SCL时钟信号的发生,在SCL的时钟脉冲下,通过SDA的时序,即可与外部模块通讯。
IIC简介
IIC(Inter-Integrated Circuit)总线是一种由NXP(原PHILIPS)公司开发的两线式串行总线,用于连接微控制器及其外围设备。多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距离短,任意时刻只能有一个主机等特性。
- IIC是为了低速设备通信而发明、V(IIC) < V ( spi )
下面就根据AT24C02 的芯片来讲解IIC时序的各个时序单元
a . IIC 起始信号(AT24C02)
开始解析:
从这个时序单元可以看出,一开始SCL 为1,榆次同事SDA也为1 ,于是程序为:
【 注意:我们不需要考虑StartCondition 之前的时序,这是上一个时序单元做的工作
】
void start(){
SCL = 1;
SDA = 1;
}
按照时间的顺序,我们可以看到SDA,和 SCL谁最先变化呢,答案是SDA.,但是时间需要满徐Tchdx > 4.7 uS , 我们可以设置成5us。于是代码为:
void start(){
SCL = 1;
SDA = 1;
Delay5us();
}
紧接着,在SCL为1 期间,SDA开始变化,从 1 变 0 ,而且持续时间为tdlcl > 4 uS,于是代码变成:
void start(){
SCL = 1;
SDA = 1;
Delay5us();
SDA = 0; // 执行这条语句前SDA = 1,和时序图一致
Delay5us(); // 让SDA = 0的状态保持至少4us , 这里我们设置成5us
}
到这里SDA的时需我们已经严格按照启动信号的SDA的时序来写。
但是此时我们忽略了SCL的时序是否满足,也就是Tchcl , 查看参数表发现等于 4,现在我们看代码,从SCL = 1 之后,到Tdlcl
之后,此时时间已经过去了5 + 5us = 10 us
, 也就是满足了,所以我们不需要额外写关于tCHCL的时间代码。
此时启动时序已经完成。
b . 发送数据
我们需要了解一个概念,就是主机和从机是如何通讯的。
答案:
- 我们是通过SCL发送脉冲信号,在脉冲信号为低电平期间,SDA可以变更数据,
- 在SCL从0 - > 1 变化过程中,从机被立马开始读取SDA上的电平信号(读取 0 [ 低电平 ] / 1 [ 高电平 ] )
但是经过start 信号之后,SCL仍然为 高电平,所以第一步就是,将SCL 拉低,为了等下产生一个 由低到高的电平脉冲信号。
由时序图我们可以得知,它要求我们SCL为低电平期间,SDA允许发生变化,那我想要在SCL为高电平期间,SDA发生变化呢?
答案是:不行, 为什么呢?
从上面的分析后,我们开始写代码:
void send_data(uchar data) {
SCL = 0;
if(data & 0x80) SDA = 1;
else SDA = 0;
delay_us();
SCL = 1;
}
但是写到这里,我们发现,我们只考虑SDA的时序规定,而没有考虑SDA的时序规定。
也就是说,我们要考虑SCL 变成低电平后 到 SDA 变成高电平期间,需要持续的时间tCLCH = 4.7us
而我们发现t CLCH 里面包含了 tDXCX ,所以我们只需要考虑tDXCX的时间即可
void send_data(uchar data) {
SCL = 0;
if(data & 0x80) SDA = 1;
else SDA = 0;
delay_5us