I2C是一种串行总线协议。 目前几种常用的串行总线有UART、SPI和I2C协议。UART协议的总线只有两条,发送(Transmit:TX)和接收(Receive:RX),没有时钟信号,这就要求两位数据的间隔要相同,它传送数据有严格的规定,每个数据以相同的位串形式传送,每个位串由起始位、数据位、奇偶位校验和停止位组成。SPI有三线和四线模式,四条总线分别为SCLK(时钟)、MISO(主器件数据输入,从器件数据输出)、MOSI(主器件数据输出,从器件数据输入)、SS(从器件使能信号),SPI总线由主机提供时钟,为同步通信,有两条总线进行数据传输,可以同时进行收发数据,为双工模式。三线不包含SS信号,其相应的数据传输,根据时钟极性和时钟相位的不同有四种情况,其传送数据的格式则与I2C基本类似。I2C总线只有两条,SDA(数据传输)、SCL(时钟),需要双向IO口支持,而且需要上拉电阻的协助,因此狂干扰能力弱,通常用于同一板子上芯片间的通信。
硬件结构:每一个I2C总线器件内部的SDA,SCL引脚结构一样,引脚的输出驱动与输入脉冲连在一起,输出为漏极开路的场效应管,输入为一只高输入阻抗的同相器。SCL和SDK借助上拉电阻行成“线与”关系,引脚在输出信号的同时还将引脚上的电平,检测是否与刚才输出一致。为“时钟同步”和“总线仲裁”提供硬件基础。时间同步的实现:可以在应答信号后使SCL延长低电平时间的方法来通知主机。SCL线上的低电平时间是由时钟低电平最长的器件决定;高电平时间是由时钟高电平最短的器件决定。从而实现时钟同步。
数据传输:主机发送数据传输流程:主机检测到总线处于空闲状态,发送启动信号S(数据线电平由低电平变为高电平);主机发送一个命令字节,该命令字节由7位的外围器件地址和1位读/写控制位(R/W=0);相应的从机收到命令字节后,向主机发送应答信号ACK=0(数据线上为低电平);主机收到从机的应答信号后开始发送下一个数据字节;当主机发送最后一个数据字节并收到从机的ACK时,通过向从机发送一个停止信号P(数据线电平由低电平变为高电平)结束本次通信并释放总线。从机收到信号P后也退出通信。
主机接收数据流程:主机发送启动信号,接着发送命令字节(R/W=1);对应的从机收到地址字节后,返回一个应答信号并向主机发送数据;主机收到数据后向从机反馈一个应答信号;从机收到应答信号后再向主机发送一个数据;主机完成接收数据后,向从机发送一个非应答信号(ACK=1),从机收到应答信号后,便不再发送数据;主机 发送应答信号后,发送一个停止信号,释放总线结束通信。Tips:主机所接收的数量由主机自身决定,发送非应答信号的作用:前一个数据接收成功;停止从机的再次发送。
以一个实例(开发板为EP2C8-2010)分析了解I2C协议基本功能:该例实现通过I2C总线对EEPROM(电可擦可编程只读存储器,掉点后数据不丢失在专用的设备商可擦除)的读写,重点在于对I2C总线协议时序的掌握,即用I2C总线要求的格式将输入写入之后读出。为实现该功能,完成两个器件间的通信,我们需要一个主机和从机,设计实例中的signal模块和EEPROM_WR模块模拟主机,EEPROM模块模拟从机。当写入数据时,EEPROM_WR模块从signal模块调取数据,通过I2C总线向EEPROM写数据。当读出数据时,EEROM_WR仍然通过SDA和SCL总线读出EEPROM中的数据,再输入给signal模块。开发板存在EEPROM器件,而signal模块可以通过创建IP核(基于ram)来实现,因此只有EEPROM_WR模块是要写入FPGA中的可综合模块,而signal模块和EEPROM模块都是 仿真模块。
每个正在接收数据的从机EEPROM在接到一个字节的数据后,通常需要发出一个应答信号。而每个正在发送数据的从机EEPROM在发出一个字节的数据后,通常需要接收一个应答信号。EEPROM读写控制器必须产生一个与这个应答位相联系的额外的时钟脉冲。在EEPROM读写控制器对EEPROM完成的最后一个字节产生一个高的应答位,这叫做非应答信号,随后给EEPROM一个结束信号。
由于开发板EP2C8-2010开发板采用的EEPROM是AT24C02,所以EEPROM_WR模块的编写应该满足AT24C02的写入和读取。如下图所示是AT24C02字节写入帧格式,第一位是启动信号,第2位到第8位是控制字节(从机地址:第2-5位是1010,6-8位是页地址),第9位是写操作(W/R置零),第10位是从机EEPROM给的应答信号0,第11-18位是存储单元地址,19位是应答信号0,第20-27位是写入的数据,第28位是应答信号,29号主机发送停止信号P。
而与之相对应的字节读取格式也大同小异,先写入控制字节和存储地址,然后是启动信号与控制字节信号,这时控制字节第八位(W/R置1),读取数据,完成读取时,主机将SDA拉高作为非应答信号,最后是停止位。