嵌入式进阶——EEPROM读写

2024-05-29 13:20
文章标签 进阶 读写 嵌入式 eeprom

本文主要是介绍嵌入式进阶——EEPROM读写,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

🎬 秋野酱:《个人主页》
🔥 个人专栏:《Java专栏》《Python专栏》

⛺️心若有所向往,何惧道阻且长

文章目录

    • 设置EEPROM
    • 读写String字符串
    • 官方示例

EEPROM是一种可擦写可编程只读存储器(Electrically Erasable Programmable Read-Only Memory)的缩写。它是一种非易失性存储器,可以在不需要外部电源的情况下保持存储数据。与ROM不同,EEPROM可以通过电子擦除和编程来修改存储的数据,因此它是一种可重写的存储器。

EEPROM通常用于存储需要频繁修改的数据,例如系统配置信息、用户设置、校准数据等。由于EEPROM可以在系统运行时进行读写操作,因此它在许多应用中都具有很高的实用价值。

设置EEPROM

STC8H8K64U的EEPROM可以在烧录的时候指定大小, 如下图
在这里插入图片描述

读写String字符串

#include "Config.h"
#include "UART.h"
#include "EEPROM.h"
#include <string.h>void UART_config(void) {// >>> 记得添加 NVIC.c, UART.c, UART_Isr.c <<<COMx_InitDefine		COMx_InitStructure;					//结构定义COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;	//模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTxCOMx_InitStructure.UART_BRT_Use   = BRT_Timer1;			//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)COMx_InitStructure.UART_BaudRate  = 115200ul;			//波特率, 一般 110 ~ 115200COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLECOMx_InitStructure.BaudRateDouble = DISABLE;			//波特率加倍, ENABLE或DISABLEUART_Configuration(UART1, &COMx_InitStructure);		//初始化串口1 UART1,UART2,UART3,UART4NVIC_UART1_Init(ENABLE,Priority_1);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3UART1_SW(UART1_SW_P30_P31);		// 引脚选择, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}#define     Max_Length          100      //读写EEPROM缓冲长度
u8  xdata   tmp[Max_Length];        //EEPROM操作缓冲void main() {u16 addr_sector = 0x0000;char *str = "HelloWorld!abc123!";u16 str_length = strlen(str);	// 获取str的长度UART_config();EA = 1;// 擦除扇区, 一次性擦除一个扇区512字节, 从0x0000开始, 0x01FF
//    EEPROM_SectorErase(u16 EE_address);EEPROM_SectorErase(addr_sector);//    // 写入数据. 字符串\int\long\float
    EEPROM_write_n(u16 EE_address,u8 *DataAddress,u16 number);EEPROM_write_n(addr_sector, str, str_length);// 读取数据. 字符串\int\long\float
//    EEPROM_read_n(u16 EE_address,u8 *DataAddress,u16 number);EEPROM_read_n(addr_sector, tmp, str_length);// 添加字符串结束符tmp[str_length] = '\0';printf(">>存储的字符串: %s\n", str);printf(">>读到的字符串: %s\n", tmp);if(strcmp(str, tmp) == 0){printf("两个字符串相等\n");}else {printf("两个字符串不等\n");}while(1) {}}

官方示例

串口命令设置: (命令字母不区分大小写)
● E 0x0040 --> 对0x0040地址扇区内容进行擦除.
● W 0x0040 1234567890 --> 对0x0040地址写入字符1234567890.
● R 0x0040 10 --> 对0x0040地址读出10个字节数据.

/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com  -----------------------------------------*/
/* --- QQ:  800003751 -------------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序            */
/*---------------------------------------------------------------------*/#include	"config.h"
#include	"STC8G_H_GPIO.h"
#include	"STC8G_H_UART.h"
#include	"STC8G_H_Delay.h"
#include	"STC8G_H_NVIC.h"
#include	"STC8G_H_EEPROM.h"
#include	"STC8G_H_Switch.h"/*************	本程序功能说明	**************本例程基于STC8H8K64U为主控芯片的实验箱8进行编写测试,STC8G、STC8H系列芯片可通用参考.通过串口对STC内部自带的EEPROM(FLASH)进行读写测试。对FLASH做扇区擦除、写入、读出的操作,命令指定地址。默认波特率:  115200,N,8,1. 串口命令设置: (命令字母不区分大小写)E 0x0040             --> 对0x0040地址扇区内容进行擦除.W 0x0040 1234567890  --> 对0x0040地址写入字符1234567890.R 0x0040 10          --> 对0x0040地址读出10个字节数据. 注意:下载时,下载界面"硬件选项"中设置用户EEPROM大小,并确保串口命令中的地址在EEPROM设置的大小范围之内。下载时, 选择时钟 22.1184MHz (可以在配置文件"config.h"中修改).******************************************/#define     Max_Length          100      //读写EEPROM缓冲长度/*************	本地常量声明	**************//*************	本地变量声明	**************/
u8  xdata   tmp[Max_Length];        //EEPROM操作缓冲/*************	本地函数声明	**************//*************  外部函数和变量声明 *****************//******************* IO配置函数 *******************/
void	GPIO_config(void)
{GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义GPIO_InitStructure.Pin  = GPIO_Pin_0 | GPIO_Pin_1;		//指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7GPIO_InitStructure.Mode = GPIO_PullUp;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PPGPIO_Inilize(GPIO_P3,&GPIO_InitStructure);	//初始化
}/***************  串口初始化函数 *****************/
void	UART_config(void)
{COMx_InitDefine		COMx_InitStructure;					//结构定义COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;	//模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTxCOMx_InitStructure.UART_BRT_Use   = BRT_Timer1;			//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)COMx_InitStructure.UART_BaudRate  = 115200ul;			//波特率, 一般 110 ~ 115200COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLECOMx_InitStructure.BaudRateDouble = DISABLE;			//波特率加倍, ENABLE或DISABLEUART_Configuration(UART1, &COMx_InitStructure);		//初始化串口1 UART1,UART2,UART3,UART4NVIC_UART1_Init(ENABLE,Priority_1);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}/**********************************************/u8	CheckData(u8 dat)
{if((dat >= '0') && (dat <= '9'))		return (dat-'0');if((dat >= 'A') && (dat <= 'F'))		return (dat-'A'+10);if((dat >= 'a') && (dat <= 'f'))		return (dat-'a'+10);return 0xff;
}//========================================================================
// 函数: u16    GetAddress(void)
// 描述: 计算各种输入方式的地址.
// 参数: 无.
// 返回: 16位EEPROM地址.
// 版本: V1.0, 2013-6-6
//========================================================================
u16 GetAddress(void)
{u16 address;u8  i,j;address = 0;if((RX1_Buffer[2] == '0') && (RX1_Buffer[3] == 'X')){for(i=4; i<8; i++){j = CheckData(RX1_Buffer[i]);if(j >= 0x10)   return 65535;   //erroraddress = (address << 4) + j;}return (address);}return  65535;  //error
}/**************** 获取要读出数据的字节数 ****************************/
u8 GetDataLength(void)
{u8  i;u8  length;length = 0;for(i=9; i<COM1.RX_Cnt; i++){if(CheckData(RX1_Buffer[i]) >= 10)  break;length = length * 10 + CheckData(RX1_Buffer[i]);}return (length);
}/********************* 主函数 *************************/
void main(void)
{u8  i,j;u16 addr;u8  status;EAXSFR();		/* 扩展寄存器访问使能 */GPIO_config();UART_config();EA = 1;PrintString1("STC8系列单片机EEPROM测试程序,串口命令设置如下:\r\n");    //UART1发送一个字符串PrintString1("E 0x0040             --> 对0x0040地址扇区内容进行擦除\xfd.\r\n");     //UART1发送一个字符串PrintString1("W 0x0040 1234567890  --> 对0x0040地址写入字符1234567890.\r\n");  //UART1发送一个字符串PrintString1("R 0x0040 10          --> 对0x0040地址读出10个字节内容.\r\n");    //UART1发送一个字符串while(1){delay_ms(1);if(COM1.RX_TimeOut > 0)		//超时计数{if(--COM1.RX_TimeOut == 0){for(i=0; i<COM1.RX_Cnt; i++)    TX1_write2buff(RX1_Buffer[i]);    //把收到的数据原样返回,用于测试status = 0xff;  //状态给一个非0值if((COM1.RX_Cnt >= 8) && (RX1_Buffer[1] == ' ')) //最短命令为8个字节{for(i=0; i<8; i++){if((RX1_Buffer[i] >= 'a') && (RX1_Buffer[i] <= 'z'))    RX1_Buffer[i] = RX1_Buffer[i] - 'a' + 'A';  //小写转大写}addr = GetAddress();if(addr < 63488)    //限制在0~123扇区{if(RX1_Buffer[0] == 'E')    //写入N个字节{EEPROM_SectorErase(addr);           //擦除扇区PrintString1("擦除\xfd成功!\r\n");status = 0; //命令正确}else if((RX1_Buffer[0] == 'W') && (RX1_Buffer[8] == ' '))    //写入N个字节{j = COM1.RX_Cnt - 9;if(j > Max_Length)  j = Max_Length; //越界检测//EEPROM_SectorErase(addr);           //擦除扇区EEPROM_write_n(addr,&RX1_Buffer[9],j);      //写N个字节PrintString1("已写入");if(j >= 100)    {TX1_write2buff(j/100+'0');   j = j % 100;}if(j >= 10)     {TX1_write2buff(j/10+'0');    j = j % 10;}TX1_write2buff(j%10+'0');PrintString1("字节!\r\n");status = 0; //命令正确}else if((RX1_Buffer[0] == 'R') && (RX1_Buffer[8] == ' '))   //PC请求返回N字节EEPROM数据{j = GetDataLength();if(j > Max_Length)  j = Max_Length; //越界检测if(j > 0){PrintString1("读出");TX1_write2buff(j/10+'0');TX1_write2buff(j%10+'0');PrintString1("个字节内容如下:\r\n");EEPROM_read_n(addr,tmp,j);for(i=0; i<j; i++)  TX1_write2buff(tmp[i]);TX1_write2buff(0x0d);TX1_write2buff(0x0a);status = 0; //命令正确}}}}if(status != 0) PrintString1("命令错误!\r\n");COM1.RX_Cnt = 0;}}}
} 
/**********************************************/

这篇关于嵌入式进阶——EEPROM读写的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1013737

相关文章

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

ShardingProxy读写分离之原理、配置与实践过程

《ShardingProxy读写分离之原理、配置与实践过程》ShardingProxy是ApacheShardingSphere的数据库中间件,通过三层架构实现读写分离,解决高并发场景下数据库性能瓶... 目录一、ShardingProxy技术定位与读写分离核心价值1.1 技术定位1.2 读写分离核心价值二

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python进阶之列表推导式的10个核心技巧

《Python进阶之列表推导式的10个核心技巧》在Python编程中,列表推导式(ListComprehension)是提升代码效率的瑞士军刀,本文将通过真实场景案例,揭示列表推导式的进阶用法,希望对... 目录一、基础语法重构:理解推导式的底层逻辑二、嵌套循环:破解多维数据处理难题三、条件表达式:实现分支

基于Python编写自动化邮件发送程序(进阶版)

《基于Python编写自动化邮件发送程序(进阶版)》在数字化时代,自动化邮件发送功能已成为企业和个人提升工作效率的重要工具,本文将使用Python编写一个简单的自动化邮件发送程序,希望对大家有所帮助... 目录理解SMTP协议基础配置开发环境构建邮件发送函数核心逻辑实现完整发送流程添加附件支持功能实现htm

基于Python实现进阶版PDF合并/拆分工具

《基于Python实现进阶版PDF合并/拆分工具》在数字化时代,PDF文件已成为日常工作和学习中不可或缺的一部分,本文将详细介绍一款简单易用的PDF工具,帮助用户轻松完成PDF文件的合并与拆分操作... 目录工具概述环境准备界面说明合并PDF文件拆分PDF文件高级技巧常见问题完整源代码总结在数字化时代,PD

javaSE类和对象进阶用法举例详解

《javaSE类和对象进阶用法举例详解》JavaSE的面向对象编程是软件开发中的基石,它通过类和对象的概念,实现了代码的模块化、可复用性和灵活性,:本文主要介绍javaSE类和对象进阶用法的相关资... 目录前言一、封装1.访问限定符2.包2.1包的概念2.2导入包2.3自定义包2.4常见的包二、stati

MySQL中读写分离方案对比分析与选型建议

《MySQL中读写分离方案对比分析与选型建议》MySQL读写分离是提升数据库可用性和性能的常见手段,本文将围绕现实生产环境中常见的几种读写分离模式进行系统对比,希望对大家有所帮助... 目录一、问题背景介绍二、多种解决方案对比2.1 原生mysql主从复制2.2 Proxy层中间件:ProxySQL2.3

C语言进阶(预处理命令详解)

《C语言进阶(预处理命令详解)》文章讲解了宏定义规范、头文件包含方式及条件编译应用,强调带参宏需加括号避免计算错误,头文件应声明函数原型以便主函数调用,条件编译通过宏定义控制代码编译,适用于测试与模块... 目录1.宏定义1.1不带参宏1.2带参宏2.头文件的包含2.1头文件中的内容2.2工程结构3.条件编

从入门到进阶讲解Python自动化Playwright实战指南

《从入门到进阶讲解Python自动化Playwright实战指南》Playwright是针对Python语言的纯自动化工具,它可以通过单个API自动执行Chromium,Firefox和WebKit... 目录Playwright 简介核心优势安装步骤观点与案例结合Playwright 核心功能从零开始学习