转载:关于STM32硬件I2C读写EEPROM代码实现原理的理解与总结

三、以I2C读写EEPROM(AT24C02)为例进行说明
3.1 针对EEPROM的基本操作
①写操作
②读操作
针对EEPROM的写操作和读操作也可以细分,如:
写操作:
①往EEPROM中写入一个字节的数据;
②往EEPROM中批量写入数据;
读操作:
①从EEPROM中指定地址读取一个字节数据;
②从EEPROM中批量读取数据;
下面结合上面4种读写操作来具体说明:
1、往EEPROM中写入一个字节数据
1)写入时序

2)时序分析
①第一步:主机产生起始信号,开始传输;
②第二步:发送挂载在I2C总线下的从机设备地址(这里由于是针对EEPROM,其地址是7位),注意:EEPROM的地址高四位已经固定,为1010,低三位由自己的硬件设计决定,一般都将EEPROM的这三根地址线直接接地,所以低三位地址就为000,这样该EEPROM的设备地址就为1010 000。由于这里是写入数据,所以R/W位就为0,这一位与前面的7位地址组成一个字节,所以写入数据时,发送的从机地址就为0xA0;
③第三步:发送完从机地址后,主机会释放SDA线,等待从机给一个低电平应答信号ACK,主机收到ACK后,进行下一步;
④第四步:发送将要写入数据的地址,这里要搞清楚,这个地址不是上面的从机地址,而是我们要写入数据到EEPROM中具体地址;(两者的关系可以打个比方:我们假设I2C总线就是一条叫香樟大道的马路,EEPROM就是这条马路上某个地方的一栋大楼,地址是香樟大道99号,而写入数据的地址就是香樟大道99号这栋楼里的某个具体房间号。)
⑤发送完写入数据地址后,释放SDA总线并等待从机给一个低电平的应答信号ACK;
⑥主机收到应答信号ACK后,开始向指定的地址中写入一个字节数据,写完一个字节数据后释放SDA总线;
⑦从机接受到一个字节数据后,返回一个应答信号给主机,主机接受到应答信号后,发送一个结束信号来结束本次数据传输。

图4中我们要看的是7位主发送的序列图,下面结合图4的主发送器传送序列图来解释上面写一个字节数据到EEPROM函数:
①主机产生起始信号,起始信号发送后,会产生EV5事件,EV5即表示SB=1,SB是I2C状态寄存器I2C_SR1的bit0,如下图5:

看上面的图5可以知道,如果起始条件已发送,SB会被置“1”,即产生事件EV5,所以我们要检测该位确认起始条件已发送;
②发送从机设备地址,从机应答后,会产生EV6事件,即ADDR=1,ADDR是I2C_SR1寄存器的bit1,说明如下图6:

通过图6我们可以知道,当地址发送完成,主机收到从机的应答后,ADDR位被置“1”,我们通过检测EV6事件来判断地址已发送完成并清除相关位;
③发送要写入数据的地址(地址也是数据),从机收到数据后应答,通过图4传送序列图可以看出,在第一个数据(第一个数据是要写入数据的地址)发送完并收到应答后,EV8事件早已经产生,EV8表示TxE=1,移位寄存器非空,数据寄存器空,写入DR寄存器将清除该事件。数据寄存器空,移位寄存器非空说明我们要发送的数据已经由数据寄存器转入移位寄存器,数据一旦转入移位寄存器就会在时钟信号的驱动下自动一位一位的将数据发送出去,所以我们在发送完地址后检测EV6事件,确认数据已经由数据寄存器转移到移位寄存器中发送,可以向数据寄存器中写入新的数据;
④发送我们要写入到EEPROM中的数据,从机应答后,检测EV8_2,这里为什么是检测EV8_2而不是EV8?因为我们这个函数只向EEPROM中写入一个字节数据,所以这个字节数据就是最后一个要发送的数据,通过图4传送序列图可以看出,最后一个数据传输完成后产生事件EV8_2,表示TxE=1,BTF=1,请求设置停止位。至于为什么产生的是EV8_2而不是EV8,我们来看看图7中有关BTF的说明:BTF表示字节发送结束,在发送时,当一个新数据被发送且数据寄存器还未被写入新的数据(TxE=1)时,BTF会被置“1”,由于我们这个函数只向从机发送一个字节数据(不包括地址),所以在这个字节数据被发送后并没有新的数据写入到数据寄存器,因此符合了上面的条件,BTF被置“1”。在TxE=1、BTF=1的情况下,就产生EV8_2;

⑤检测到EV8_2后,主机就可以产生停止信号来结束本次传输了。
有关写入一个字节数据到EEPROM中函数的分析到这里就结束了,下面来说一些从EEPROM中读取一个字节数据的相关代码以及分析。

2)时序分析
①第一步:主机产生起始信号;
②第二步:主机发送从机设备地址,写选通(即R/W为‘0’),从机接收到地址后应答;
③第三步:主机发送要读取数据在EEPROM中的地址,从机接收到后应答;
④第四步:主机再次产生起始信号;
⑤第五步:主机发送从机设备地址,读选通(即R/W为‘1’),从机接收到后应答;
⑥第六步:从机发送数据,主机接收,接收到最后一个数据后非应答;
⑦第七步:主机产生停止信号结束传输。

问题说明:
问题1:为什么要加一句等待EEPROM准备好的函数:
EEPROM的写入是需要时间的,只有当前面的写入操作完成,它才能继续响应后面的读取操作,否则在它还没有准备好的情况下,进行读取肯定是不成功的。关于等待EEPROM函数准备好的函数,它的实现原理就是通过向EEPROM发送从机地址,看从机是否成功应答,如果应答了就表示EEPROM已经准备好,如果应答失败就说明EEPROM还没准备好,然后主机继续发送从机地址来呼叫EEPROM等待应答,直到从机应答成功就退出该函数执行下一步,其代码如下(这段代码是我在野火的工程代码上修改了一点点,大家可以直接去看野火的官方例程,一定会有所收获的):
转载:关于STM32硬件I2C读写EEPROM代码实现原理的理解与总结的更多相关文章
- STM32F10x_硬件I2C读写EEPROM(标准外设库版本)
Ⅰ.写在前面 上一篇文章是“STM32F10x_模拟I2C读写EEPROM”,讲述使用IO口模拟I2C总线通信,对EEPROM(AT24Xxx)进行读写操作的过程. 上一篇文章主要内容:I2C协议.模 ...
- STM32F10x_模拟I2C读写_硬件I2C读写
STM32F10x_模拟I2C读写EEPROM STM32F10x_硬件I2C读写EEPROM(标准外设库版本) STM32F10x_硬件I2C主从通信(轮询发送,中断接收)
- STM32 硬件I2C 到底是不是个坑?
/** ****************************************************************************** * @author Maox ...
- 第23章 I2C—读写EEPROM—零死角玩转STM32-F429系列
第23章 I2C—读写EEPROM 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/f ...
- STM32F10x_模拟I2C读写EEPROM
Ⅰ.写在前面 说到IIC,大家都应该不会陌生,我们初学单片机的时候或多或少都知道或了解过,甚至使用I2C控制过器件.但是,有多少人真正去深入理解,或者深入研究过I2C通信协议呢? 1.我们有必要学习I ...
- 浅谈 STM32 硬件I2C的使用 (中断方式 无DMA 无最高优先级)(转)
引子 STM32的硬件I2C很多人都对它望而却步.因为很多电工都说,STM32 硬件 I2C有BUG.不稳定.死机等等……最后都使用GPIO模拟I2C. 的确,模拟I2C好用.但是在我看来在一个72M ...
- 基于FPGA的I2C读写EEPROM
I2C在芯片的配置中应用还是很多的,比如摄像头.VGA转HDMI转换芯片,之前博主分享过一篇I2C协议的基础学习IIC协议学习笔记,这篇就使用Verilog来实现EEPROM的读写,进行一个简单的I2 ...
- I2C读写EEPROM—EEPROM简介
EEPROM 是一种掉电后数据不丢失的存储器,常用来存储一些配置信息,以便系统重新上电的时候加载之.EEPOM 芯片最常用的通讯方式就是 I 2C 协议,本小节以 EEPROM 的读写实验为大家讲解如 ...
- (转)stm32硬件IIC
cube与I2C:https://www.cnblogs.com/121792730applllo/p/5044920.html I2C官网:https://www.i2c-bus.org/stand ...
随机推荐
- Java题库——Chapter14 JavaFX基础
Chapter 14 JavaFX Basics Section 14.2 JavaFX vs Swing and AWT1. Why is JavaFX preferred?a. JavaFX is ...
- Python——高阶函数概念(Higher-order function)
1.变量可以指向函数 以内置的求绝对值abs()函数为例,: >>> abs(-12) 12 >>> abs <built-in function abs&g ...
- 关于 Python_你一定没读过的8个技巧
介绍 Python 功能和小技巧的文章网上有无数篇,比如变量解压缩,partial 偏函数,枚举可迭代对象... 但关于 Python 我们能说的还有很多.所以今天我将向大家展示一些我知道和有使用过的 ...
- Python3 pickle模块用法
pickle(python3.x)和cPickle(python2.x的模块)相当于java的序列化和反序列化操作. 常采用下面的方式使用: import pickle pickle.dump(obj ...
- PHP 是如何做垃圾回收的
PHP 是如何做垃圾回收的 包含 php 5 与 php7 的变量实现和垃圾回收的对比 变量的实现 PHP 的变量是弱类型的,可以表示整数.浮点数.字符串等类型.PHP 的变量是使用结构体 zval ...
- 前端最佳实践——DOM操作
1.浏览器渲染原理 在讲DOM操作的最佳性能实践之前,先介绍下浏览器的基本渲染原理. 分为以下四个步骤: 解析HTML(HTML Parser) 构建DOM树(DOM Tree) 渲染树构建(Rend ...
- report for PA2
目录 说明 Report for PA 2(writed with vim) Part i - pa2.1 Steps: instr(seperately) Part ii - 2.2 Part ii ...
- 如何实现用户的历史记录功能(最多n条)
使用容量为n的队列存储历史记录 使用标准库collections中的deque,它是一个双端循环队列 from collections import deque q = deque([], 5) #参 ...
- MySQL日志简介
一.MySQL日志简介 二.错误日志 作用: 记录mysql数据库的一般状态信息及报错信息,是我们对于数据库常规报错处理的常用日志. 默认位置: $MYSQL_HOME/data/ 开启方式:(MyS ...
- SERCOS总线程序相关
SERCOS程序就是围绕主机发送MDT电报,伺服在下一个周期发送AT电报作为应答这个原则来实现的,这个过程是由控制字等控制实现的,读程序的时候如果忽略这点,可能在想程序从哪里读数据,在哪里写数据呢.. ...