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

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

设置EEPROM

STC8H8K64U的EEPROM可以在烧录的时候指定大小, 如下图
image.png

读写String字符串

  1. #include "Config.h"
  2. #include "UART.h"
  3. #include "EEPROM.h"
  4. #include <string.h>
  5. void UART_config(void) {
  6. // >>> 记得添加 NVIC.c, UART.c, UART_Isr.c <<<
  7. COMx_InitDefine COMx_InitStructure; //结构定义
  8. COMx_InitStructure.UART_Mode = UART_8bit_BRTx; //模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
  9. COMx_InitStructure.UART_BRT_Use = BRT_Timer1; //选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
  10. COMx_InitStructure.UART_BaudRate = 115200ul; //波特率, 一般 110 ~ 115200
  11. COMx_InitStructure.UART_RxEnable = ENABLE; //接收允许, ENABLE或DISABLE
  12. COMx_InitStructure.BaudRateDouble = DISABLE; //波特率加倍, ENABLE或DISABLE
  13. UART_Configuration(UART1, &COMx_InitStructure); //初始化串口1 UART1,UART2,UART3,UART4
  14. NVIC_UART1_Init(ENABLE,Priority_1); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
  15. UART1_SW(UART1_SW_P30_P31); // 引脚选择, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
  16. }
  17. #define Max_Length 100 //读写EEPROM缓冲长度
  18. u8 xdata tmp[Max_Length]; //EEPROM操作缓冲
  19. void main() {
  20. u16 addr_sector = 0x0000;
  21. char *str = "HelloWorld!abc123!";
  22. u16 str_length = strlen(str); // 获取str的长度
  23. UART_config();
  24. EA = 1;
  25. // 擦除扇区, 一次性擦除一个扇区512字节, 从0x0000开始, 0x01FF
  26. // EEPROM_SectorErase(u16 EE_address);
  27. EEPROM_SectorErase(addr_sector);
  28. // // 写入数据. 字符串\int\long\float
  29. //// EEPROM_write_n(u16 EE_address,u8 *DataAddress,u16 number);
  30. EEPROM_write_n(addr_sector, str, str_length);
  31. // 读取数据. 字符串\int\long\float
  32. // EEPROM_read_n(u16 EE_address,u8 *DataAddress,u16 number);
  33. EEPROM_read_n(addr_sector, tmp, str_length);
  34. // 添加字符串结束符
  35. tmp[str_length] = '\0';
  36. printf(">>存储的字符串: %s\n", str);
  37. printf(">>读到的字符串: %s\n", tmp);
  38. if(strcmp(str, tmp) == 0){
  39. printf("两个字符串相等\n");
  40. }else {
  41. printf("两个字符串不等\n");
  42. }
  43. while(1) {
  44. }
  45. }

官方示例

串口命令设置: (命令字母不区分大小写)

  • E 0x0040 —> 对0x0040地址扇区内容进行擦除.
  • W 0x0040 1234567890 —> 对0x0040地址写入字符1234567890.
  • R 0x0040 10 —> 对0x0040地址读出10个字节数据. ```c /——————————————————————————————————-/ / —- 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; //结构定义

  1. GPIO_InitStructure.Pin = GPIO_Pin_0 | GPIO_Pin_1; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
  2. GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
  3. GPIO_Inilize(GPIO_P3,&GPIO_InitStructure); //初始化

}

/* 串口初始化函数 */ void UART_config(void) { COMx_InitDefine COMx_InitStructure; //结构定义

  1. COMx_InitStructure.UART_Mode = UART_8bit_BRTx; //模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
  2. COMx_InitStructure.UART_BRT_Use = BRT_Timer1; //选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
  3. COMx_InitStructure.UART_BaudRate = 115200ul; //波特率, 一般 110 ~ 115200
  4. COMx_InitStructure.UART_RxEnable = ENABLE; //接收允许, ENABLE或DISABLE
  5. COMx_InitStructure.BaudRateDouble = DISABLE; //波特率加倍, ENABLE或DISABLE
  6. UART_Configuration(UART1, &COMx_InitStructure); //初始化串口1 UART1,UART2,UART3,UART4
  7. NVIC_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;

  1. address = 0;
  2. if((RX1_Buffer[2] == '0') && (RX1_Buffer[3] == 'X'))
  3. {
  4. for(i=4; i<8; i++)
  5. {
  6. j = CheckData(RX1_Buffer[i]);
  7. if(j >= 0x10) return 65535; //error
  8. address = (address << 4) + j;
  9. }
  10. return (address);
  11. }
  12. return 65535; //error

}

/** 获取要读出数据的字节数 **/ u8 GetDataLength(void) { u8 i; u8 length;

  1. length = 0;
  2. for(i=9; i<COM1.RX_Cnt; i++)
  3. {
  4. if(CheckData(RX1_Buffer[i]) >= 10) break;
  5. length = length * 10 + CheckData(RX1_Buffer[i]);
  6. }
  7. return (length);

}

/* 主函数 */ void main(void) { u8 i,j; u16 addr; u8 status;

  1. EAXSFR(); /* 扩展寄存器访问使能 */
  2. GPIO_config();
  3. UART_config();
  4. EA = 1;
  5. PrintString1("STC8系列单片机EEPROM测试程序,串口命令设置如下:\r\n"); //UART1发送一个字符串
  6. PrintString1("E 0x0040 --> 对0x0040地址扇区内容进行擦除\xfd.\r\n"); //UART1发送一个字符串
  7. PrintString1("W 0x0040 1234567890 --> 对0x0040地址写入字符1234567890.\r\n"); //UART1发送一个字符串
  8. PrintString1("R 0x0040 10 --> 对0x0040地址读出10个字节内容.\r\n"); //UART1发送一个字符串
  9. while(1)
  10. {
  11. delay_ms(1);
  12. if(COM1.RX_TimeOut > 0) //超时计数
  13. {
  14. if(--COM1.RX_TimeOut == 0)
  15. {
  16. for(i=0; i<COM1.RX_Cnt; i++) TX1_write2buff(RX1_Buffer[i]); //把收到的数据原样返回,用于测试
  17. status = 0xff; //状态给一个非0值
  18. if((COM1.RX_Cnt >= 8) && (RX1_Buffer[1] == ' ')) //最短命令为8个字节
  19. {
  20. for(i=0; i<8; i++)
  21. {
  22. if((RX1_Buffer[i] >= 'a') && (RX1_Buffer[i] <= 'z')) RX1_Buffer[i] = RX1_Buffer[i] - 'a' + 'A'; //小写转大写
  23. }
  24. addr = GetAddress();
  25. if(addr < 63488) //限制在0~123扇区
  26. {
  27. if(RX1_Buffer[0] == 'E') //写入N个字节
  28. {
  29. EEPROM_SectorErase(addr); //擦除扇区
  30. PrintString1("擦除\xfd成功!\r\n");
  31. status = 0; //命令正确
  32. }
  33. else if((RX1_Buffer[0] == 'W') && (RX1_Buffer[8] == ' ')) //写入N个字节
  34. {
  35. j = COM1.RX_Cnt - 9;
  36. if(j > Max_Length) j = Max_Length; //越界检测
  37. //EEPROM_SectorErase(addr); //擦除扇区
  38. EEPROM_write_n(addr,&RX1_Buffer[9],j); //写N个字节
  39. PrintString1("已写入");
  40. if(j >= 100) {TX1_write2buff(j/100+'0'); j = j % 100;}
  41. if(j >= 10) {TX1_write2buff(j/10+'0'); j = j % 10;}
  42. TX1_write2buff(j%10+'0');
  43. PrintString1("字节!\r\n");
  44. status = 0; //命令正确
  45. }
  46. else if((RX1_Buffer[0] == 'R') && (RX1_Buffer[8] == ' ')) //PC请求返回N字节EEPROM数据
  47. {
  48. j = GetDataLength();
  49. if(j > Max_Length) j = Max_Length; //越界检测
  50. if(j > 0)
  51. {
  52. PrintString1("读出");
  53. TX1_write2buff(j/10+'0');
  54. TX1_write2buff(j%10+'0');
  55. PrintString1("个字节内容如下:\r\n");
  56. EEPROM_read_n(addr,tmp,j);
  57. for(i=0; i<j; i++) TX1_write2buff(tmp[i]);
  58. TX1_write2buff(0x0d);
  59. TX1_write2buff(0x0a);
  60. status = 0; //命令正确
  61. }
  62. }
  63. }
  64. }
  65. if(status != 0) PrintString1("命令错误!\r\n");
  66. COM1.RX_Cnt = 0;
  67. }
  68. }
  69. }

} /**/ ```