关注👆 望森FPGA 👆 查看更多FPGA资讯
这是望森的第 31 期分享
作者 | 望森
来源 | 望森FPGA
目录
[1 I²C 总线简介](#1 I²C 总线简介)
[2 I²C 总线特点](#2 I²C 总线特点)
[3 I²C 总线速度](#3 I²C 总线速度)
[4 I²C 总线协议](#4 I²C 总线协议)
[I²C 读写时序](#I²C 读写时序)
摘要
本文将从简介、特点、速度、协议等几个重要方面为大家介绍 I²C 总线,其中最重要的是 I²C 总线协议的部分。
1 I²C 总线简介
I²C(Inter-Integrated Circuit)是I²C Bus简称,叫集成电路总线。
I²C 是一种简单、双向、二线制串行通信总线,使用多主从架构。
I²C 的来历:
1980年代,飞利浦公司为了让主板、嵌入式系统或手机能够以极为简便的方式连接周边的低速设备,发明了I²C 。
I²C 多用于主机和从机在数据量不大且传输距离短的场合下的主从通信。
主机启动总线,并产生时钟用于传送数据,此时任何接收数据的器件均被认为是从机。
I²C的正确读法为"I平方C"("I-squared-C"),而"I二C"("I-two-C")则是另一种错误但被广泛使用的读法。
2 I²C 总线特点
I²C 总线的主要特性包括:
-
仅需两条总线线路:串行数据线(SDA)和串行时钟线(SCL)。
-
连接到总线的每个设备都有唯一的地址,并在任何时候都可以建立简单的控制器/目标关系;
控制器可以作为控制器-发送器或控制器-接收器工作。
-
I²C 具有冲突检测和仲裁功能,能防止两个或多个控制器同时发起数据传输时的数据损坏情况。
-
可以实现串行、8位定向的双向数据传输。
-
标准模式下速率最高可达100 kbit/s,
快速模式可达400 kbit/s,
快速模式增强版可达1 Mbit/s,
高速模式可达3.4 Mbit/s。
-
在超快速模式下,支持最高5 Mbit/s的串行、8位定向单向数据传输。
-
可以连接到同一总线的控制器数量仅受限于最大总线电容,在某些条件下允许更大的电容。
3 I²C 总线速度
I²C规范五种操作速度类别如下:
-
双向总线:
-
标准模式(Sm):最高速率为100 kbit/s
-
快速模式(Fm):最高速率为400 kbit/s
-
快速模式增强版(Fm+):最高速率为1 Mbit/s
-
高速模式(Hs-mode):最高速率为3.4 Mbit/s
-
-
单向总线:
- 超快速模式(UFm):最高速率为5 Mbit/s
标准模式、快速模式(Fm)、快速模式增强版(Fm+)和高速模式(Hs-mode)设备均向下兼容,可以在较低总线速度下运行。
超快速模式(UFm)设备则不兼容先前的版本,因为其总线为单向传
4 I²C总线协议
标准模式、快速模式和快速模式增强版的I²C总线协议
每个设备都有一个唯一的地址,并根据设备的功能充当发送器 或接收器。
例如,LCD驱动器可能只作为接收器,而存储器可以既接收又发送数据。
除了发送器和接收器,设备在数据传输时还可以是控制器 或目标设备(详见表2)。
控制器是发起数据传输并生成传输时钟信号的设备,此时被寻址的任何设备都视为目标设备。
I²C总线是一个多控制器总线,这意味着可以连接多个具有控制总线能力的设备。
控制器通常是微控制器/单片机,以下是两个连接到I²C总线的微控制器之间的数据传输示例(参见图2)。
此示例展示了I²C总线上的控制器-目标和接收器-发送器关系。
数据传输过程如下:
-
假设微控制器A要向微控制器B发送信息:
-
微控制器A(控制器)寻址微控制器B(目标设备)
-
微控制器A(控制器-发送器)向微控制器B(目标-接收器)发送数据
-
微控制器A 终止传输。
-
-
如果微控制器A要从微控制器B接收信息:
-
微控制器A(控制器)寻址微控制器B(目标设备)
-
微控制器A(控制器-接收器)从微控制器B(目标-发送器)接收数据
-
微控制器A 终止传输。
-
在此过程中,控制器(微控制器A)负责生成时钟并终止传输。
注意:本文仅介绍一个控制器-发送器和一个接收器-目标的I²C总线使用说明,时钟同步、仲裁等更详细的内容请查阅恩智浦NXP公司的I²C总线标准文件。如果您需要的话,可以关注公众号【望森FPGA】,回复"I2C"领取。
I²C总线上能够连接多个微控制器,意味着多个控制器可能同时尝试发起数据传输。
为避免由此引发的混乱,开发了一种仲裁机制。
该机制依赖于所有I²C接口与I²C总线的有线与连接(wired-AND)。
如果两个或多个控制器尝试向总线发送信息,当一个控制器产生'1'而另一个产生'0'时,'1'的发送者将丢失仲裁。
仲裁过程中时钟信号是由多个控制器通过有线与连接同步生成的。
在I²C总线上生成时钟信号始终是控制器设备的任务;
SDA 和 SCL 信号
SDA和SCL都是双向线,通过电流源或上拉电阻连接到正电源(见图3)。
当总线空闲时,这两条线均处于高电平。
连接到总线的设备的输出级必须是开漏或开集电极结构,以实现有线与功能。
总线的电容限制了连接到总线的接口数量。
数据有效性
在SDA线上的数据在时钟高电平期间必须保持稳定。
只有当SCL线上的时钟信号处于低电平时,数据线的高或低状态才能改变(见图4)。
每传输一个数据位生成一个时钟脉冲。
起始和停止条件
所有传输都以起始条件(START,S)开始,并以停止条件(STOP,P)结束(见图5)。
当SCL为高电平时,SDA线上出现高到低的跳变定义为起始条件;
当SCL为高电平时,SDA线上出现低到高的跳变定义为停止条件。
起始和停止条件始终由控制器生成。
起始条件后总线视为繁忙状态。
停止条件后的一段时间内,总线再次视为空闲状态。
如果生成了重复起始(Sr)而不是停止条件,总线将继续保持繁忙状态。
在功能上,起始(S)和重复起始(Sr)条件是相同的。
因此,在本文档的剩余部分中,S符号用作代表起始和重复起始条件的通用术语。
字节格式
在SDA线上发送的每个字节都必须为八位长。
每次传输的数据字节数量没有限制。
每个字节必须由一个确认(Acknowledge)位跟随。
数据以最高有效位(the Most Significant Bit,MSB)优先的格式传输(见图6)。
如果目标设备在接收或发送下一个完整字节前需要执行其他操作(例如服务内部中断),它可以将SCL线拉低,使控制器进入等待状态。
当目标设备准备好接收下一个字节并释放SCL线时,数据传输将继续。
I²C 读写时序
主机发送完字地址,从机正确应答后就把内部的存储单元地址指针指向该单元。
如果读写控制位 R/W 位为"0"即写命令,从机就处于接收数据的状态,此时,主机就开始写数据了。
写数据可分为单次写和连续写,下面我们分别介绍。
单次写
单次写的时序如下图所示:
参照时序图,单次写操作流程如下:
(1)主机产生并发送起始信号到从机,并且将写控制命令发送给从机设备。
读写控制位设置为低电平,表示对从机进行写数据操作。
注意:写控制命令的发送是高位在前低位在后;
(2)从机接收到写控制指令后,回传应答信号。
如果从机没有应答则会输出 I²C 通信错误信号;
如果主机接收到应答信号,就开始字地址的写入。
根据器件类型,我们需要先判断使用的器件是单字节地址还是双字节地址。
若为双字节地址:
先向从机写入高 8 位地址,且高位在前低位在后;
待接收到从机回传的应答信号,再写入低 8 位地址,且高位在前低位在后;
双字节字地址写入完成后执行步骤(4)。
若为单字节地址:
跳转到步骤(3)。
(3)按高位在前低位在后的顺序写入单字节存储地址;
单字节字地址写入完成后执行步骤(4);
(4)字地址写入完成。
主机接收到从机回传的应答信号后,开始单字节数据的写入;
(5)单字节数据写入完成。
主机接收到应答信号后,向从机发送停止信号,单次写(字节写)完成。
连续写
连续写的时序如下图所示:
参照时序图,连续写操作流程如下:
(1)主机产生并发送起始信号到从机,并且将写控制命令发送给从机设备。
读写控制位设置为低电平,表示对从机进行写数据操作。
注意:写控制命令的发送是高位在前低位在后;
(2)从机接收到写控制指令后,回传应答信号。
如果从机非应答:则会输出 I2C 通信错误信号。
如果主机接收到从机应答信号:开始字地址的写入。
根据器件类型,我们需要先判断使用的器件是单字节地址还是双字节地址。
若为双字节地址:
先向从机写入高 8 位地址,且高位在前低位在后;
待接收到从机回传的应答信号,再写入低 8 位地址,且高位在前低位在后;
双字节字地址写入完成后执行步骤(4)。
若为单字节地址:
跳转到步骤(3);
(3)按高位在前低位在后的顺序写入单字节存储地址,单字节字地址写入完成后执行步骤(4);
(4)地址写入完成。
主机接收到从机回传的应答信号后,开始第一个单字节数据的写入。
(5)数据写入完成。
主机接收到从机回传应答信号后,开始下一个单字节数据的写入。
(6)直到所有数据写入完成,主机接收到从机回传应答信号后,执行步骤(7)。
若数据未完成写入,跳回到步骤(5);
(7)主机向从机发送停止信号,连续写操作完成。
我们总结下单次写与连续写的区别。
两者的区别在于:
发送完一字节数据后,是发送结束信号还是继续发送下一字节数据。
如果发送的是结束信号,就称为单次写;
如果继续发送下一字节数据,就称为连续写。
注意:所有 I²C 设备均支持单字节数据写入操作,但只有部分 I²C 设备支持连续写操作。
接下来我们开始 I²C 读时序部分的介绍。
根据一次读操作读取数据量的多少,读操作可分为随机读操作和顺序读操作。
在发送控制命令时,如果读写控制位 R/W 位为"1"即读命令,主机就处于接收数据的状态,从机从该地址单元输出数据。
读数据有三种方式:
当前地址读、随机读和连续读。
当前地址读
当前地址读是指在一次读或写操作后发起读操作。
由于 I²C 器件在读写操作后,其内部的地址指针自动加一,因此当前地址读可以读取下一个字地址的数据。
也就是说,上次读或写操作的单元地址为 02 时,当前地址读的内容就是地址 03 处的单元数据。
当前地址读时序图如下所示:
参照时序图,当前地址读操作流程如下:
(1)主机产生并发送起始信号到从机,并且将读控制命令发送给从机设备。
读写控制位设置为高电平,表示对从机进行读数据操作。
注意:读控制命令的发送是高位在前低位在后;
(2)从机接收到读控制指令后:
如果回传非应答信号,则会输出 I2C 通信错误信号;
如果回传应答信号,主机接收到从机回传的应答信号后,开始接收从机传回的单字节数据。
(3)数据接收完成后,主机产生一个时钟的高电平无应答信号;
(4)主机向从机发送停止信号,当前地址读操作完成。
随机地址读
由于当前地址读极不方便读取任意的地址单元的数据,所以就有了随机读。
随机地址读的时序有点奇怪,如下所示:
参照时序图,随机地址读操作流程如下:
(1)主机产生并发送起始信号到从机,并且将写控制命令发送给从机设备。
读写控制位设置为低电平,表示对从机进行写数据操作。
注意:写控制命令的发送是高位在前低位在后。
(2)从机接收到写控制指令后:
如果回传非应答信号,则会输出 I²C 通信错误信号;
如果回传应答信号,主机接收到应答信号后开始字地址的写入。
根据器件类型,我们需要先判断使用的器件是单字节地址还是双字节地址。
若为双字节地址:
先向从机写入高 8 位地址,且高位在前低位在后;
待接收到从机回传的应答信号,再写入低 8 位地址,且高位在前低位在后。
双字节字地址写入完成后执行步骤(4);
若为单字节地址:
跳转到步骤(3)。
(3)按高位在前低位在后的顺序写入单字节存储地址。
单字节字地址写入完成后执行步骤(4)。
(4)字地址写入完成。
主机接收到从机回传的应答信号后,主机再次向从机发送一个起始信号;
(5)主机向从机发送读控制命令。
读写控制位设置为高电平,表示对从机进行数据读操作;
(6)主机接收到从机回传的应答信号后,开始接收从机传回的单字节数据;
(7)数据接收完成后,主机产生一个时钟的高电平无应答信号;
(8)主机向从机发送停止信号,单字节读操作完成。
至此随机地址读时序的操作步骤介绍完成。
需要注意理解的是:
随机地址读在发送完器件地址和字地址后,竟然又发送起始信号和器件地址;
而且第一次发送器件地址时后面的读写控制位为"0",也就是写命令;
第二次发送器件地址时后面的读写控制位为"1",也就是读。
为什么会有这样奇怪的操作呢?
因为我们需要让从机的存储单元地址指针指向我们想要读取的存储单元地址处,
所以首先发送了一次 Dummy Write 也就是虚写操作。
之所以称为虚写,
是因为我们并不是真的要写数据,而是通过这种虚写操作使地址指针指向虚写操作中字地址的位置;
等从机应答后,就可以以当前地址读的方式读数据了。
因此,随机地址读是没有发送数据的单次写操作和当前地址读操作的结合体。
连续读
当前地址读和随机读都是一次读取一个字节;
连续读是将当前地址读或随机读的主机非应答改成应答,表示继续读取数据。
当前地址连续读
当前地址连续读的时序如下图所示:
(1)主机产生并发送起始信号到从机,并且将读控制命令发送给从机设备。
读写控制位设置为高电平,表示对从机进行读数据操作。
注意:读控制命令的发送是高位在前低位在后;
(2)从机接收到读控制指令后。
如果回传非应答信号,则会输出 I²C 通信错误信号;
如果回传应答信号,主机接收到从机回传的应答信号后,开始接收从机传回的单字节数据;
(3)数据接收完成后。
主机产生应答信号回传给从机,从机接收到应答信号开始下一字节数据的传输。
若数据传输完成,主机产生非应答信号回传给从机,执行步骤(4);
若数据传输未完成,再次执行步骤(3);
(4)主机向从机发送停止信号,当前地址连续读时序操作完成。
随机地址连续读
随机地址连续读是在随机地址读时序的基础上,主机非应答改成应答,表示继续读取数据。
随机地址连续读的时序如下图所示:
参照时序图,随机地址连续读操作流程如下:
(1)主机产生并发送起始信号到从机,并且将写控制命令发送给从机设备。
读写控制位设置为低电平,表示对从机进行写数据操作。
注意:写控制命令的发送是高位在前低位在后;
(2)从机接收到写控制指令后。
如果回传非应答信号,则会输出 I²C 通信错误信号;
如果回传应答信号,主机接收到应答信号后开始字地址的写入。
根据器件类型,我们需要先判断使用的器件是单字节地址还是双字节地址。
若为双字节地址:
先向从机写入高 8 位地址,且高位在前低位在后;
待接收到从机回传的应答信号,再写入低 8 位地址,且高位在前低位在后。
双字节字地址写入完成后执行步骤(4);
若为单字节地址:
跳转到步骤(3);
(3)按高位在前低位在后的顺序,写入单字节存储地址。
单字节字地址写入完成后执行步骤(4);
(4)字地址写入完成。
主机接收到从机回传的应答信号后,主机再次向从机发送一个起始信号;
(5)主机向从机发送读控制命令。
读写控制位设置为高电平,表示对从机进行数据读操作;
(6)主机接收到从机回传的应答信号后,开始接收从机传回的单字节数据;
(7)数据接收完成后。
若数据传输完成:
主机产生非应答信号回传给从机,执行操作步骤(8);
若数据传输未完成:
主机产生应答信号回传给从机,从机接收到应答信号开始下一字节数据的传输,并再次执行步骤(7);
(8)主机向从机发送停止信号,随机地址连续读时序操作完成。
总结
本文介绍的I²C 读写时序简单总结如下图所示:
参考文献
[1] 正点原子 达芬奇Pro之FPGA开发指南;
[2] NXP恩智浦 UM10204 I2C-bus specification and user manual
如果您需要的话,可以关注公众号【望森FPGA】,回复"I2C"领取。
- END -
公z号/CSDN/知乎搜索【望森FPGA】,查看更多FPGA资讯~
相关推荐文章,点击跳转:
📌 作者能力有限,欢迎大家在评论区批评指正或提出宝贵建议
📌 希望文章内容能对您有所帮助,欢迎多多点赞、评论、收藏与分享,您的支持是对我最大的鼓励
📌 很荣幸能在有限的时间里和大家一同成长