Arduino 入门学习笔记12 读写外置EEPROM

Arduino 入门学习笔记12 读写外置EEPROM

  • 一、准备工作
    • 1. 外置 EEPROM 简介
    • 2. Arduino操作外置 EEPROM 流程
  • 二、读写操作流程
    • 1. 写操作流程
    • 2. 读操作
  • 三、示例代码

在这里插入图片描述

一、准备工作

1. 外置 EEPROM 简介

外置I2C接口的EEPROM是一种常用的非易失性存储器,通过I2C总线与微控制器或其他设备进行通信。它通常用于存储持久性数据,如配置设置、日志、校准数据等。以下是一些常用的外置I2C接口的EEPROM型号以及它们的特点:

  • 24C系列:Microchip的24C系列EEPROM是一些常见的I2C接口EEPROM型号。它们分为24C01到24C512等不同容量的型号,容量从128字节到64K字节不等。这些EEPROM设备在I2C总线上占用7位或8位的设备地址,并且通常具有多个页,可实现更高的写入速度。

  • AT24系列:AT24系列是Atmel(现在的Microchip)生产的I2C EEPROM。它们也提供不同容量的选项,从AT24C01到AT24C512。这些设备通常具有低功耗特性,适用于电池供电的设备。

  • CAT24系列:Catalyst(现在的ON Semiconductor)的CAT24系列EEPROM是一种具有扩展温度范围和多个页的EEPROM。它们适用于工业和汽车应用。

  • M24系列:STMicroelectronics的M24系列EEPROM提供了多种不同容量的型号,具有低功耗和低工作电流特性。

  • TC24系列:Microchip的TC24系列EEPROM针对温度敏感的应用提供了增强的温度范围。

  • FM24系列:Fremont Micro Devices的FM24系列EEPROM采用了更大的页大小,以实现更高的写入速度。

  • LC24系列:Excelon™ Ultra-Low-Power EEPROM是Microchip的一个系列,适用于需要极低功耗的应用。

下图是AT24系列引脚示例:
在这里插入图片描述

2. Arduino操作外置 EEPROM 流程

在Arduino中,读写外部EEPROM(电可擦除可编程只读存储器)的流程与内置EEPROM类似,但需要通过I2C通信来与外部EEPROM设备进行交互。基本流程是:

  1. 连接硬件:首先,将外部EEPROM设备与Arduino连接,通常使用I2C通信协议。确保连接SCL(时钟线)和SDA(数据线)引脚,并将设备的电源(VCC和GND)连接到适当的电源引脚。

  2. 安装I2C库:在Arduino IDE中,需要安装Wire库,它用于I2C通信。在"工具"菜单下的"管理库"中搜索"Wire"并安装它。

  3. 编写读写代码:根据外部EEPROM的规格和通信协议,编写Arduino代码来读写EEPROM。

一般EEPROM 的 I2C 地址从 0x00开始。

二、读写操作流程

1. 写操作流程

当使用writeEEPROM函数时,一个外部EEPROM设备通过I2C总线与我们建立了通信,以实现数据写入到特定地址的存储单元。以下是writeEEPROM函数的步骤解释:

  1. 开启通信:首先,我们使用Wire.beginTransmission(EEPROM_ADDR)来开始I2C通信,发送一个起始信号,这标志着写入操作的开始。在这里,EEPROM_ADDR是外部EEPROM设备的I2C地址。

  2. 发送高位地址:接着,我们使用Wire.write((int)highByte(address))发送了地址的高字节部分。这个高位地址指示了我们希望将数据写入的确切存储单元。

  3. 发送低位地址:继续,我们使用Wire.write((int)lowByte(address))发送了地址的低字节部分。这个低位地址更精确地指定了写入的位置。

  4. 发送数据:此时,我们使用Wire.write(data)将待写入的数据发送出去。

  5. 结束通信:随后,我们调用了Wire.endTransmission()来结束I2C通信。这意味着我们已经将数据和地址都传送给了外部EEPROM设备。实际上,这是向设备发送了一个写入请求。

  6. 等待写入完成:为确保写入操作成功完成,我们添加了delay(5)。这个短暂的等待时间允许EEPROM完成数据写入的操作,确保数据被正确存储。

需要注意的是,EEPROM写入通常需要一些时间,所以在调用writeEEPROM函数后,等待一段时间非常重要。EEPROM的写入周期可以从设备的规格表中获知。

2. 读操作

当我们使用readEEPROM函数时,我们与外部EEPROM设备通过I2C总线建立了通信,以从特定地址的存储单元读取数据。以下是readEEPROM函数的步骤解释:

  1. 开始通信:首先,我们使用Wire.beginTransmission(EEPROM_ADDR)开启I2C通信,发送了一个起始信号,这表明读取操作的开始。在这里,EEPROM_ADDR是外部EEPROM设备的I2C地址。

  2. 发送地址:然后,我们使用Wire.write((int)highByte(address))发送地址的高字节部分。这个高位地址指示了我们希望读取数据的确切存储单元。

  3. 发送低位地址:接下来,我们使用Wire.write((int)lowByte(address))发送地址的低字节部分。这个低位地址更精确地指明了读取的位置。

  4. 结束通信:随后,我们调用了Wire.endTransmission()来结束I2C通信。这意味着我们已经向外部EEPROM设备发送了读取请求。

  5. 请求数据:然后,我们使用Wire.requestFrom(eepromAddress, 1)请求从EEPROM读取1字节数据。

  6. 等待数据:我们使用while (Wire.available() == 0)来等待数据的到达。这确保了在数据准备好之前,我们不会继续执行。

  7. 获取数据:一旦数据可用,我们使用Wire.read()来读取并返回这个数据。

总结:通过readEEPROM函数,我们使用I2C通信协议成功地从外部EEPROM设备读取数据。我们发送地址和读取请求,然后等待数据的到达。这样,我们能够从EEPROM的指定地址成功地获取数据。

需要注意的是,EEPROM读取也需要一些时间,所以在调用readEEPROM函数后,等待一段时间也是必要的。EEPROM的读取速度可以从设备的规格表中找到。

三、示例代码

#include <Wire.h>const byte EEPROM_ADDR = 0x57;  // I2C address#define start 0x25
#define BUF_SIZE 50
char myMessage[BUF_SIZE] = { "Hello, I'll save Data to EEPROM demo." };
char MEM[BUF_SIZE];void setup() {Serial.begin(9600);Wire.begin();Serial.println();Serial.println("Writing to Ext.EEPROM...");for (unsigned int i = 0; i < sizeof(myMessage); i++) {writeEEPROM(i + start, myMessage[i]);delay(5);}Serial.println("Write Complete.");Serial.println();Serial.println("Reading Ext.EEPROM...");for (unsigned int j = 0; j < sizeof(MEM); j++) {byte data = readEEPROM(j + start);Serial.print("Address 0x");Serial.print(j + start, HEX);Serial.print(": 0x");Serial.print(data, HEX);Serial.print(" '");if (data >= 32 && data <= 126) {Serial.print((char)data);} else {Serial.print(".");}Serial.println("'");}Serial.println("Read Complete.");
}void loop() {
}void writeEEPROM(unsigned int address, byte data) {Wire.beginTransmission(EEPROM_ADDR);Wire.write((int)highByte(address));Wire.write((int)lowByte(address));Wire.write(data);Wire.endTransmission();delay(5);  // wait to complete the write cycle
}byte readEEPROM(unsigned int address) {byte data;Wire.beginTransmission(EEPROM_ADDR);Wire.write((int)highByte(address));Wire.write((int)lowByte(address));Wire.endTransmission();Wire.requestFrom(EEPROM_ADDR, (byte)1);while (Wire.available() == 0);  // wait for datadata = Wire.read();return data;
}

运行效果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/103144.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

石油和天然气行业如何实现数字化转型和工业4.0

石油和天然气行业的数字化转型正面临着前所未有的挑战和机遇。尽管过去相对滞后&#xff0c;这个复杂而庞大的行业正逐渐意识到数字化的紧迫性&#xff0c;以应对市场变化、降低运营成本、提高效率和确保可持续性。然而&#xff0c;数字化转型的进程并非一帆风顺&#xff0c;行…

echarts 之 科技感进度条

1.图片展示 2.代码实现 /* ng qty 进度条 */ <template><div class"ngqty-progress"><div class"ngqty-info"><span>X4</span><span>50%</span></div><div :id"barNgQtyProgress index" c…

【校招VIP】产品行测考点之图的推理和分析

考点介绍&#xff1a; 大厂产品校招笔试里经常会出现行测的考察&#xff0c;而图的推理是行测里面稍微有难度的一部分。因为时间有限&#xff0c;很多同学因为没有解题思路而丢分。 『产品行测考点之图的推理和分析』相关题目及解析内容可点击文章末尾链接查看&#xff01; 一…

第 7 章 排序算法(4)(插入排序)

7.7插入排序 7.7.1插入排序法介绍: 插入式排序属于内部排序法&#xff0c;是对于欲排序的元素以插入的方式找寻该元素的适当位置&#xff0c;以达到排序的目的。 7.7.2插入排序法思想: 插入排序&#xff08;Insertion Sorting&#xff09;的基本思想是&#xff1a;把n个待排…

Kaggle分类问题Titanic——Machine Learning from Disaster

目录 前言1 题目介绍2 数据清洗3 数据可视化分析4 模型训练5 源码 前言 这是我在大三选修课的课程设计&#xff0c;内容参考了Kaggle上高赞的代码&#xff0c;有详细批注&#xff0c;整体比较基础&#xff0c;结构相对完整&#xff0c;便于初学者学习。这个是一个分类问题&am…

【C语言】动态内存管理(malloc,free,calloc,realloc)-- 详解

一、动态内存分配 定义&#xff1a;动态内存分配 (Dynamic Memory Allocation) 就是指在程序执行的过程中&#xff0c;动态地分配或者回收存储空间的分配内存的方法。动态内存分配不像数组等静态内存分配方法那样&#xff0c;需要预先分配存储空间&#xff0c;而是由系统根据程…

基于微信小程序+Springboot校园二手商城系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、目前专注于大学生项目实战开发,讲解,毕业答疑辅导✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3…

android Junit4编写自测用例

10多年的android开发经验&#xff0c;一直以来呢&#xff0c;也没有使用过android自带的测试代码编写。说来也惭愧。今天也花了点时间稍微研究了下。还挺简单。接下来就简单的说一下。 新建工程 直接默认新建一个工程&#xff0c;就会有两个目录androidTest和test(unitTest)两…

Qt+C++动力监控动画仿真SCADA上位机

程序示例精选 QtC动力监控动画仿真SCADA上位机 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<QtC动力监控动画仿真SCADA上位机>>编写代码&#xff0c;代码整洁&#xff0c;规则…

Spring 为什么使用三级缓存解决循环依赖

文章目录 前言1. 什么是循环依赖1.1 互相依赖1.2 递归依赖 2. Sping中循环依赖有什么问题&#xff1f;3. 什么是三级缓存4. Spring 可以解决哪些情况的循环依赖&#xff1f; 二级缓存作用——普通循环依赖实操环节1. 实例化类A对象2. 实例化类B对象3. B对象完成创建4.继续创建A…

合宙Air724UG LuatOS-Air LVGL API--对象

对象 概念 在 LVGL 中&#xff0c;用户界面的基本构建块是对象。例如&#xff0c;按钮&#xff0c;标签&#xff0c;图像&#xff0c;列表&#xff0c;图表或文本区域。 属性 基本属性 所有对象类型都共享一些基本属性&#xff1a; Position (位置) Size (尺寸) Parent (父母…

2.文章复现《热电联产系统在区域综合能源系统中的定容选址研究》(附matlab程序)

0.代码链接 1.简述 光热发电是大规模利用太阳能的新兴方式&#xff0c;其储热系 统能够调节光热电站的出力特性&#xff0c;进而缓解光热电站并网带来的火电机组调峰问题。合理配置光热电站储热容量&#xff0c;能够 有效降低火电机组调峰成本。该文提出一种光热电站储热容 量配…

mysql-sql性能分析工具

一、sql执行频率 MySQL 客户端连接成功后&#xff0c;通过 show [session|global] status 命令可以提供服务器状态信息。通过如下指令&#xff0c;可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次&#xff1a; -- session 是查看当前会话 ; -- global 是查询全…

异地机房容灾备份方案,异地容灾备份方式有哪些

任何时候&#xff0c;我们都不能避免自然灾害、硬件问题、黑客攻击等事故。这些事情可能会导致数据中心的偏瘫&#xff0c;甚至影响整个业务的正常使用。因此&#xff0c; 机房容灾备份计划已成为确保业务连续性的关键对策。 一、异地机房容灾备份方案是什么&#xff1f; 国外…

运维高级学习--Docker(二)

1、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘。 #拉取mysql5.6和owncloud镜像 [rootlocalhost ~]# docker pull mysql:5.6 [rootlocalhost ~]# docker pull owncloud [rootlocalhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED …

接口自动化yaml文件读取与写入

前言 在走进yaml文件之前大家应该都很想知道他是用来干嘛的&#xff1f; 是的是的&#xff0c;他是用来做接口自动化测试的。 我们一起来学习他吧&#xff01;——&#xff08;一定要收藏带走哦❤&#xff09; 1、yaml文件有什么作用呢&#xff1f; ①可作为配置文件使用—…

maven工具-maven的使用-镜像仓库、本地仓、IDEA使用maven

Maven 一、为什么使用maven 添加第三方jar包jar包之间的依赖关系处理jar包之间的冲突获取第三方jar包将项目拆分成多个工程模块实现项目的分布式部署 二、maven简介 ​ Maven项目对象模型(POM)&#xff0c;可以通过一小段描述信息来管理项目的构建&#xff0c;报告和文档的…

Pytorch06-复杂模型构建

https://github.com/ExpressGit/Pytorch_Study_Demo 1、PyTorch 复杂模型构建 1、模型截图2、模型部件实现3、模型组装 2、模型定义 2.1、Sequential 1、当模型的前向计算为简单串联各个层的计算时&#xff0c; Sequential 类可以通过更加简单的方式定义模型。2、可以接收…

学习ts(七)泛型

定义 泛型允许我们在强类型程序设计语言中编写代码时使用一些以后才指定的类型&#xff0c;在实例化时作为参数指明这些类型。在ts中&#xff0c;定义函数、接口或类的时候&#xff0c;不预先定义好具体的类型&#xff0c;而在使用的时候在指定类型的一种特性。 例子&#xff…

数据库——Redis 单线程模型详解

文章目录 Redis 基于 Reactor 模式来设计开发了自己的一套高效的事件处理模型 &#xff08;Netty 的线程模型也基于 Reactor 模式&#xff0c;Reactor 模式不愧是高性能 IO 的基石&#xff09;&#xff0c;这套事件处理模型对应的是 Redis 中的文件事件处理器&#xff08;file …