对 IIC 总线的理解、调用函数以及常见面试问题
来源:互联网 发布:金拱门域名价格 编辑:程序博客网 时间:2024/06/04 19:33
一、IIC 总线概述:
IIC 即Inter-Integrated Circuit(集成电路总线)
I2C总线是PHLIPS公司推出的一种串行总线, I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。
每个接到I2C总线上的器件都有唯一的地址。主机与其它器件间的数据传送可以是由主机发送数据到其它器件,这时主机即为发送器。由总线上接收数据的器件则为接收器。
二、IIC 总线通信协议:
要掌握IIC的通信协议,需要掌握以下6个通信信号:
1.起始信号
2.终止信号
3.写数据
4.读数据
5.应答信号
6.非应答信号
起始和终止信号
SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。应答信号
IIC 总线协议规定,每传送一个字节数据后,都要有一个应答信号以确定数据传送是否被对方收到。应答信号由接受设备产生,在SCL为高电平期间,接受设备将SDA拉低为低电平,表示数据传输正确,产生应答(ACK)数据传送
I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
根据AT24C02的芯片,可编写以下信号函数程序:
//1.起始信号 SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;void IIC_Start(void) { SDA = 1; SCL = 1; delay_us(1); //15us >> 4.7us SDA = 0; delay_us(1); SCL = 0;}//2.终止信号 SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。void IIC_Stop(void) { SDA = 0; SCL = 1; delay_us(1); //15us >> 4.7us SDA = 1; delay_us(1); SCL = 0;}void IIC_SendByte(unsigned char dat) //3.写数据{ unsigned char i; for (i = 0; i < 8; i++) { if((dat<<i)&0x80) { SDA = 1; } else { SDA = 0; } SCL = 1; //开始让数据维持稳定 delay_us(1); SCL = 0; delay_us(1); } SDA = 1; //释放总线 , 发送完8位,主机置高电平 SCL = 1; delay_us(1); if (SDA) //SDA 低电平 从机回馈低电平 { ack = 0; //0 == ack 代表无ack信号, 从机不应答,发送不成功 } else { ack = 1; //从机应答,发送成功 } SCL = 0; delay_us(5);}unsigned char IIC_RecvByte(void) //4. 读数据{ unsigned char i, temp; SDA = 1; //保险 高的 与 上低的 是低的, 线与 for (i = 0; i < 8; i++) { SCL = 0; // 告诉 数据可以变化 SDA 脉冲线 //只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。 delay_us(1); SCL = 1; // 数据保持稳定, 开始读 delay_us(1); temp<<=1; if (SDA) { temp = temp + 1; } } SCL = 0; delay_us(10); return temp;}void IIC_ACK(void) //5. 应答信号{ SDA = 0; SCL = 1; delay_us(1); SCL = 0;}void IIC_NOACK(void) //6. 非应答信号{ SDA = 1; SCL = 1; delay_us(1); SCL = 0;}
根据时序图,可编写24C02的读写函数程序:
unsigned char AT24CXX_WriteStr(unsigned char devaddr, unsigned char romaddr, unsigned char *s, unsigned char num){ unsigned char i; IIC_Start(); IIC_SendByte(devaddr); if (0 == ack) { return 0; } IIC_SendByte(romaddr); if (0 == ack) { return 0; } for (i = 0; i < num; i++) { IIC_SendByte(*s); if (0 == ack) { return 0; } s++; } IIC_Stop(); return 1;}
unsigned char AT24CXX_ReadStr(unsigned char devaddr, unsigned char romaddr, unsigned char *s, unsigned char num){ unsigned char i; IIC_Start(); IIC_SendByte(devaddr); if (0 == ack) //无应答 返回0 失败 { return 0; } IIC_SendByte(romaddr); if (0 == ack) { return 0; } IIC_Start(); IIC_SendByte(devaddr + 1); if (0 == ack) { return 0; } for (i = 0; i < num - 1; i++) { *s = IIC_RecvByte(); IIC_ACK(); s++; } *s = IIC_RecvByte(); IIC_NOACK(); IIC_Stop(); return 1;}
三、有关 IIC 总线常见面试题:(参考)
- 介绍一下你了解的I2C?
I2C总线是飞利浦(PHLIPS)公司推出的一种串行总线,用于连接微控制器及其外围设备, I2C串行总线有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。 它仅通过两根信号线就可以完成对所有挂载在I2C总线上的从器件进行操作。这样的好处是可以大大的节省我们微处理器的IO口资源。
- I2C到底可以挂载多少个器件呢?
答:IIC协议规定,在启动总线后第1字节的高7位是从节点的寻址地址,其中高四位为器件类型识别符,接着三位为片选,最后一位为读写位,当为1时为读操作,为0时为写操作,所以具体挂载多少个器件由I2C地址决定,7位寻址地址减去1个广播地址0x00不用,所以有2^7=128 - 1 = 127,那就是127个地址, 所以理论上可以挂127个从器件。
- I2C如何同时挂载多个同一种器件(地址相同的器件)?
答:理论上是不会这样设计的,如果一定要这样做的话,可以通过硬件上设计,控制器件是否挂载总线来实现(方法可用一个开关电路切断器件SDA或者SCL是否接入总线来实现)
- I2C总线的主机与从机之间是如何通信的呢?
I2C总线的主机与从机之间的通信主要和I2C的时序有关。在通信开始的时候SCL与SDA都置为高电平,此时为总线空闲时间。当SCL为高电平期间SDA的电平被拉低,标志这总线的启动。当SCL为高电平期间SDA的电平被拉高,标志这总线的终止。在进行数据传送时,SCL为高电平期间,SDA上的数据必须保持稳定,只有在SCL的信号为低电平时,SDA上的高电平才允许变化。所以只要我们根据芯片手册正确的写好IIC的时序,按时序发送器件地址(不同的器件的地址不同)以及数据,就可以使主机与从机之间通信。
- I2C总线的仲裁你知道吗?
总线上可能挂接有多个器件,有时会发生两个或多个主器件同时想占用总线的情况,这种情况叫做总线竞争。I2C总线具有多主控能力,可以对发生在SDA线上的总线竞争进行仲裁,其仲裁原则是这样的:当多个主器件同时想占用总线时,如果某个主器件发送高电平,而另一个主器件发送低电平,则发送电平与此时SDA总线电平不符的那个器件将自动关闭其输出级。总线竞争的仲裁是在两个层次上进行的。首先是地址位的比较,如果主器件寻址同一个从器件,则进入数据位的比较,从而确保了竞争仲裁的可靠性。由于是利用I2C总线上的信息进行仲裁,因此不会造成信息的丢失。
- I2C时钟信号(SCL)的同步问题
在I2C总线上传送信息时的时钟同步信号是由挂接在SCL线上的所有器件的逻辑“与”完成的。SCL线上由高电平到低电平的跳变将影响到这些器件,一旦某个器件的时钟信号下跳为低电平,将使SCL线一直保持低电平,使SCL线上的所有器件开始低电平期。此时,低电平周期短的器件的时钟由低至高的跳变并不能影响SCL线的状态,于是这些器件将进入高电平等待的状态。当所有器件的时钟信号都上跳为高电平时,低电平期结束,SCL线被释放返回高电平,即所有的器件都同时开始它们的高电平期。其后,第一个结束高电平期的器件又将SCL线拉成低电平。这样就在SCL线上产生一个同步时钟。可见,时钟低电平时间由时钟低电平期最长的器件确定,而时钟高电平时间由时钟高电平期最短的器件确定。
- I2C总线的其他注意点
1、进行数据传送时,在SCL为高电平期间,SDA线上电平必须保持稳定,只有SCL为低时,才允许SDA线上电平改变状态。并且每个字节传送时都是高位在前。
2、对于应答信号,ACK=0时为有效应答位,说明从机已经成功接收到该字节,若为1则说明接受不成功。
3、如果从机需要延迟下一个数据字节开始传送的时间,可以通过把SCL电平拉低并保持来强制主机进入等待状态。
4、主机完成一次通信后还想继续占用总线在进行一次通信,而又不释放总线,就要利用重启动信号Sr。它既作为前一次数据传输的结束,又作为后一次传输的开始。
5、总线冲突时,按“低电平优先”的仲裁原则,把总线判给在数据线上先发送低电平的主器件。
6、在特殊情况下,若需禁止所有发生在I2C总线上的通信,可采用封锁或关闭总线,具体操作为在总线上的任一器件将SCL锁定在低电平即可。
7、SDA仲裁和SCL时钟同步处理过程没有先后关系,而是同时进行的。
- 对 IIC 总线的理解、调用函数以及常见面试问题
- 对IIC总线时序的一点理解以及ACK和NACK(NAK)
- IIC总线理解
- IIC总线的研究
- GPIO模拟IIC过程中对IIC的理解
- HashMap深入理解详细分析原理以及常见面试问题
- 关于单片机IIC总线的理解(附程序)
- 以C语言的方式理解IIC总线
- 关于LCD1602以及IIC总线的相关学习笔记整理
- 基于sopc的iic总线对24LC256读写操作
- 代码增进对IIC的理解
- 对“AMBA 总线”的理解
- SPI,IIc总线的区别
- 51单片机的IIC总线
- 对I2C总线时序的一点理解以及ACK和NACK(NAK)
- 对I2C总线时序的一点理解以及ACK和NACK(NAK)
- 对I2C总线时序的一点理解以及ACK和NACK(NAK)
- 对I2C总线时序的一点理解以及ACK和NACK(NAK)
- Error:Execution failed for task ':app:transformClassesWithDexForRelease'. > com.android.build.api.tr
- 交叉编译GCC for arm
- HPU2017-2016级暑期集训练习赛
- 极光推送图标遇到问题及退出极光推送帐号
- python_selenium(五)
- 对 IIC 总线的理解、调用函数以及常见面试问题
- Hadoop1.x安装:关于错误没有到主机的路由
- 魅族容器云平台自动化运维实践
- 触摸事件
- 我的安全之路——二进制与逆向篇
- SharedPreferences保存list集合
- 有关密码本小项目的一些知识点总结(二)
- 【数据库系统概念】第5章 高级SQL 知识总结
- 在已有win7系统的基础上重装win10系统