I2C(Inter-Integrated Circuit)是一种串行通信协议,用于在计算机或其他设备内部连接设备。它允许多个设备之间进行通信。他是半双工的
I2C最初是飞利浦公司于1982年为各种飞利浦芯片开发的。原始规范只允许 100kHz 通信,并且只提供 7 位地址,将总线上的设备数量限制为 112 个(有几个保留地址,永远不会用于有效的I2C地址)。1992 年,第一个公开规范发布,增加了 400kHz 快速模式以及扩展的 10 位地址空间。大多数时候(例如,在许多 Arduino 兼容板上的 ATMega328 设备中),设备对I2C的支持在此时结束。指定了三种附加模式:
除了“vanilla”I2C 之外,英特尔还在 1995 年推出了一种称为“系统管理总线”(SMBus)的变体。SMBus 是一种更严格控制的格式,旨在最大限度地提高 PC 主板上支持 IC 之间通信的可预测性。
SMBus 之间最显着的区别是它限制了从 10kHz 到 100kHz 的速度,而I2C 可以支持从 0kHz 到 5MHz 的设备。SMBus 包括一个时钟超时模式,它使低速操作成为非法,尽管许多 SMBus 设备无论如何都会支持它以最大限度地提高与嵌入式 I2C 系统的互操作性。
I2C协议的工作原理。I2C(Inter-Integrated Circuit)协议是一种电气总线(TWI)协议,主要用于在系统内部进行短距离数据传输。它的主要特点是可以在线性结构中连接多个设备,并且支持多主机和多从机。
I2C协议使用两根线SCL(时钟线)和SDA(数据线)来进行数据传输。
SCL用于传送时钟信号,SDA用于传送数据。
整个传输过程由主机驱动,在传输过程中主机会根据需要来控制SCL和SDA的电平。
I2C协议的信息传输过程,主要分为两种模式:
IIC总线在传输数据的过程中一共有三种类型信号
分别为:开始信号、结束信号和应答信号。//起始位,停止位,数据位,速度
这些信号中,起始信号是必需的,结束信号和应答信号
IIC寻址分为7、8、10位寻址方法,下面这篇文章应该可以大概介绍一下(不必较真)
http://www.toomoss.com/news/12-cn.html
消息分为两种类型的帧:一种是地址帧,其中控制器指示将消息发送到的外设,另一种是一个或多个数据帧,它们是从控制器传递到外设的 8 位数据消息,反之亦然. 数据在 SCL 变低后被放置在 SDA 线上,并在 SCL 线变高后被采样。时钟边沿和数据读/写之间的时间由总线上的设备定义,并且因芯片而异。
Start Condition:
Address Frame
在任何新的通信序列中,地址帧总是第一个。 对于 7 位地址,地址首先输出最高有效位 (MSB),然后是指示这是读 (1) 还是写 (0) 操作的 R/W 位。
帧的第 9 位是 NACK/ACK 位。 所有帧(数据或地址)都是这种情况。 一旦发送了帧的前 8 位,接收设备就获得了对 SDA 的控制权。 如果接收设备在第 9 个时钟脉冲之前没有将 SDA 线拉低,则可以推断接收设备要么没有收到数据,要么不知道如何解析消息。 在这种情况下,交换将停止,由系统的控制器决定如何进行。
Data Frames:
Stop condition:
10 位地址
在 10 位寻址系统中,需要两帧来传输外设地址。第一帧将包含代码 b11110xyz,其中“x”是外设地址的 MSB,y 是外设地址的第 8 位,z 是如上所述的读/写位。第一帧的 ACK 位将由与地址的前两位匹配的所有外设断言。
与正常的 7 位传输一样,另一个传输立即开始,并且此传输包含地址的位 7:0。此时,被寻址的外设应以 ACK 位响应。如果不是,则故障模式与 7 位系统相同。
请注意,10 位地址设备可以与 7 位地址设备共存,因为地址的前导“11110”部分不是任何有效 7 位地址的一部分。
重复启动条件
有时,重要的是允许一个控制器一次交换多个消息,而不允许总线上的其他控制器干扰。为此,定义了重复启动条件。
要执行重复启动,允许 SDA 变高,同时 SCL 为低,允许 SCL 变高,然后 SDA 再次变低,同时 SCL 为高。由于总线上没有停止条件,之前的通信并没有真正完成,电流控制器保持对总线的控制。
此时,下一条消息可以开始传输。这条新消息的语法与任何其他消息相同——地址帧后跟数据帧。允许任意次数的重复启动,并且控制器将保持对总线的控制,直到它发出停止条件。
时钟延展
有时,控制器的数据速率会超过外围设备提供该数据的能力。这可能是因为数据尚未准备好(例如,外设尚未完成模数转换)或因为先前的操作尚未完成(例如,EEPROM 尚未完成尚未写入非易失性内存,需要在它可以服务其他请求之前完成)。
在这种情况下,一些外围设备将执行所谓的“时钟延展”。名义上,所有时钟都由控制器驱动——外设简单地将数据放在总线上或从总线上取下数据以响应控制器的时钟脉冲。在数据传输过程中的任何时候,寻址外设都可以在控制器释放 SCL 线后将其保持为低电平。在外设释放 SCL 线之前,控制器需要避免额外的时钟脉冲或数据传输。
//所有函数均对应上面时序图
//晶振11.0592MHZ,1个nop=5微妙
#include
#include
sbit SDA = P1^0;
sbit SCL = P1^1;
//IIC开始信号
void IIC_Start()
{
SCL = 1;
SDA = 1;
_nop_();
SDA = 0;
_nop_();
SCL = 0;
}
//IIC结束信号
void IIC_Stop()
{
SCL = 1;
SDA = 0;
_nop_();
SDA = 1;
_nop_();
SDA = 0;
}
//IIC答应信号
char IIC_Ask()
{
char flag;
SDA = 1;//脉冲9释放数据线
_nop_();
SCL = 1;
_nop_();
flag = SCL;
_nop_();
SCL = 0;
_nop_();
return flag;
}
//IIC发送一位字符信号
void IIC_Send_Byte(char byte)
{
int i = 0;
for(i = 0;i<8;i++){
SCL = 0;
SDA = byte & 0x80;
_nop_();
SCL = 1;
_nop_();
SCL = 0;
byte = byte << 1;
}
}
理解了I2C协议的工作原理就是可以开始在51单片机上实现I2C通信了。下一步是在单片机中实现I2C通信的硬件部分,通常包括设置SCL和SDA的端口,使用定时器或计数器来生成时钟信号,以及在单片机中编写I2C驱动程序。
……后续另外发一篇文章,太长了。完事补链接。
链接如下:
https://blog.csdn.net/qq_52749711/article/details/128806653?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22128806653%22%2C%22source%22%3A%22qq_52749711%22%7D
如果对你有帮助,点赞支持一下把。
转载联系作者。