EEPROM
一.EEPROM简介
EEPROM(Electrically Erasable Programmable Read-Only Memory,电子可擦可编程只读存储器)是一种非易失性存储器,它可以在断电后保留数据。EEPROM通常用于存储需要长期保存的数据,如系统配置、用户设置等。
STC8G系列单片机内置了EEPROM,其容量为4K字节。EEPROM的读写操作需要通过特定的指令来完成。
二.示例代码
以下程序的代码的作用是,将EEPROM中的数据读取出来,并打印到串口上. 如果串口发送了数据,则将数据写入EEPROM中.
系统主系统时钟为11.0592MHz,波特率为9600.
关于串口的接收数据的方法,请参考: 串口通信
1.扇区删除函数
c
// EEPROM操作函数实现
void EEPROM_SectorErase(unsigned int addr) {
IAP_CONTR = 0x80; // 使能IAP
IAP_CMD = 0x03; // 扇区擦除命令
IAP_ADDRH = addr >> 8;
IAP_ADDRL = addr & 0xFF;
IAP_TRIG = 0x5A;
IAP_TRIG = 0xA5;
_nop_();
_nop_();
IAP_CONTR = 0x00; // 关闭IAP
}
2.字节写入函数
c
// EEPROM字节写入
void EEPROM_ByteWrite(unsigned int addr, unsigned char dat) {
IAP_CONTR = 0x80; // 使能IAP
IAP_CMD = 0x02; // 字节编程命令
IAP_ADDRH = addr >> 8;
IAP_ADDRL = addr & 0xFF;
IAP_DATA = dat;
IAP_TRIG = 0x5A;
IAP_TRIG = 0xA5;
_nop_();
_nop_();
IAP_CONTR = 0x00; // 关闭IAP
}
3.字节读取函数
c
// EEPROM字节读取
unsigned char EEPROM_ByteRead(unsigned int addr) {
unsigned char dat;
IAP_CONTR = 0x80; // 使能IAP
IAP_CMD = 0x01; // 字节读取命令
IAP_ADDRH = addr >> 8;
IAP_ADDRL = addr & 0xFF;
IAP_TRIG = 0x5A;
IAP_TRIG = 0xA5;
_nop_();
dat = IAP_DATA;
IAP_CONTR = 0x00; // 关闭IAP
return dat;
}
三.完整代码
c
#include "stc8g.h"
#include "intrins.h"
#include <string.h>
// EEPROM操作函数声明
void EEPROM_SectorErase(unsigned int addr);
void EEPROM_ByteWrite(unsigned int addr, unsigned char dat);
unsigned char EEPROM_ByteRead(unsigned int addr);
bit uartReceived = 0;
unsigned char receivedData = 0;
// 用户参数结构体
typedef struct {
unsigned int param1;
float param2;
char param3[16];
} UserParams;
// 串口中断服务函数
void UART_ISR() interrupt 4 {
if(RI) {
RI = 0; // 清除接收中断标志
receivedData = SBUF; // 读取接收到的数据
uartReceived = 1; // 设置接收标志
}
if(TI) {
TI = 0; // 清除发送中断标志
}
}
// 添加串口初始化函数
void UART_Init() {
SCON = 0x50; // 8位数据,可变波特率
AUXR |= 0x40; // 定时器1时钟为Fosc,即1T
AUXR &= 0xFE; // 串口1选择定时器1为波特率发生器
TMOD &= 0x0F; // 设定定时器1为16位自动重装方式
TL1 = 0xE0; // 设定定时初值
TH1 = 0xFE; // 设定定时初值
ET1 = 0; // 禁止定时器1中断
TR1 = 1; // 启动定时器1
}
// 串口发送一个字符
void UART_SendChar(char c) {
SBUF = c;
while(!TI);
TI = 0;
}
// 串口发送字符串
void UART_SendString(char *s) {
while(*s) {
UART_SendChar(*s++);
}
}
// EEPROM操作函数实现
void EEPROM_SectorErase(unsigned int addr) {
IAP_CONTR = 0x80; // 使能IAP
IAP_CMD = 0x03; // 扇区擦除命令
IAP_ADDRH = addr >> 8;
IAP_ADDRL = addr & 0xFF;
IAP_TRIG = 0x5A;
IAP_TRIG = 0xA5;
_nop_();
_nop_();
IAP_CONTR = 0x00; // 关闭IAP
}
// EEPROM字节写入
void EEPROM_ByteWrite(unsigned int addr, unsigned char dat) {
IAP_CONTR = 0x80; // 使能IAP
IAP_CMD = 0x02; // 字节编程命令
IAP_ADDRH = addr >> 8;
IAP_ADDRL = addr & 0xFF;
IAP_DATA = dat;
IAP_TRIG = 0x5A;
IAP_TRIG = 0xA5;
_nop_();
_nop_();
IAP_CONTR = 0x00; // 关闭IAP
}
// EEPROM字节读取
unsigned char EEPROM_ByteRead(unsigned int addr) {
unsigned char dat;
IAP_CONTR = 0x80; // 使能IAP
IAP_CMD = 0x01; // 字节读取命令
IAP_ADDRH = addr >> 8;
IAP_ADDRL = addr & 0xFF;
IAP_TRIG = 0x5A;
IAP_TRIG = 0xA5;
_nop_();
dat = IAP_DATA;
IAP_CONTR = 0x00; // 关闭IAP
return dat;
}
// 保存用户参数到EEPROM
void SaveUserParams(UserParams *params, unsigned int baseAddr) {
unsigned char *p = (unsigned char *)params;
unsigned int i;
// 先擦除整个扇区
EEPROM_SectorErase(baseAddr);
// 写入数据
for(i = 0; i < sizeof(UserParams); i++) {
EEPROM_ByteWrite(baseAddr + i, p[i]);
}
}
// 从EEPROM读取用户参数
void LoadUserParams(UserParams *params, unsigned int baseAddr) {
unsigned char *p = (unsigned char *)params;
unsigned int i;
for(i = 0; i < sizeof(UserParams); i++) {
p[i] = EEPROM_ByteRead(baseAddr + i);
}
}
void Delay1s() {
unsigned int i, j;
for(i = 0; i < 5000; i++) {
for(j = 0; j < 1000; j++) {
_nop_();
}
}
}
// 示例主函数
void main() {
UserParams params;
UserParams params2;
char str[10]; // 用于存储转换后的字符串
unsigned int eepromBaseAddr = 0x0000; // EEPROM起始地址
UART_Init();
// 添加这两行启用中断
ES = 1; // 使能串口中断
EA = 1; // 开启全局中断
// 初始化IAP等待时间
IAP_TPS = 12; // 根据系统时钟设置
// 修改参数
params.param1 = 1234;
params.param2 = 3.14f;
strcpy(params.param3, "STC8G1K08A");
// 保存修改后的参数
SaveUserParams(¶ms, eepromBaseAddr);
while(1) {
// 主循环
if(uartReceived){ // 检查是否有数据接收
uartReceived = 0; // 清除标志
params.param1 = receivedData;
// 保存修改后的参数
SaveUserParams(¶ms, eepromBaseAddr);
UART_SendString("Save Sucess\r\n");
}
// 从EEPROM加载参数
LoadUserParams(¶ms2, eepromBaseAddr);
// 打印参数
UART_SendString("Loaded User Params:\r\n");
UART_SendString("param1: ");
// 将param1转换为字符串并发送
sprintf(str, "%d", params2.param1); // 将param1转换为字符串
UART_SendString(str); // 发送转换后的字符串
UART_SendString("\r\n");
UART_SendString("param2: ");
// 将param2转换为字符串并发送
sprintf(str, "%.2f", params2.param2); // 将param2转换为字符串,保留两位小数
UART_SendString(str); // 发送转换后的字符串
UART_SendString("\r\n");
UART_SendString("param3: ");
UART_SendString(params2.param3);
UART_SendString("\r\n");
Delay1s(); // 添加1秒延时
}
}