I2C总线协议
I2C总线简介:
- I2C总线是PHLIPS公司推出的一种串行总线
- 是具备多主机系统所需的包括总线裁决和高低速器件同步功能的高性能串行总线。
- I2C总线只有两根双向信号线。
- 一根是数据线SDA,另一根是时钟线SCL。
- I2C总线发送数据的整个过程时序
- 主机根据从机地址来进行通信
总线空闲:
- I2C总线 空闲的时候,两条线SDA和SCL都是高电平
传输暂停:
- 接收器件收到一个完整的数据字节后,有可能需要完成一些其它工作,如处理内部中断服务等,可能无法立刻接收下一个字节,这时接收器件可以将SCL线拉成低电平,从而使主机处于等待状态。直到接收器件准备好接收下一个字节时,再释放SCL线使之为高电平,从而使数据传送可以继续进行。
信息传输:
- 起始信号
- SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号。
-
/*************************************************************************
* 函数名 : I2cStart()
* 函数功能 : 起始信号:在SCL时钟信号在高电平期间SDA信号产生一个下降沿
* 输入 : 无
* 输出 : 无
* 备注 : 起始之后SDA和SCL都为0
*************************************************************************/
void I2cStart()
{
SDA=1;
Delay10us();
SCL=1;
Delay10us();//建立时间是SDA保持时间>4.7us
SDA=0;
Delay10us();//保持时间是>4us
SCL=0;
Delay10us();
}
- SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号。
-
/************************************************************************* * 函数名 : I2cStart() * 函数功能 : 起始信号:在SCL时钟信号在高电平期间SDA信号产生一个下降沿 * 输入 : 无 * 输出 : 无 * 备注 : 起始之后SDA和SCL都为0 *************************************************************************/ void I2cStart() { SDA=1; Delay10us(); SCL=1; Delay10us();//建立时间是SDA保持时间>4.7us SDA=0; Delay10us();//保持时间是>4us SCL=0; Delay10us(); }
- 停止信号
- SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。
-
/*************************************************************************
* 函数名 : I2cStop()
* 函数功能 : 终止信号:在SCL时钟信号高电平期间SDA信号产生一个上升沿
* 输入 : 无
* 输出 : 无
* 备注 : 结束之后保持SDA和SCL都为1;表示总线空闲
*************************************************************************/
void I2cStop()
{
SDA=0;
Delay10us();
SCL=1;
Delay10us();//建立时间大于4us
SDA=1;
Delay10us();//SDA持续时间大于4.7us
}
- SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。
-
/************************************************************************* * 函数名 : I2cStop() * 函数功能 : 终止信号:在SCL时钟信号高电平期间SDA信号产生一个上升沿 * 输入 : 无 * 输出 : 无 * 备注 : 结束之后保持SDA和SCL都为1;表示总线空闲 *************************************************************************/ void I2cStop() { SDA=0; Delay10us(); SCL=1; Delay10us();//建立时间大于4us SDA=1; Delay10us();//SDA持续时间大于4.7us }
逻辑“1”和逻辑“0”的表示
- 逻辑“0”。注意在SCL跳变读取期间,要保持SDA的稳定。
- 逻辑“1”。注意在SCL跳变读取期间,要保持SDA的稳定。
-
使用I2C发送数据
-
/*********************************************************** * 函数名 : I2cSendByte(unsigned char num) * 函数功能 : 通过I2C发送一个字节。在SCL时钟信号高电平期间,保持发送信号SDA保持稳定 * 输入 : num * 输出 : 0或1。发送成功返回1,发送失败返回0 * 备注 : 发送完一个字节SCL=0,SDA=1 ************************************************************/ unsigned char I2cSendByte(unsigned char dat) { unsigned char a=0,b=0;//最大255,一个机器周期为1us,最大延时255us。 for(a=0;a<8;a++)//要发送8位,从最高位开始 { SDA=dat>>7; //起始信号之后SCL=0,所以可以直接改变SDA信号 dat=dat<<1; Delay10us(); SCL=1; Delay10us();//建立时间>4.7us SCL=0; Delay10us();//时间大于4us } SDA=1; Delay10us(); SCL=1; while(SDA)//等待应答,也就是等待从设备把SDA拉低 { b++; if(b>200) //如果超过2000us没有应答发送失败,或者为非应答,表示接收结束 { SCL=0; Delay10us(); return 0; } } SCL=0; Delay10us(); return 1; }
使用I2C读取数据/************************************************************ * 函数名 : I2cReadByte() * 函数功能 : 使用I2c读取一个字节 * 输入 : 无 * 输出 : dat * 备注 : 接收完一个字节SCL=0,SDA=1. ************************************************************/ unsigned char I2cReadByte() { unsigned char a=0,dat=0; SDA=1; //起始和发送一个字节之后SCL都是0 Delay10us(); for(a=0;a<8;a++)//接收8个字节 { SCL=1; Delay10us(); dat<<=1; dat|=SDA; Delay10us(); SCL=0; Delay10us(); } return dat; }