大家好,欢迎来到IT知识分享网。
物理I2C接口有两根双向线:串行时钟线(SCL)和双向串行数据线(SDA),可用于发送和接收数据,但是通信都是由主设备发起,从设备被动响应,实现数据的传输。SDA负责在设备间传输串行数据,SCL负责产生同步时钟脉冲。
一、基础介绍
调I2C时序,主要在调数据写入write_I2C和数据读取read_I2C的机制。I2C主要实现数据的传输,使主机和从机的相互响应。它有一种数据传送机制。总结起来为:起始信号,终止信号、应答信号,读字节,写字节,数据读取和数据写入。
I2C基本架构:
Start_I2C Stop_I2C readack 读取应答信号 sendack and sendnack 输出应答或非应答 sendbyte readbyte write_I2C read_I2C
二、I2C通信协议详解
SDA和SCL变化情况:
所有数据传输均起始于一个start,终于一个stop. Start_I2C定义:SCL为高时,SDA从高到低转换; Stop_I2C定义:SCL为高时,SDA从低到高转换; 数据有效性:SCL为高时,SDA的数据必须稳定; 只有SCL变低时,SDA的状态才能跳变。
1、空闲状态
SCL和SDA接上拉电阻,默认高电平,表示总线是空闲状态
2、主从设备
主设备负责控制通信,通过对数据传输进行初始化/终止化,来发送数据并产生所需的同步时钟脉冲。 从设备则是等待来自主设备的命令,并响应命令的接收。且同步时钟信号只能由主设备产生。
3、起始信号和结束信号
:
(1) I2C的起始位
void I2C_sendStart() //开始位 {
SDA=1; /*发送起始条件的数据信号*/ SCL=1; SDA=0; /*发送起始信号*/ Delay_us(1); SCL=0; }
(2)I2C的结束位
Void sendstop() {
SCL=0; SDA=0; /*发送结束条件的数据信号*/ SCL=1; while(SCL!=1) {
}; Delay_us(1); SDA=1; Delay_us(1); }
4、数据有效性
I2C总线进行数据传送时,在SCL的每个时钟脉冲期间传输一个数据位,时钟信号SCL为高电平期间,数据线SDA上的数据必须保持稳定,只有在时钟线SCL上的信号为低电平期间,数据线SDA上的高电平或低电平状态才允许变化,因为当SCL是高电平时,数据线SDA的变化被规定为控制命令(START或STOP,也就是前面的起始信号和停止信号)。
从机地址发送完后可能会发送一些指令,依从机而定,然后开始传输数据,由主机或者从机发送,每个数据为8位,数据的字节数没有限制。在开始信号之后,SDA和SCL先都处于低电平,当要传输数据时SDA先为高,之后SCL再跳变为高,才可进行数据的传输:
5、应答信号
当SDA是低电平为有效应答(ACK),表示对方接收成功; 当SDA是高电平为无效应答(NACK),表示对方没有接收成功。
接收端收到有效数据后向对方响应的信号,发送端每发送一个字节(8位)数据,在第9个时钟周期释放数据线去接收对方的应答。
(1)、接收数据需向发送方发送应答:
void IIC_ack(u8 ack) {
// 数据线设置为输出 SCL = 0; delay_us(5); if(ack) SDA = 1; // 无效应答 else SDA = 0; // 有效应答 delay_us(5); SCL = 1; // 保持数据稳定 delay_us(5); // 拉低SCL开始传输数据 SCL = 0; }
(2)、发送数据需等待接收方的应答:
// 等待ACK 1-无效 0-有效 u8 IIC_wait_ack(void) {
u8 ack = 0; // 数据线设置为输入 // 拉高时钟线 SCL = 1; delay_us(5); // 获取数据线的电平 if(SDA) {
// 无效应答 ack = 1; IIC_stop(); } else {
// 有效应答 ack = 0; // 拉低SCL开始传输数据 SCL = 0; delay_us(5); } return ack; }
三、I2C通信实现方式
1、硬件I2C
即使用I2C控制器实现,使用芯片上的I2C外设,它有相应的I2C驱动电路,有专用的I2C引脚,调用I2C的控制函数即可,无需用代码去控制SCL、SDA的各种高低电平变化来实现I2C协议,只需要将I2C协议中的可变部分(如:从设备地址、传输数据等等)通过函数传参给控制器,控制器自动按照I2C协议实现传输,但是若出现问题,只能通过示波器看波形找问题。
2、模拟I2C
通过使用任意IO口去模拟实现I2C通信协议,手动写代码去控制IO口的电平变化,模拟I2C协议的时序,实现I2C信号和数据传输。
3、数据读取和写入的示例:
Write_I2C:start->slave address+0+ACK+数据包(byte+ack+…+byten+Nack)+stop Read_I2C:start->slave address+1+ACK+数据包(byte+ack+…+byten+Nack)+stop
注意:关于slave address是7位的一个字节,write是0位,read是1位;
示例:slave address为50H()
则写地址在其后加一位0,即变成(),为A0
读地址在其后加一位1,即变成(),为A1;
write_I2C {
Start_I2C; sendbyte();//传送地址与写入标记 readack; sendbyte();//传送字节 readack; Stop_I2C; } read_I2C {
Start_I2C; sendbyte();//传送地址与读取标记 readack; readbyte();//读取字节 sendack and sendnack Stop_I2C; }
4、应用示例
Define address:根据芯片规格书定义读写地址
设置端口:SDA/SCL/INT
缓存buffer: 主控端的写入和读取资料缓存
(1)读取I2C的应答标志位
Unsigned char readACK() //读取应答信号 {
SCL=0; SDA=1; /*此处为释放SDA 总线,由从从机发出低电平应答*/ _nop_(); SCL=1; _nop_(); if(SDA) return 1; //no ACK else return 0; //ACK }
(2)主控端送出应答信号
void sendACK() //输出应答信号 {
SCL=0; SDA=0; _nop_(); SCL=1; } void sendNOACK() //输出无应答信号 {
SCL=0; SDA=1; _nop_(); SCL=1; }
(3)主控端写入一个字节到从机
void sendByte(uchar dat) //写一个字节 {
uchar i; for(i=0;i<8;i++) {
SCL=0; /*钳住I2C 总线,准备发送数据 */ if(dat&0x80) SDA=1; else SDA=0; _nop_(); _nop_(); SCL=1; dat<<=1; } }
(4)主控端对从机读取一个字节
uchar readByte() //读一个字节 {
uchar i, dat=0; for(i=0;i<8;i++) {
SCL=0; SDA=1; _nop_(); dat<<=1; SCL=1; if(SDA==1) dat|=0x01; } return dat; }
(5)主控端数据写入
bit writeIIC(uchar addrW, uchar *writeData, uchar length) {
uchar i; bit ACK; sendStart(); sendByte(addrW); //传送地址与写入标记 ACK = readACK(); if (ACK) {
sendStop(); //地址不正确或装置未连接,送出停止信号 return ACK; } for(i = 0; i<length; i++) {
sendByte(writeData[i]); ACK = readACK(); if (ACK) {
sendStop(); //未接收到ACK,送出停止信号 return ACK; } } sendStop(); //资料写入完成,送出停止信号 return ACK; }
(6)主控端对从机数据读取
bit readIIC(uchar addrR, uchar *readData, uchar length) {
uchar i; bit ACK; sendStart(); sendByte(addrR); //传送地址与读取标记 ACK = readACK(); if (ACK) {
sendStop(); //地址不正确或装置未连接,送出停止信号 return ACK; } for(i = 0; i<length; i++) {
readData[i] = readByte(); if(i<length-1) sendACK(); else sendNOACK(); //读取最后一笔资料,送出No ACK } sendStop(); //资料读取完成,送出停止信号 return ACK; }
(7)调用数据写入和读取
writeIIC(address_W, &Write_Buffer,4); readIIC(address_R, &Read_Buffer, 5);
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/138104.html