【紫光同创PGL22G学习】四、以24LC04为例,上手I2C接口使用(附加学习Opencores开源网站使用 和 Fabric Debugger在线调试)

导读:本实验通过使用开源软件 opencores 上的 I2C master 控制器去控制 I2C 接口的 EEPROM 读写,练习如何有效的使用开源代码提升开发效率。同时,附带学习基于 Fabric Debugger 在线调试方法。

一、实验原理

1.1、硬件电路

PGL22G 开发板板载了一片 EEPROM,型号为 24LC04,容量为:4Kbit(2*256*8bit),由 2 个 256byte 的 block 组成,通过 IIC 总线进行通信。板载 EEPROM 是为了学习 IIC 总线的通信方式,EEPROM 的 I2C 信号与FPGA 的 IO 口连接示意图如下所示:

在这里插入图片描述

从上图可以看到,FPGA 芯片通过 I2C 总线连接 EEPROM 24LC04,I2C 的两根总线各上拉一个 4.7K的电阻到 3.3V,所以当总线上没有输出时会被拉高。24LC04 模块外围电路如下图所示:

在这里插入图片描述

从上图可以看出,24LC04 的写保护引脚(WP)没有使能,不然 FPGA 会无法写入数据。另外,24LC04 的三根地址线A0~A2在电路上都为低,所以 24LC04 的设备地址为 0xA0。还有特别重要的的一点,24LC04的单页为16个字节!

1.2、I2C的总线协议和时序

I2C 标准模式速率100kbit/s快速模式速率 400kbit/s,支持多机通讯, 支持多主控模块,但同一时刻只允许有一个主控。由数据线 SDA 和时钟 SCL 构成串行总线,每个电路和模块都有唯一的地址

I2C 设备的操作可分为写单个存储字节写多个存储字节读单个存储字节读多个存储字节,各个操作如下图所示:

在这里插入图片描述

下面对 I2C 总线通信过程中出现的几种信号状态和时序进行分析。

  • 1、总线空闲状态

I2C 总线总线的 SDA 和 SCL 两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。

  • 2、启动信号(Start)

在时钟线 SCL 保持高电平期间,数据线 SDA 上的电平被拉低(即负跳变),定义为 I2C 总线总线的启动信号,它标志着一次数据传输的开始。启动信号是由主控器主动建立的,在建立该信号之前 I2C 总线必须处于空闲状态,如下图所示。

在这里插入图片描述

  • 3、停止信号(Stop)

在时钟线 SCL 保持高电平期间,数据线 SDA 被释放,使得 SDA 返回高电平(即正跳变),称为 I2C 总线的停止信号,它标志着一次数据传输的终止。停止信号也是由主控器主动建立的,建立该信号之后,I2C 总线将返回空闲状态。

  • 4、数据位传送

在 I2C 总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在 SCL 串行时钟的配合下,在 SDA 上逐位地串行传送每一位数据。进行数据传送时,在 SCL 呈现高电平期间,SDA 上的电平必须保持稳定,低电平为数据 0,高电平为数据 1。只有在 SCL 为低电平期间,才允许 SDA 上的电平改变状态。

  • 5、应答信号(ACK 和 NACK)

I2C 总线上的所有数据都是以 8 位字节传送的,发送器每发送一个字节,就在第9个时钟脉冲期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK 简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。对于反馈有效应答位 ACK 的要求是,接收器在第 9 个时钟脉冲之前的低电平期间将 SDA 线拉低,并且确保在该时钟的高电平期间为稳定的低电平。如果接收器是主控器,则在它收到最后一个字节后,发送一个 NACK 信号,以通知被控发送器结束数据发送,并释放 SDA 线,以便主控接收器发送一个停止信号。

二、程序设计

2.1、I2C控制器源码获取

I2C 时序虽然简单,但是写的不好也会出现很多问题,在开源网站 http://opencores.org/ 上我们可以找到很多非常好的代码,这些代码大部分都提供详细的文档和仿真。俗话说,他山之石,可以攻玉,恰当的使用开源代码,不光能提升我们的开发效率,也能学习别人的开发思路。由于代码大部分都是经过很长时间反复修改,反复精炼后的,所以有些代码理解起来可能比较困难,在不能很好的理解别人代码的时候,最好的办法就是仿真

如何下载开源的i2c控制器代码呢?且听娓娓道来。

:下载前需要先注册账号!

  • 1、进入 opencores 后,点击左侧的 PROJECTS,如下图所示:

在这里插入图片描述

  • 2、打开其中的Communication controller,如下所示:

在这里插入图片描述

  • 3、找到I2C controller core,并点击进入选择download,进行下载,如下图所示:

在这里插入图片描述

在这里插入图片描述

2.2、读写EEPROM程序设计

从 IP core 文档得知,i2c_master_byte_ctrl 模块主要完成一个字节的读写,我们只需要按照 I2C 读写的要求,完成设备地址、寄存器地址、数据等读写即可。

i2c_master_top 模块是我们对 i2c_master_byte_ctrl 模块的再次封装,完成一个寄存器的读写,由于不同的设备寄存器可能是 8bit,也可能是 16bit,这里 i2c_addr_2byte 信号来控制寄存器地址是 8 位还是 16 位。对于i2c_master_top 模块状态机来说,读写寄存器操作流程如下:

  • 如果是写操作:先写一个字节设备地址(写操作),再写 1 个字节或 2 个字节的寄存器地址,再写一个字节的数据;
  • 如果是读操作:先写一个字节的设备地址(写操作),再写 1 个字节或 2 字节的寄存器地址,完成地址的写入,再次写设备地址(读操作),然后读取一个字节的数据。

不管怎么说,程序设计都是要满足芯片时序要求的,所以在阅读程序之前最好先把芯片的数据手册仔细阅读一遍。

i2c_master_top 状态机的状态转换图如下图所示:

在这里插入图片描述

i2c_master_top 模块端口列表如下:

信号名称方向说明
clkin时钟输入
rstin异步复位输入,高复位
---
clk_div_cntinI2C 时钟分频因子,等于系统时钟频率/(5 * I2C 时钟频率) - 1。例如 50Mhz 系统时钟,100Khz 的I2C,配置为 99,400Khz 的 I2C,配置为 24
---
scl_pad_iinI2C 时钟数据输入,本实验可忽略
scl_pad_ooutI2C 时钟输出
scl_padoen_ooutI2C 时钟输出使能,低有效,I2C 外部有上拉电阻,如果输出高阻态,则会被拉到高电平,在本实验中,高电平输出时输出高阻
---
sda_pad_iinI2C 数据输入
sda_pad_ooutI2C 数据输出
sda_padoen_ooutI2C 数据输出使能,低有效。在本实验中,高电平输出时输出高阻。
---
i2c_addr_2bytein寄存器地址是 8 位还是 16 位,1表示 16 位,0表示 8 位
---
i2c_read_reqinI2C 寄存器读请求
i2c_read_req_ackoutI2C 寄存器读请求应答
---
i2c_write_reqinI2C 寄存器写请求
i2c_write_req_ackoutI2C 寄存器写请求应答
---
i2c_slave_dev_addrinI2C 设备地址,8bit,最低位忽略,有效数据位是高 7位。
i2c_slave_reg_addrin寄存器地址,8 位地址时,低 8 位有效
---
i2c_write_datain写寄存器数据
i2c_read_dataout读寄存器数据
---
errorout设备无应答错误

i2c_eeprom_test 模块完成 EEPROM 的读写,EEPROM 设备地址A0,程序中将地址 00 的数据读出,然后通过 LED 显示,在 KEY2 按下时,数字加一并再次写入 EEPROM 并显示出来。在 I2C控制器中,代码的大部分功能在备注中也有很多批注。

三、下载实验

下载实验程序后,可以看到 LED 显示一个二进制数字,这个数字是存储在 EEPROM 中 00 地址的数据,数据是随机的,这个时候按键 KEY2 按下,数字加一,并写入了 EEPROM,再次下载程序,可以看到直接显示更新后的数据。

在这里插入图片描述

四、使用在线调试 Fabric Debugger观察信号

使用 Fabric Debugger 可以非常直观的看到程序在开发板上运行时各个信号的变化,在本例程中添加一个 Debug Core 来观察程序运行时各数据线的变化情况。具体操作步骤如下:

  • 1、打开PDS软件,选择工具栏的“Inserter”,如下图所示:

在这里插入图片描述

  • 2、在弹出界面选择 New DebugCore Unit 来新建一个 Debug Core,如下图所示:

在这里插入图片描述
在这里插入图片描述

  • 3、单击 U0:DebugCore,会跳到参数设置界面,在"Trigger Parameters"栏中根据需求选择采样深度Sample Depth。这里全部保持默认,如下图所示:

在这里插入图片描述

  • 4、在"Net Connections"栏中选择 Modify Connections,进行 Net 修改;

在这里插入图片描述

  • 5、弹出的界面中,首先在 TriggerPort 栏中进行观测信号关联。本例中,选择左侧 read_data,然后单击Make Connections,可以在 TriggerPort 栏中看到关联的观测信号 read_data,如下图所示:

在这里插入图片描述

在这里插入图片描述

:read_data有七路信号,所以占了7位。

  • 6、以同样的方式对 Clock 栏中时钟信号关联,选择左侧 nt_sys_clk,然后单击 Make Connections,可以在 Clock 栏中看到关联的观测信号 nt_sys_clk,然后单击 OK,如下图所示:

在这里插入图片描述

在这里插入图片描述

  • 7、回到如下界面,直接关闭即可,如下图所示:

在这里插入图片描述

  • 8、接下来重新生成.sbit 文件。右击 Generate Bitstream,选择Rerun All,在弹出的窗口选择Yes后,等待全编译完成,会生成带有在线调试DebugCore的比特流文件,如下图所示:

在这里插入图片描述
在这里插入图片描述

  • 9、上面的工作准备好后,接下来才是正式开始调试, 单击 Debugger确保开发板上电并连接了下载器),如下图所示:

在这里插入图片描述

  • 10、单击 JTAG 扫描按钮,在找到后单击 OK,如下图所示:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 11、右击 DEV:0MyDevice0,在下拉菜单中单击 Configure Bitstream File,如下图所示:

在这里插入图片描述

  • 12、在弹出窗口,选择刚刚编译生成的比特流文件,点击Open,最后点击OK,如下图所示:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 13、到此,程序已下载到 FPGA 中可以在线观察所需要的信号,选择 Waveform,选择触发模式为连续,并单击 run,如下图所示:

在这里插入图片描述

  • 14、可以看到 read_data 数据,每按一次 KEY2 键运行一次可以看到数据增加 1
    在这里插入图片描述

参考

  • 7
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ReCclay

如果觉得不错,不妨请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值