一种带DMA 功能的I/O 可配置I2C 总线接口的设计
2023-12-04强小燕王嘉瑶邢梦菲
强小燕,王嘉瑶,邢梦菲
(1.中国电子科技集团公司第五十八研究所,江苏 无锡 214072;2.西安电子科技大学杭州研究院,浙江 杭州 311231)
0 引言
内置集成电路(Inter-Intergrated Circuit,I2C)总线作为一种简单、高效的二线制双向串行传输总线,在电子器件及系统中应用非常普遍,其严格的通信规范保证了数据传输的可靠性[1]。如果设计人员在设计中优先考虑成本效益和更简单的设计,那么I2C 就可以达到目的,同时确保更高的速度。I2C 的使用可以有多个设备充当主设备,并且可以在不更改接线的情况下在主设备和从设备之间切换设备。在某些情况下,为了使CPU 更加专注于计算控制等操作时,可以使用DMA 来进行实现数据的直接传输,去掉传统数据传输需要CPU 参与的环节[2-3]。I2C 作为一种外设,支持DMA 的访问显得尤为重要。此外,在使用MCU 时,有时候会遇到接口不够用的情况,考虑到这种情况下提高I2C 接口的使用率,可以使I2C 接口模块的每个引脚根据需求编程为I2C 引脚或通用输入输出引脚。因此,在本文中,扩展I2C 总线接口的功能,使其具有DMA 功能和I/O 可配置功能。
本文首先简要介绍I2C 总线协议与I2C 总线接口的基本原理,然后着重介绍实现带DMA 功能的I/O 可配置I2C 总线接口的总体结构和各个功能的实现,最后给出了仿真分析的结果。
1 I2C 总线的基本原理
I2C 总线协议的时序图如图1 所示,协议规定:当总线处于非忙状态时,即数据线(SDA)和时钟线(SCL)都保持高电平,数据才能开始传输;当时SCL 为高电平,SDA 从高电平变为低电平,此时视为产生起始位;在产生起始位后,在SCL 为高电平期间SDA 保持不变,在SCL 为低电平期间SDA 上的数据才能发生改变,因此每位数据会占用一个时钟脉冲;在SCL 经过8 个时钟周期后的第9 个时钟脉冲时,接收器会向发送器发送一个应答信号;与起始位相反的是,停止位的产生是在SCL 为高电平期间,SDA 从低电平变为高电平[4]。
图1 I2C 总线协议时序图
I2C 接口可以工作在主发送器、主接收器、从发送器、从接收器这四种模式之一。在默认情况下以从模式工作,接口在生成起始位后,会自动由从模式切换为主模式,并在出现仲裁丢失或是产生停止位时从主模式切换为从模式,从而实现多主模式功能。在主模式下,I2C接口会启动数据传输并产生时钟信号。在从模式下,I2C 接口能够识别其自身的7 位或10 位地址以及广播呼叫地址。在产生起始位后,紧随其后会传输地址字节,7位地址占据一个字节,10 位地址占据两个字节。在传输期间,数据和地址均以8 位字节传输,MSB 在前。
7 位地址格式的传输序列图如图2 所示,起始位后的第一个字节由一个7 位的从地址和一个读/写位组成,读/写位决定数据包传输的方向。
图2 7 位地址格式传输序列图
10 位地址格式的传输序列图如图3 所示,与7 位地址格式类似,但是主机是通过两次单独的字节传输发送的从机地址,并且从机必须在两次字节传输后均发送应答信号。
图3 10 位地址格式传输序列图
2 I2C 模块简介
2.1 I2C 总体结构
I2C 总线接口用作微控制器和I2C 串行总线之间的接口。它提供多主模式功能,可以控制所有I2C 总线特定的序列、协议、仲裁和时序。多个I2C 串行端口之间的连接如图4 所示,可以用于从一个设备到另一个设备的双向传输。
图4 多个I2C 模块连接图
如图5 所示,可以将单个I2C 模块分为以下模块组成:
图5 单个I2C 模块结构图
接口:由一个SDA 数据引脚和一个SCL 时钟引脚组成的串行接口。
数据控制:用于临时保存在SDA 引脚和中央处理器或直接存储器存取之间传输的接收和发送数据的数据控制模块。
仲裁器:当I2C 模块配置为主模块时,仲裁器用于处理I2C 模块和另一个主模块之间的仲裁。
时钟同步器:用于同步来自系统模块的的I2C 输入时钟和SCL 引脚上的时钟,并与不同时钟速度的主机同步数据传输。
控制逻辑:通过状态机实现I2C 通信协议,实现将中断发送到中央处理器的中断生成逻辑,以及I2C 模块中用于同步DMA 传输的数据接收和数据传输,即具有DMA 功能。
时钟控制:用于对驱动至I2C 模块的外设时钟进行分频,产生模块时钟和主时钟。
引脚控制:当不需要I2C 功能时,控制其SDA 数据引脚和SCL 时钟引脚可以用作通用输入/输出引脚(GPIO),即具有I/O 可配置功能。
2.2 DMA 功能与实现
直接存储访问(Direct Memory Access,DMA)用于在外设与存储器之间、外设与外设之间以及存储器和存储器之间提供高速的数据传输。它可以在不需要任何CPU 操作的情况下通过DMA 快速地移动数据。这样一来,节省出来的CPU 资源就可以用来执行其他操作。因此根据器件的不同,可以给I2C 模块增加DMA 功能,并利用DMA 功能来减轻MCU 的工作量。
具体的实现方法是:当I2C 模块作为发送器时,向DMA 模块发出发送请求,并使能DMA 模式进行发送,使用DMA 控制器从数据发送寄存器中读取数据,与此同时将数据写入数据缓冲寄存器中;当I2C 模块作为接收器时,向DMA 模块发出接受请求,并使能DMA 模式进行接收,使用DMA 控制器从数据接收寄存器中同步读取接收数据,与此同时将接收到的数据写入数据缓冲寄存器中。
2.3 I/O 可配置功能与实现
当不适用I2C 模块时,I2C 的两个引脚SCL 引脚和SDA 引脚可以通过编程配置为通用输入或通用输出引脚。即该接口模块的每个引脚可以根据需求编程为I2C引脚或通用输入输出引脚。
此外,当I2C 引脚配置为输出引脚时,可以对其进行编程,使其具有开漏功能。当开漏功能被使能时,写入数据输出寄存器的低值(0)会迫使引脚处于低输出电压(VOL 或更低),而写入数据输出寄存器的高值(1)会迫使引脚处于高阻状态。
具体的实现方式是:通过I2C 管脚功能寄存器控制SDA 数据引脚和SCL 时钟引脚是作为I2C 引脚还是作为输入/输出引脚;当I2C 管脚功能为输入/输出引脚时,通过I2C 管脚方向寄存器决定I2C 的每个引脚是作为输入还是输出;数据传输期间,通过设有一个I2C 数据输入寄存器和一个I2C 数据输出寄存器,分别反映SDA 和SCL引脚上的输入输出值,还可以通过I2C 数据清除寄存器对SDA 和SCL 的GPIO 引脚进行串行数据清除;此外,可以用I2C 引脚开漏寄存器、I2C 拉功能寄存器和I2C 拉选择寄存器分别进行开漏使能/禁止、拉功能使能/禁止和上拉/下来选择。
3 仿真分析
本文采用Linux 平台上的NCVerilog 和Verdi 仿真工具联合对该设计的带DMA 功能的I/O 可配置I2C 总线接口进行仿真验证与分析[5-7]。仿真结果如图6~图8所示。
图6 I2C 主发送从接收模式下的DMA 功能仿真图
为了充分验证I2C 接口在四种工作模式下DMA 功能的正确性,如图6 所示,验证设计的两个I2C 模块分别工作在主发送模式和从接收模式下DMA 功能的正确性;以及如图7 所示,验证两个I2C 模块分别工作在主接收模式和从发送模式下DMA 功能的正确性。两个仿真均是利用DMA 将10 到19 十个数据搬运到工作在发送模式的I2C,其再将数据传输给工作在接收模式的I2C,再由DMA 从I2C 搬运到预置的数据存储空间。如图8所示,验证了I2C 的I/O 可配置功能,当I2C 模块的两个接口均输出高电平时,打开开漏使能的端口不能输出高电平,但低电平可以正常输出。
图7 I2C 主接收从发送模式下的DMA 功能仿真图
图8 I/O 可配置功能仿真图
4 结论
本文设计并实现了一种带DMA 功能的I/O 可配置I2C 总线接口,在I2C 总线接口的功能上增加了DMA 功能和I/O 可配置功能。利用了DMA 快速移动数据,可以节省CPU 资源来执行其他操作的优势,来减轻MCU 的工作量。此外,该I2C 接口模块的每个引脚可以根据需求编程为I2C 引脚或通用输入输出引脚,广泛地增加了该模块的适用范围。通过仿真验证分析可知,该设计实现了预期的功能,可以应用在多数MCU 中。