FPGA实现IIC通信(读写EEPROM)

FPGA实现iic通信(读写EEPROM)

实验平台:正点原子ALIENTEK开拓者FPGA开发板

1. IIC协议简介

1.1 什么是IIC协议

IIC即为Inter-Inegrated Circuit(集成电路总线),在上世纪八十年代左右由Philips公司(即现做的NXP半导体公司)设计出来的一种简单、双向、二进制总线标准。其只需要两根线(SDA数据线和SCL时钟线)即可实现总线连接的器件间的通信。SDA和SCL都是双向I/O线,所以主要适用于数据量小,距离短的主从通信,数据的传输速率在标准模式下可达100kbit/s,在快速模式下可达400kbit/s,在高速模式下可达3.4Mbit/s。

Alt
当两个器件通信时,用于启动总线并产生时钟的为主器件,此时总线上所有可被寻址的都为从器件。所有的从器件都有其第一无二的设备地址,主机发送想要通信的从机的设备地址,所有的从器件将此地址与自身的设备地址对照,对应的从器件则发出应答信号,二者即开始通信。这也意味着主机与从机不是固定的,而是取决于数据的传输方向。

1.2 硬件结构

SDA(串行数据线)和SCL(串行时钟线)都是双向I/O线,接口电路为开漏输出,需通过上拉电阻接电源VCC,因此当总线空闲时两根线都是高电平。
Alt

1.3 为什么要使用IIC协议

通过上文可知IIC可以挂载多个设备,这也是其最大的优点。在工业中有时我们并不需要读出所有设备的数据,这时就可以使用IIC总线,将多个传感器挂载在其上,只需要在需要的时候读出对应设备的数据。虽然其与其他的串行外设接口相比,通信速度较慢,但是其大大节约了I/O资源;而且在传输过程中可以通过应答位来判断是否成功通信;这些优点导致IIC大面积应用。

1.4 IIC协议的时序特点

1.4.1 传输特点

由于IIC是由数据线和时钟线所组成的,因此二者相互配合完成数据的传输。当时钟线(SCL)为高电平时要求数据线(SDA)的数据稳定,此时从机开始接收主机数据或者主机接收从机的应答;当时钟线(SCL)为低电平时数据线(SDA)的数据可变化,即更新数据以备下一次的接收。
Alt

1.4.2 时序特点

IIC传输主要由开始信号、停止信号、应答/非应答、读、写信号五部分组成:
开始信号
当时钟线(SCL)为高电平期间,数据线(SDA)由高电平变为低电平即为起始信号,时序图如下图所示:
在这里插入图片描述
终止信号
当时钟线(SCL)为高电平期间数据线(SDA)由低电平变为高电平即为终止信号,时序图如下图所示:
在这里插入图片描述
应答/非应答
应答信号与非应答都由接收方发出(需要注意在读数据时,主机为接收方,因此要由主机发送应答/非应答信号),在时钟线(SCL)为高电平期间,检测数据线(SDA)的值,如果数据线(SDA)为低电平则为应答信号,数据线(SDA)为高电平则为非应答信号。
在这里插入图片描述
读数据
读数据的时序与应答/非应答的相同,都是在时钟线(SCL)为高电平期间读取数据线(SDA)的值,数据线(SDA)的高低电平即代表“1”或“0”,读数据的时序如下图所示:![在这里插入图片描述](https://img-blog.csdnimg.cn/20210308164815695.png #pic_center =750x)
写数据
通过上面的分析可知,从机在时钟线(SCL)高电平期间读取数据线(SDA)的数据,因此写数据时需要在时钟线(SCL)低电平期间改变数据线(SDA)的值来传输数据,时序图如下:
在这里插入图片描述

1.4.3 完整时序

IIC写时序
Alt

IIC写时序变化
Alt
IIC读时序
Alt

2. IIC协议实践

2.1 设计思想

通过对读写过程分析可知,无论是读或者写过程都由开始信号、发送设备地址(最后一位读或者写)、发送存储单元地址、发送数据/读数据、结束几部分组成。因此用状态机来完成此代码。
状态机
在此我将读写操作写在了一个驱动文件里,是考虑到如果读写分别写在两个文件里的话,在例化时对inout端口的例化会有困难(因为其还需要一个控制信号),因此我写在了一个文件里,由一个读写控制信号来判断是执行读操作还是写操作;在此次设计中我将开始信号放在了发送设备地址里,以便减少状态。

2.2 RTL代码重要部分

驱动时钟
由于IIC需要满足不同的通信速率,因此在此将其设置为参数,为了在时钟线(SCL)的不同时刻对数据线(SDA)进行处理,因此将其进行四分频,这样驱动时钟的4个周期就是时钟线(SCL)的一个周期。

	parameter   CLK_FREQ   = 26'd50_000_000, //模块输入的时钟频率
    parameter   I2C_FREQ   = 18'd250_000     //IIC_SCL的时钟频率
	
	assign  clk_divide = (CLK_FREQ/I2C_FREQ) >> 2'd2;

时钟计数器
由于驱动时钟是与时钟线(SCL)相互对应的,因此驱动一个计数器来作为其他信号的判断依据。由于不同的状态持续的时间不同,因此将计数器的自加放在状态机的case语句中,这样不同状态可直接判断计数器来判断其他信号的状态。

数据线(SDA)数据的变化
通过驱动时钟来驱动一个计数器,由于驱动时钟的四个周期对应时钟线(SCL)的一个周期,因此通过计数器的数值即可判断时钟线(SCL)是处于什么位置,并根据此来判断时钟线(SCL)的上升沿和下降沿。
inout端口输入输出方向变化
在状态机内部通过计数器来判断时钟线(SCL)的不同状态,当其计数到相应时刻时将控制inout端口的 信号更新到对应的状态。

2.3 开发过程遇到的问题

从机无应答
在测试过程中出现了从机应答错误的情况,用SignalTap抓取波形图发现起始信号并没有问题,通过上网查询发现EEPROM在写之间需要时间间隔,由于不知道需要等待多长时间,因此在状态机中持续等待应答,等到应答正确后再状态跳转。
应答正常但读出数据不对
更改后发现读写时序都正确,应答也正确但是读出的数据不正确,通过查询资料怀疑是EEPROM出问题,所以将设备断电使EEPROM进行上电,上电后恢复正常。
时钟问题
将IIC和串口模块相连接,实现数据的回环,将IIC模块的完成信号作为串口的发送使能信号,由于IIC的完成信号保持的时钟是远远长于一个时钟的,因此会造成串口持续发送。所以在IIC模块中加了一个边沿检测程序,将电平信号变为脉冲信号后再将其输出。

3. 代码下载

链接: IIC通信源码.

  • 7
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值