I2C总线串口读写EEPROM

1.原理介绍

I2C总线在近年来微电子通信控制领域广泛采用的一种新型的总线标准,他是同步通信的一种特殊方式,具有接口少,控制简单,器件封装形式小,通信速率高等优点。
在主从通信中,可以有多个I2C总线器件同时接到I2C总线上,所有与I2C兼容的器件都有标准的接口,通过地址来识别通信对象,使他们可以经由I2C总线互相直接通信。
I2C总线由两条线控制,一条时钟线SCL,一条数据线SDA。

I2C 总线( I2C bus, Inter-IC bus)是一个双向的两线连续总线,提供集成电路( ICs)之间的通信线路。 I2C 总线是一种串行扩展技术,最早由 Philips 公司推出,广泛应用于电视,录像机和音频设备。 I2C 总线的意思是“完成集成电路或功能单元之间信息交换的规范或协议”。 I2C 总线采用一条数据线( SDA),加一条时钟线( SCL)来完成数据的传输及外围器件的扩展。
I2C总线串口读写EEPROM_第1张图片
I2C 总线在物理连接上比较简单,分别由 SDA(串行数据线)和 SCL(串行时钟线)两条总线及上拉电阻组成。通信的原理是通过控制 SCL 和 SDA 的时序,使其满足 I2C 的总线协议从而进行数据的传输。

I2C 总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址(可以从 I2C 器件数据手册得知),主从设备之间就是通过这个地址来确定与哪个器件进行通信。本次实验我们把 FPGA 作为主设备,把挂载在总线上的其他设备(如 EEPROM、 PFC8563 等 I2C 器件)作为从设备。I2C 总线上的主设备与从设备之间以字节(8 位)为单位进行双向的数据传输。

2.I2C协议整体时序

I2C总线串口读写EEPROM_第2张图片
I2C 协议整体时序说明如下:
总线空闲状态: SDA 为高电平, SCL 为高电平;
I2C 协议起始位: SCL 为高电平时, SDA 出现下降沿,产生一个起始位;
I2C 协议结束位: SCL 为高电平时, SDA 出现上升沿,产生一个结束位;
I2C 读写数据状态:主要包括数据的串行输出输入和数据接收方对数据发送方的响应信号
I2C总线串口读写EEPROM_第3张图片
当 I2C 主机(后面简称主机)向 I2C 从机(后面简称从机) 写入数据时,SDA 上的每一位数据在 SCL 的高电平期间被写入从机中。从主机角度来看,需要在 SCL 低电平期间改变要写入的数据。
而当主机读取从机中数据时,从机在SCL 低电平期间将数据输出到 SDA 总线上,在 SCL 的高电平期间保持数据稳定,从主机角度来看,需要在 SCL 的高电平期间将 SDA 线上的数据读取并存储。

每当一个字节的数据或命令传输完成时,数据接收方都会向发送方响应一位应答位ACK。在响应应答位时,数据发出方将 SDA 总线设置为三态输入,由于 I2C总线上都有上拉电阻,因此此时总线默认为高电平,若数据接收方正确接收到数据,则数据接收方将 SDA 总线拉低,以示正确应答。
例如当主机向从机写入数据或命令时,每个字节都需要从机产生应答信号以告诉主机此次的数据或命令是否成功被写入。所以,当主机将一字节的数据或命令传出后,会将 SDA 信号设置为三态输入(高电平),等待从机应答(等待 SDA 被从机拉低为低电平),若从机正确应答,表明当前数据或命令传输成功,可以结束或开始下一个数据或命令的传输,否则表明数据或命令写入失败,主机就可以决定是否放弃写入或者重新发起写入

3. 器件地址(控制字设置)

每个 I2C 器件都有一个器件地址,有的器件地址在出厂时地址就设置好了,用户不可以更改(例如 OV7670 器件地址为固定的 0x42),有的确定了几位,剩下几位由硬件确定(比如常见的 I2C 接口的 EEPROM 存储器,留有 3 个控制地址的引脚,由用户自己在硬件设计时确定)。

严格讲,主机不是直接向从机发送地址,而是主机往总线上发送地址,所有的从机都能接收到主机发出的地址,然后每个从机都将主机发出的地址与自己的地址比较,如果匹配上了,这个从机就会向总线发出一个响应信号。主机收到响应信号后,开始向总线上发送数据,与这个从机的通讯就建立起来了。如果主机没有收到响应信号,则表示寻址失败。

通常情况下,主从器件的角色是确定的,也就是说从机一直工作在从机模式。

I2C 协议在进行数据传输时,主机需要首先向总线上发出控制命令,其中,控制命令就包含了从机器件地址和读写控制,然后等待从机响应。如图 1.4 所示为 I2C 控制命令传输的数据格式

I2C总线串口读写EEPROM_第4张图片

I2C 传输时,按照从高到低的位序进行传输。控制字节的最低位为读写控制位
当该位为 0 时表示主机对从机进行写操作,当该位为 1 时表示主机对从机进行读操作。
例如,当需要对片选地址为 3’b100 的 AT24LC64 发起写操作,则控制字节应该为 1010_100_0.
若进行读操作,则控制字节应该为1010_100_1.

4.存储单元地址

每个支持 I2C 协议的器件,内部总会有一些可供读写的寄存器或存储器,例如, EEPROM 存储器,内部就是顺序编址的一系列存储单元;型号为的 CMOS 摄像头( OV7670 的该接口叫 SCCB 接口,其实质也是一种特殊的 I2C协议,可以直接兼容 I2C 协议),其内部就是一系列编址的可供读写的寄存器。
因此,我们要对一个器件中的存储单元(寄存器和存储器,以下简称存储单元)
进行读写,就必须要能够指定存储单元的地址。 I2C 协议设计了有从机存储单元寻址地址段,该地址段为一个字节或两个字节长度,在主机确认收到从机返回的控制字节响应后由主机发出。地址段长度视不同的器件类型,长度不同,例如同是 EEPROM 存储器, AT24C04 的址段长度为一个字节,而 AT24C64 的地址段长度为两个字节。具体是一个字节还是两个字节,与器件的存储单元数量有关。如图 30.5 和图 30.6 分别为 1 字节地址和 2 字节地址器件的地址分布图,其中 1 字节地址的器件是以内存为 1kbit 的 EEPROM 存储器 AT24C01 举例, 2 字节地址的器件是以内存为 64kbit 的 EEPROM 存储器 AT24C64 举例的。I2C总线串口读写EEPROM_第5张图片

5. 单字节写时序

I2C总线串口读写EEPROM_第6张图片

  1. 主机设置 SDA 为输出;
  2. 主机发起起始信号;
  3. 主机传输器件地址字节,其中最低位为 0,表明为写操作;
  4. 主机设置 SDA 为三态门输入,读取从机应答信号;
  5. 读取应答信号成功,主机设置 SDA 为输出,传输 1 字节地址数据;
  6. 主机设置 SDA 为三态门输入,读取从机应答信号;
  7. 读取应答信号成功,对于两字节地址段器件,传输地址数据低字节,对于 1字节地址段器件,主机设置 SDA 为输出,传输待写入的数据;
  8. 设置 SDA 为三态门输入,读取从机应答信号,对于两字节地址段器件,接着步骤9;对于 1 字节地址段器件,直接跳转到步骤11;
  9. 读取应答信号成功,主机设置 SDA 为输出,传输待写入的数据(对于两字节地址段器件);
  10. 设置 SDA 为三态门输入,读取从机应答信号(两字节地址段器件);
  11. 读取应答信号成功,主机产生 STOP 位,终止传输。

6. 多字节连续写时序

I2C总线串口读写EEPROM_第7张图片

1.主机设置 SDA 为输出;
2. 主机发起起始信号;
3. 主机传输器件地址字节,其中最低位为 0,表明为写操作;
4. 主机设置 SDA 为三态门输入,读取从机应答信号;
5. 读取应答信号成功,主机设置 SDA 为输出,传输 1 字节地址数据;
6. 主机设置 SDA 为三态门输入,读取从机应答信号;
7. 读取应答信号成功后,主机设置 SDA 为输出,对于两字节地址段器件,传输低字节地址数据,对于 1 字节地址段器件,传输待写入的第 1 个数据;
8. 设置 SDA 为三态门输入,读取从机应答信号,对于两字节地址段器件,接着步骤9;对于 1 字节地址段器件,直接跳转到步骤11;
9. 读取应答信号成功后,主机设置 SDA 为输出,传输待写入的第 1 个数据(两字节地址段器件);
10. 设置 SDA 为三态门输入,读取从机应答信号(两字节地址段器件);
11. 读取应答信号成功后,主机设置 SDA 为输出,传输待写入的下一个数据;
12. 设置 SDA 为三态门输入,读取从机应答信号; n 个数据被写完,转到步骤13,若数据未被写完,转到步骤11;
13. 读取应答信号成功后,主机产生 STOP 位,终止传输。

7. 单字节读时序

I2C总线串口读写EEPROM_第8张图片

主机设置 SDA 为输出;
主机发起起始信号;
主机传输器件地址字节,其中最低位为 0,表明为写操作;
主机设置 SDA 为三态门输入,读取从机应答信号;
读取应答信号成功,主机设置 SDA 输出,传输 1 字节地址数据;
主机设置 SDA 为三态门输入,读取从机应答信号;
读取应答信号成功,主机设置 SDA 输出,对于两字节地址段器件,传输低字节地址数据;对于 1 字节地址段器件,无此步骤,直接跳转到步骤 h;
主机发起起始信号;
主机传输器件地址字节,其中最低位为 1,表明为读操作;
设置 SDA 为三态门输入,读取从机应答信号;
读取应答信号成功,主机设置 SDA 为三态门输入,读取 SDA 总线上的一个字节的数据;
产生无应答信号(高电平)(无需设置为输出高电平,因为总线会被自动拉高);
主机产生 STOP 位,终止传输

8. 多字节读时序

I2C总线串口读写EEPROM_第9张图片
主机设置 SDA 为输出
主机发起起始信号
主机传输器件地址字节,其中最低位为 0,表明为写操作。
主机设置 SDA 为三态门输入,读取从机应答信号。
读取应答信号成功,主机设置 SDA 输出,传输 1 字节地址数据
主机设置 SDA 为三态门输入,读取从机应答信号。
读取应答信号成功,主机设置 SDA 输出,对于两字节地址段器件,传输低字节地址数据;对于 1 字节地址段器件,无此步骤;直接跳转到步骤 h;
主机发起起始信号;
主机传输器件地址字节,其中最低位为 1,表明为读操作;
设置 SDA 为三态门输入,读取从机应答信号;
设置 SDA 为三态门输入,读取 SDA 总线上的第 1 个字节的数据;
主机设置 SDA 输出,发送一位应答信号;
设置 SDA 为三态门输入,读取 SDA 总线上的下一个字节的数据;若 n 个字节数据读完成,跳转到步骤 n,若数据未读完,跳转到步骤 l;(对于 AT24Cxx,一次读取长度最大为 32 字节,即 n 不大于 32)
主机设置 SDA 输出,产生无应答信号(高电平)(无需设置为输出高电平,因为总线会被自动拉高);
主机产生 STOP 位,终止传输。

8. I2C 控制器设计

I2C总线串口读写EEPROM_第10张图片
不管对于从机还是主机, SDA 上的每一位数据在 SCL 的高电平期间保持不变,而数据的改变总是在 SCL 的低电平期间发生。
因此,我们可以选用 2 个标志位对时钟 SCL 的高电平和低电平进行标记.scl_high 对 SCL 高电平期间进行标志, scl_low 对 SCL 低电平期间进行标志。这样就可以在 scl_high 有效时读 SDA 数据,在 scl_low 有效时改变数据。
I2C总线串口读写EEPROM_第11张图片
I2C总线串口读写EEPROM_第12张图片

在本实验中,时钟信号 SCL 采用计数器方法产生,计数器最大计数值为系统时钟频率除以 SCL 时钟频率,即:SCL_CNT_M = SYS_CLOCK/SCL_CLOCK。
对于 scl_high 和 scl_low 则只需要分别在计数到四分之一的最大值和四分之三的最大值时产生标志位即可

Wr 和 Rd 信号为 I2C 进行一次写和读操作的门控使能信号,
Done 信 号 为 一 次 I2C 写 和 读 操 作 完 成 标 志 位 。
(SCL_CNT_M>>2 )为 1/4 的 SCL_CNT_M
(SCL_CNT_M>>1)+(SCL_CNT_M>>2)为 3/4 的SCL_CNT_M

读写操作状态机

模块设计

I2C总线串口读写EEPROM_第13张图片
代码部分略,有时间参考下小梅哥自学笔记里的I2C部分,提供了一种简明的将读写字节合并为对字节进行单独操作再附上起始位、结束位、应答位的方法,代码量精简很多。

你可能感兴趣的:(FPGA)