概述
I2C 通讯协议 (Inter - Integrated Circuit) 是由 Phiilps 公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、 CAN 等通讯协议的外部收发设备,现在被广泛地使用在系统内多个集成电路 (IC) 间的通讯。
如图是通过IIC通信协议进行通讯的主机与各个从机示意图。
接下来介绍一下我个人理解的IIC读写基本过程。
这是通过协议写入一个字节 数据的过程。首先由主机发出传输信号(S),紧接着开始呼叫从机的具体地址(SLAVE ADDRESS),并且在地址信号后加上一位数据来表明读or写。由于SDA数据线上通常挂在着多个从机设备,所以在主机呼叫从机地址后,各个挂载设备会接受数据并且有与自己的地址进行比对,如果比对成功,则回应主机一位数据(A)。
这时候,主机与从机配对成功,建立通讯,主机开始正式向从机传输数据 (DATA),数据包的大小为 8 位,主机每发送完一个字节数据,都要等待从机的应答信号 (ACK),重复这个过程,可以向从机传输 N 个数据,这个 N 没有大小限制。当数据传输结束时,主机向从机发送一个停止传输信号 (P),表示不再传输数据。
若配置的方向传输位为读数据,则如上图所示,广播从机地址后,有变化的只是从机地址后续的一位读写数据,等接受到从机响应(A)后,数据传输方向发生变化,又从机传输(DATA)数据,而又主机发送应答(A),重复这个过程,可以返回 N 个数据,这个 N 也没有大小限制。当主机希望停止接收数据时,就向从机返回一个非应答信号 (NACK),则从机自动停止数据传输。
时序详解
起始信号(S)和停止信号(P)是两种特殊的状态,时序如下,
简单来说,在SCL时钟线置1的时候,将SDA数据线拉低,这时候表示一个起始信号。
在SCL时钟线置1的时候,将SDA数据线拉高,这时候表示一个停止信号。
搞明白了起始信号与停止信号,接下来就是有效数据的传输。
在SCL时钟线为高电平时,对SDA数据线上的电平进行采集,高电平表示数据1,低电平则表示数据0。在SCL时钟线为低电平时,不对SDA数据线进行采样,一般这个时候SDA数据线会进行电平切换,为下一次传输数据做准备。
而每次数据传输都以字节为单位,每次传输的字节数不受限制。
代码
初始化IIC总线,delay为us级延时函数。
void IIC_init() //IIC初始化
{
SCL=1; //首先把时钟线拉高
delay(4);//延时函数
SDA=1; //在SCL为高的情况下把SDA拉高
delay(4); //延时函数
}
起始信号
//产生IIC起始信号
//1.先拉高SDA,再拉高SCL,空闲状态
//2.拉低SDA
void IIC_Start() //启动信号
{
SDA=1; //确保SDA线为高电平
delay(5);
SCL=1; //确保SCL高电平
delay(5);
SDA=0; //在SCL为高时拉低SDA线,即为起始信号
delay(5);
SCL=0; //拉低SCL,准备发送或接收数据
}
停止信号
//产生IIC停止信号
//1.先拉低SDA,再拉低SCL
//2.拉高SCL
//3.拉高SDA
//4.停止接收数据
void IIC_Stop(void)
{
IIC_SCL=0;
IIC_SDA=0; //STOP:当SCL高时,数据由低变高
delay(4);
IIC_SCL=1;
IIC_SDA=1; //发送I2C总线结束信号
delay(4);
}
发送一个字节
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
//IIC_SCL=0;
//在SCL上升沿时准备好数据,进行传送数据时,拉高拉低SDA,因为传输一个字节,一个SCL脉冲里传输一个位。
//数据传输过程中,数据传输保持稳定(在SCL高电平期间,SDA一直保持稳定,没有跳变)
//只有当SCL被拉低后,SDA才能被改变
//总结:在SCL为高电平期间,发送数据,发送8次数据,数据为1,SDA被拉高,数据为0,SDA被拉低。
//传输期间保持传输稳定,所以数据线仅可以在时钟SCL为低电平时改变。
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
//IIC_SDA=txd&0x80; //获取最高位
//获取数据的最高位,然后数据左移一位
//如果某位为1,则SDA为1,否则相反
if(txd&0x80)
IIC_SDA=1;
else
IIC_SDA=0;
txd<<=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
接受一个字节
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN(); //SDA设置为输入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us(1);
}
if (!ack)
IIC_NAck(); //发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
最后
以上就是鲤鱼电脑为你收集整理的关于I²C通信协议的理解的全部内容,希望文章能够帮你解决关于I²C通信协议的理解所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复