我是靠谱客的博主 鲤鱼电脑,最近开发中收集的这篇文章主要介绍关于I²C通信协议的理解,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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通信协议的理解所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部