发送启动信号S
在同步时钟线SCL 为高电平时,数据线出现的由高到低的下降沿。 启动信号子程序STA
1 /******************************************************************************* 2 * 函数名 : I2cStart() 3 * 函数功能 : 起始信号:在SCL时钟信号在高电平期间SDA信号产生一个下降沿 4 * 输入 : 无 5 * 输出 : 无 6 * 备注 : 起始之后SDA和SCL都为0 7 *******************************************************************************/ 8 9 void I2cStart() 10 { 11 SDA=1; 12 Delay10us(); 13 SCL=1; 14 Delay10us();//建立时间是SDA保持时间>4.7us 15 SDA=0; 16 Delay10us();//保持时间是>4us 17 SCL=0; 18 Delay10us(); 19 }
发送停止信号P
在SCL 为高电平期间SDA 发生正跳变。
停止信号子程序STOP
1 /******************************************************************************* 2 * 函数名 : I2cStop() 3 * 函数功能 : 终止信号:在SCL时钟信号高电平期间SDA信号产生一个上升沿 4 * 输入 : 无 5 * 输出 : 无 6 * 备注 : 结束之后保持SDA和SCL都为1;表示总线空闲 7 *******************************************************************************/ 8 9 void I2cStop() 10 { 11 SDA=0; 12 Delay10us(); 13 SCL=1; 14 Delay10us();//建立时间大于4.7us 15 SDA=1; 16 Delay10us(); 17 }
等待应答信号
应答信号:应答信号由接受设备产生,在scl信号为高电平期间,接受设备将SDA拉低为低电平一段时间,表示数据传输正确。
非应答信号:应答信号由接受设备产生,在SCL信号为高电平期间,接受设备不将将SDA拉低为低电平一段时间,没有应答。
1 /******************************************************************************* 2 * 函数名 : yingda() 3 * 函数功能 : 对数据是否被从机接受给出应答/非应答信号(1/0) 4 * 输入 : 无 5 * 输出 : 0或1。发送成功返回1,发送失败返回0 6 * 备注 : 发送完一个字节SCL=0,SDA=1 7 *******************************************************************************/ 8 void yingda() 9 { 10 unsigned char b; 11 while(SDA)//等待应答,也就是等待从设备把SDA拉低 12 { 13 b++; 14 if(b>200) //如果超过2000us没有应答发送失败,或者为非应答,表示接收结束 15 { 16 SCL=0; 17 Delay10us(); 18 return 0; 19 } 20 } 21 SCL=0; 22 Delay10us(); 23 return 1; 24 }
通过I2C发送一个字节
数据传送格式
unsigned char I2cSendByte(unsigned char dat) { unsigned char a=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; yingda(); //应答子函数 }
使用I2c读取一个字节
1 /******************************************************************************* 2 * 函数名 : I2cReadByte() 3 * 函数功能 : 使用I2c读取一个字节 4 * 输入 : 无 5 * 输出 : dat 6 * 备注 : 接收完一个字节SCL=0,SDA=1. 7 *******************************************************************************/ 8 9 unsigned char I2cReadByte() 10 { 11 unsigned char a=0,dat=0; 12 SDA=1; //起始和发送一个字节之后SCL都是0 13 Delay10us(); 14 for(a=0;a<8;a++)//接收8个字节 15 { 16 SCL=1; 17 Delay10us(); 18 dat<<=1; 19 dat|=SDA; 20 Delay10us(); 21 SCL=0; 22 Delay10us(); 23 } 24 return dat; 25 }
以At24c02举例说明i2c总线读写数据过程
a、主机向从机发送数据,数据传送方向在整个传送过程中不变:
注:有阴影部分表示数据由主机向从机传送,无阴影部分则表示数据由从机向主机传送。
A表示应答, A非表示非应答(高电平)。
S表示起始信号,P表示终止信号。
1 /******************************************************************************* 2 * 函数名 : void At24c02Write(unsigned char addr,unsigned char dat) 3 * 函数功能 : 往24c02的一个地址写入一个数据 4 * 输入 : 无 5 * 输出 : 无 6 *******************************************************************************/ 7 8 void At24c02Write(unsigned char addr,unsigned char dat) 9 { 10 I2cStart(); 11 I2cSendByte(0xa0); //发送写器件地址 用“0”表示主机发送数据(T),“1”表示主机接收数据(R)
12 I2cSendByte(addr);//发送要写入内存地址 13 I2cSendByte(dat); //发送数据14 I2cStop(); 15 }
b、主机从从机读数据
1 /******************************************************************************* 2 * 函数名 : unsigned char At24c02Read(unsigned char addr) 3 * 函数功能 : 读取24c02的一个地址的一个数据 4 * 输入 : 无 5 * 输出 : 无 6 *******************************************************************************/ 7 8 unsigned char At24c02Read(unsigned char addr) 9 { 10 unsigned char num; 11 I2cStart(); 12 I2cSendByte(0xa0); //发送写器件地址 13 I2cSendByte(addr); //发送要读取的地址 14 I2cStart(); 15 I2cSendByte(0xa1); //发送读器件地址 16 num=I2cReadByte(); //读取数据 17 I2cStop(); 18 return num; 19 }
来源:https://www.cnblogs.com/zhj868/p/12536778.html