芯路恒电子技术论坛

 找回密码
 立即注册
热搜: 合集
查看: 33589|回复: 20

【设计实例】I2C协议读写EEPROM存储器完整设计加仿真文件

[复制链接]
  • TA的每日心情
    慵懒
    2021-2-24 10:16
  • 422

    主题

    780

    帖子

    1万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    15847
    QQ
    发表于 2018-12-28 15:41:27 | 显示全部楼层 |阅读模式
    如果您还没有注册本论坛,将无法下载论坛中附件,但是注册论坛非常简单,使用微   信 扫码即可注册。
    也可以在小梅哥任意一个Q群内直接索取邀请码使用邀请码注册,小梅哥创建的任意一个群都可以。



    在2014年参加培训的时候写过一次IIC协议的控制器,后来,又讲解了I2C协议的公开课,培训时候也讲解过该内容,但是一直没有亲自动手写过一个完整的I2C协议控制器,一直偷懒用的网友提供的现成的,进来兴致大发,写了一个简单的I2C控制器,使用状态机加线性序列机的思维实现了整个设计,还是比较清晰易懂的。

    24LC64和24C04两种存储器的存储器地址段长度不同,24LC64是2个字节地址,24C04是一个字节地址,因此这里分别作了两个工程,来对应仿真测试,仿真脚本已经设置好,直接运行仿真就可以看到效果啦。
    仿真波形.png
    AC_I2C_Control_24C04.rar (313.17 KB, 下载次数: 2770) AC_I2C_Control_24LC64.rar (320.99 KB, 下载次数: 2283)



    以下收录了几个网友在学习过程中的疑问和解答:


    问:请问这个IIC协议中为什么有读写信号是直接跳到读写状态,不用到起始状态吗,不太懂,能解答一下吗
    00001.png

    答:一次完整的写寄存器过程,包括起始状态,写器件地址,写存储器地址,写数据,仅在写器件地址之前需要产生起始位,后面的写存储器地址,写数据都不需要产生起始位。这个程序只是完成一个字节的数据传输,因此存在无需传输起始位的过程。
    ============================================================

    问:文件夹里面的这个AC_IIC control文件和i2c bit_shift文件是不是一样的功能啊,有一个是用序列机写的是吗

    答:[size=13.3333px]第一个没用,忘了删了。即AC_IIC control用状态机思维写的,最后发现在细节上处理不是很方便,就舍弃了,新写了一个叫i2c bit_shift的文件,该文件使用的是状态机加序列机的方式写的。
    ============================================================

    问:这个里面Go=1;Cmd=3,WR=1,Rd=4,STA=2,这个CMD&WR,CMD&RD,CMD&WR都不是0,也不是1,是一个数,这个要怎么执行啊,如果说if里面的条件不为0就是真,那这个三个条件都为真,执行哪一个啊,语法没学好,望指教。
    00002.png
    答:if else 是有优先级的,这个优先级的判定和C语言里面的if else一样,所以当然是执行优先级高的。因为cmd是上层应用层传下来的指令,不会同时出现WR和RD都有效的情况的。
    ============================================================
    问:小梅哥,我想问一下,在iic这个协议里,如果地址是两个字节长度的话你是用这个addr_mode等于0表示一个字节,等于1表示两个字节吗,但如果是一个字节为什么他这里写入的是addr[15:8]而不是【7:0】呢,有点不懂这个地方,有人能解答一下吗。
    00003.png
    00004.png
    答:嗯,这里是为了写程序方便这么定义的。最开始写的时候,如过存储器长度是2个字节,应用层,就直接把存储器地址给到addr端口上,如果是1个字节的,就给到addr的高8位上。但是这种思路不是很好接收,因为自己后面调试的时候也经常性的把地址直接给addr,而不管模式是0还是1,所以后面OV7670的程序(详见:http://www.corecourse.cn/forum.php?mod=viewthread&tid=27814)就改进了下,加了个根据mode的值在驱动层切换高低字节的操作。
    00005.png
    下图中,根据mode的值,切换了addr的高低字节。
    00006.png

    ============================================================

    问:请问这里为什么字节为1的时候cnt=1写完地址的时候要加STO啊,他应该接着写device_id,应该不需要停止位的写入吧。(注意,该问题问的是使用该控制器初始化OV7670的程序中的内容,详见:http://www.corecourse.cn/forum.php?mod=viewthread&tid=27814
    00007.png
    答:需要,EEPROM不需要,但是OV7670、OV5640等摄像头的协议中,和标准的IIC协议差别就在这里,这里是需要加停止位的。
    ============================================================

    问:小梅哥,你写的这个iic协议是不是一次只能写或者读一个数据啊,不能连续读写多个数据是吗
    答:是的,在FPGA中,一般用来初始化各种器件设备,如图像、视频、音频系统里面的各种器件,这些器件都支持单次读写模式,没有页读写模式,而这个控制器本身是用来初始化这些器件用的,就没有考虑多字节模式,这样程序简单,占用的资源也最少。
    ============================================================

    问:我想请问一下开发板上的PCF8563内部是不是就包含了一个EEPROM存储器。(注意,该问题问的是使用该控制器读写RTC芯片PCF8563的程序中的内容,详见:
    http://www.corecourse.cn/forum.php?mod=viewthread&tid=27816
    答:就是几个寄存器,不是eeprom
    问:我看到的也是几个寄存器,所以我不太懂为什么在PCF8563仿真的时候这个testbench里要添加EEPROm的这个仿真芯片呢
    00008.png
    还是说这里是把PCF这个芯片看成一个EEPROM呢,
    答:看成一个eeprom 借eeprom的仿真模型来仿真的,因为8563没仿真模型


    问:这个i2c_control应答标志位为什么还要和i2c_shift_bitl应答标志位或运算一下,这里有点不明白,为什么不能直接输出i2c_shift_bitl应答标志位。ack是i2c_control输出的,ack_o是调用i2c_shift_bit传过来的。
    ack.png
    答:一次读写包含多次底层的i2c_bit shift过程,只有这么多次都有应答(ack为0),才能确定此次读写成功,所以将这每次i2c_bit shift过程的应答结果相或,只要其中有一次没有应答(ack_o为1),则会导致ack为1,从而证明此次读/写过程失败。
    回复

    使用道具 举报

  • TA的每日心情
    可爱
    2021-10-8 21:08
  • 0

    主题

    19

    帖子

    67

    积分

    初级会员

    Rank: 3Rank: 3

    积分
    67
    发表于 2019-1-2 17:29:47 | 显示全部楼层
    Good...

    回复

    使用道具 举报

  • TA的每日心情
    郁闷
    2019-3-14 11:26
  • 5

    主题

    11

    帖子

    157

    积分

    初级会员

    Rank: 3Rank: 3

    积分
    157
    发表于 2019-1-9 14:41:47 | 显示全部楼层
    很棒,正好需要学习,希望小梅哥多做一些实例
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2018-11-19 10:52
  • 0

    主题

    3

    帖子

    22

    积分

    新手上路

    Rank: 2

    积分
    22
    发表于 2019-1-13 21:38:42 | 显示全部楼层
    支持一下,多搞一些例程正好需要学习
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2023-10-25 15:02
  • 1

    主题

    33

    帖子

    518

    积分

    高级会员

    Rank: 6Rank: 6

    积分
    518
    发表于 2019-1-23 10:27:52 | 显示全部楼层
    正好学习学习,先加收藏,保存起来~~~
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    1

    帖子

    2

    积分

    新手入门

    Rank: 1

    积分
    2
    发表于 2019-10-31 17:20:47 | 显示全部楼层
    梅哥牛逼,我好好研究一下代码。谢谢
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2020-7-19 10:26
  • 0

    主题

    3

    帖子

    25

    积分

    新手上路

    Rank: 2

    积分
    25
    发表于 2020-3-6 11:54:55 | 显示全部楼层
    小梅哥牛啤,我是之前看了您的关于i2c的教程视频,尝试着写但是很糟糕,看到大佬写的就是好
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    1

    帖子

    7

    积分

    新手入门

    Rank: 1

    积分
    7
    发表于 2020-8-6 11:32:58 | 显示全部楼层
    感谢小梅哥,这种学习方式我学得很快
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    1

    帖子

    4

    积分

    新手入门

    Rank: 1

    积分
    4
    发表于 2020-9-8 09:26:31 | 显示全部楼层
    多谢小梅哥 。。。。。非常感谢。。。。。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-7-8 09:28
  • 1

    主题

    5

    帖子

    23

    积分

    新手上路

    Rank: 2

    积分
    23
    发表于 2021-7-11 11:35:07 | 显示全部楼层
    小梅哥   我想问一下 从机接收到正确的数据之后是怎么给主机发送响应位的?三态门在接收到8位正确的数据之后就将sda_en信号拉低,此时sda信号不就为高阻态了吗?怎么能在下一个时刻检测到sda为0(也就是响应位为0)
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|小黑屋|Archiver|芯路恒电子技术论坛 |鄂ICP备2021003648号

    GMT+8, 2024-4-19 14:39 , Processed in 0.133559 second(s), 44 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc. Template By 【未来科技】【 www.wekei.cn 】

    快速回复 返回顶部 返回列表