一、目标
要求:设计一个使用I2C通讯协议的EEPROM读写控制器。使用写按键向EEPROM中写入1~10共10字节数据;使用读按键读出之前写入的数据并显示在数码管上。
分析:①首先按键控制读写操作按键消抖模块;②其次读出数据显示在数码管上数码管显示模块;另外核心模块需要在了解I2C通讯协议和EEPROM存储芯片后再构建。(稍后补充模块构建思路)补充:③使用IIC协议IIC驱动模块;④IIC协议是半双工通信方式,同一时刻只能进行一种操作,相当于仲裁模块IIC_rw_data模块。
注:各个模块的具体输入输出会在后面进行介绍。
二、关于IIC
2.1 IIC物理层
(1) 它是一个支持多设备的总线。
2.2 IIC协议层
( I2C 协议的整体时序图、读、写时序以及 I2C 设备的器件地址和存储地址 )
2.2.1 整体时序图
状态1(总线空闲状态):SCL和SDA都为高电平,此时IIC无设备工作。因为IIC是用线与结构,只要有一方拉低电平,线就为低电平,所以空闲状态必为高电平。
状态2(起始信号):在SCL为高时,SDA出现由高到低的下降沿,表示数据的传输开始。
状态4(停止信号):在SCL为高电平时,SDA由低变高,因为数据线由低变高,表示数据传输停止。
状态3(读/写状态):当SCL为高电平时,SDA保持稳定;当SCL线为低电平时,SDA可以进行数据更新,任意0,1变化。其中应答信号为低电平时,规定为有效应答位(ACK),表示接收器成功接收了该字节,应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
2.2.2 IIC写时序
1、单字节存储地址写时序
注:器件地址和器件存储地址在EEPROM中有介绍
①产生start位;
②传送器件地址,器件地址的最后一位数据为数据的传输方向位【R/W】,低电平0表示主机往从机写数据【W】,1表示主机从从机读数据【R】。ACK应答,应答是从机发送给主机的应答(写时序不管);
③传送写入器件寄存地址,即数据要写入的位置;
④传送要写入的数据;
⑤产生stop信号。
3、多数据单字节存储地址写时序
①产生start位;②写入器件地址; ③写入器件寄存地址;④连续写入数据; ⑤产生stop信号。
4、多数据双字节存储地址写时序
①产生start位;②写入器件地址; ③写入器件寄存地址高位;④写入器件寄存地址
注: 一次页写操作写入的字节数不能超过设备单页包含的存储单元数。
2.2.3 IIC读时序(1、2为随机读操作;3、4为顺序读操作)
1、单字节存储地址读时序
①产生start信号;
②写入器件地址,ACK;
③写入写入器件寄存地址,ACK;
④再次产生start信号;
⑤再次传送器件地址,ACK;
⑥读取一个字节数据,读数据最后结束前无应答信号;
⑦产生stop信号。
2、双字节存储地址读时序
①产生start信号;②写入器件地址,ACK;③写入器件寄存地址高位,ACK;④写入器件寄存地址低位,ACK;⑤再次产生start信号;⑥再次传送器件地址,ACK;⑦读取一个字节数据,读数据最后结束前无应答信;⑧产生stop信号。
3、多数据单字节存储地址读时序
①产生start信号;②写入器件地址,ACK;③写入器件寄存地址,ACK;④再次产生start信号;⑤再次传送器件地址,ACK;⑥连续读取接收从机数据,读数据最后结束前无应答信;⑦产生stop信号。
4、多数据双字节存储地址读时序
①产生start信号;②写入器件地址,ACK;③写入器件寄存地址高位,ACK;④写入器件寄存地址低位,ACK;⑤再次产生start信号;⑥再次传送器件地址,ACK;⑦连续读取接收从机数据,读数据最后结束前无应答信;⑧产生stop信号。
三、关于EEPROM
IIC是一个通信协议,它拥有严密的通信时序逻辑要求,而EEPROM是一个元件(从机),只是这个元件采样了IIC协议的接口与主机相连而已,二者并没有必然的联系,EEPROM可以用其它接口,I2C也可以用在其它很多器件上。
EEPROM是指带电可擦可编程只读存储器。是一种掉电后数据不丢失的存储芯片。EEPROM 可以在电脑上或专用设备上擦除已有信息,重新编程。一般用在即插即用。
3.1器件地址
AT24C64EEPROM存储芯片有一个IP地址即器件地址,它的目的就是为了iic总线能识别挂在总线上的从机,因为IIC总线可以挂载不止一个的设备。它有7位地址,还有一位读/写位(R/W),1为读操作0为写操作,但是24C64的前四位被厂家固化为1010,所以芯片管脚上只剩3个地址管脚(A0,A1,A2)。
3.2器件存储地址
他们内部包含一些需要进行读/写配置的寄存器,只有向对应寄存器写入正确参数,才能被正 确使用,即需要存储的数据按照地址写入对应的存储单元。AT24C64的存储空间为64Kbit(8Kbyte),需要13位存储地址才能满足所有存储单元的寻址,存储地址为2字节。
四、模块设计分析
系统框图如下:
4.1 IIC驱动模块
IIC驱动模块核心思想就是描述IIC协议读写时序过程,利用状态机捋清思路。根据2.2IIC协议首先明确有哪些状态。如图(第一行为写时序,第二行为读时序;读写时序在ACK3前状态相同)
然后补充状态跳转条件如下:
IIC驱动模块的输入由协议流程来分析:sys_clk和sys_rst_n信号不需多说。i2c_start是开始标志信号,但此时不知道是读操作还是写操作,所以需要写使能wr_en和读使能rd_en信号来明确状态。协议中发送器件地址,AT24C64 EEPROM 存储芯片的器件地址为1010_011(0/1);紧接着发送存储地址需要先确定存储地址为几个字节,所以addr_num为高表示2个字节,低为1个字节,然后存储地址由byte_addr寄存;写数据由wr_data表示。以上输入都由读写控制模块传入。
输出首先考虑较为简单的i2c_clk(1MHZ),由系统时钟(50MHZ)分频得到,先定义一个中间变量cnt_clk[4:0],计数参考时钟为系统时钟,技术范围为0-24,cnt_clk 每计完一个周期i2c_clk 进行一次取反即可得到i2c_clk。然后描述状态机得到i2c_scl和i2c_sda,
其中在画时序图时i2c_sda信号又要作输入又要作输出,逆向思维去想这时候需要一个sda_en信号,sda_en为高有效时,主机拥有对 sda 的控制权即作为输出,此时i2c_sda与i2c_sda_reg相同。
然后从机回传回来的应答信号需要一个变量ack去表示,在后面状态的跳转中需要用到;那么ack由谁得到?这时定义sda_in信号(就是将i2c_sda信号赋值给它),ack在响应状态时对sda_in信号的提取,其它时刻均为高电平;数据赋值也要用到。
4.2 读写控制模块
为什么进行跨时钟域处理?首先有两路时钟信号(sys_clk 和 i2c_clk),经过按键消抖后的写和读信号只保持一个系统时钟周期高电平,但是读写控制模块的工作时钟是i2c_clk,低频信号采集高频信号会出现时钟不同引起的时序问题。所以要进行跨时钟域处理,需要将读写使能信号在系统时钟下同步到工作时钟下,即采集到正确的读写有效信号。
两个时钟信号不同频,且是高频到低频的跨时钟域处理。我们需要延长读写使能触发信号的有效时间,使模块工作时钟 i2c_clk 可以采集到该触发信号。延长多久呢?一般至少要大于i2c_clk 的两个时间周期的时间长度(时间计数时钟是系统时钟)。
i2c_clk作为读写控制模块的工作时钟。进行数据写入操作,单单只有写使能有效不够的,还需要一个开始信号,两者同时有效才能进行写操作,且一次只能写入单个字节的数据;若需要连续写入多个字节,则要将开始信号按照一定的时间间隔(查芯片手册单字节写入需要5ms)拉高。