(11.2)iic串口读写EEPROM实验:iic串口协议
一、iic协议介绍
iic(i2c,inter-integrated Circuit),即集成电路总线,是一种两线式串行总线。多用于主机(fpga)和从机(外围设备)在数据量不大且传输距离短的场合下使用(支持一主多从,根据器件地址进行从机的区分)
iic由数据线SDA和时钟线SCL构成通信线路,既可以发送数据,也可以接受数据
iic为半双工同步通信方式,在不同模式下通信速率不同
标准模式:100Kbit/s
快速模式:400Kbit/s
高速模式:3.4Mbit/s
二、协议时序
数据线只允许在时钟的低电平时改变,在高电平时保持不变
开始:时钟高电平时,数据线由高变为低;结束:时钟高电平时,数据线由低变为高
应答过程:开始时数据线由高变低,紧接着连续八个时钟fpga输出8bit数据(一开始的数据可能是器件地址),从设备检测到器件地址是自己的后,则拉低自己的相应信号,fpga会检测这个拉低的信号,即EEPROM是否响应了数据
如果没有响应(即SDA信号一直为高),则可能是因为器件地址发送错误,也可能是时钟频率过高
器件地址:由8位数据构成,前四位为固定值,后三位为A2、A1、A0(器件中已全部接地,因此都为0),最后一位为控制位,表示对器件是读操作还是写操作(读操作为1,写操作位0)
字节写:首先数据线由高到低表示开始(在时钟高电平时),紧接着发出8位的器件地址(最后一位为0,表示写),接下来的ACK是一个应答位,即EEPROM接收到正确地址后会相应,将拉低这个SDA数据线,(即前面的器件地址是fpga在控制这根线,后面的这个应答位是EEPROM在控制这根线);
接下来是第一个字节地址位(×号表示不用关心的bit位,为什么不用关心呢?因为EEPROM一共有8192个字节,即2的13次方,因此第一个字节位地址前三位是不关心的,后五位和第二个字节地址8位构成了我们的13位字节地址),发送完后EEPROM同样做出一个应答ACK;
接下来发送第二个字节位地址(低八位),发送完后EEPROM同样做出一个应答ACK;
传送完字节地址后,fpga会将数据DATA发送给EEPROM,同样做出一个应答ACK;
最后fpga会发送一个结束操作,即SCL为高电平期间SDA由低变高
结束之后EEPROM会处于一个写的周期,将数据写入字节地址中,在此期间无法对其进行操作,这一过程大概5ms
页写:前面的操作和字节写相同,区别在于在发送了数据后,不发送终止操作,而是接着发送其他数据,后面的数据依次往后面的地址中写入,直到31(地址是递增的,每一页有32个字节),如果到31还不给结束操作的话,那么他又会返回到0去写数据(注意:这里是在当前页的循环!!要到下一页的话需要重新发起操作改变前面的字节地址)
当前地址读:首先是一个开始,然后是一个八位的器件地址(最后一位为1表示读),之后是ACK应答信号,再之后是从EEPROM读取到的数据,之后主机NO ACK不进行应答,再之后就是结束操作
可以看到,该过程并没有指定读哪个地址,这是因为它内部有一个字节地址计数器在自动累加。比如我们开始往地址0写入数据,写完后字节地址计数器会变为1,我们发起读操作时读取到的就是地址1中的数据,结束之后再发送读操作的话就是地址2、3、4.......
这种读取方式比较简单,只需要给出器件地址其字节地址计数器会自动累加,但缺点就是无法指定某个地址的数据读出来
随机地址读:在真正进行读取之前首先会进行一个“哑写”的操作,其目的只是为了切换之前的字节地址计数器为我们需要的地址(因此它只发送了字节地址而没有发送数据),改变之后重新发送开始信号,器件地址(可以看到控制位已经变为1了,表示进行读),应答ACK之后紧跟着的就是读出的8bit的数据,这个数据对应的地址就是前面“哑写”的字节地址,之后主机没有应答,stop
这种方式的缺点在于读取之前需要进行一次“哑写”,会占用一定的时间,好处在于可以指定某个字节地址读数据
连续读:在前两种读取的基础上,最后不发送主机NO ACK和stop,而是发送主机ACK(注意这里是主机应答!!!),则将继续紧接着当前的地址(累加)去读取数据
这种方式非常适合输出连续地址的数据
三、程序设计
本实验对EEPROM进行字节写和随机地址读
单次字节写时序:
注:SCL和SDA在没有任务时处于空闲状态(置高)
从机应答为0表示有效
每次写入有5ms的间隔(这个只是收到8位,EEPROM还没写入),这个延迟只是针对写操作而言,读操作是不需要擦除的!!!
随机地址读时序: