1301 字
7 分钟
STC EEPROM基础操作
前言
MCU:STC8G1K08-16Pin(DIP-16)
STC8G 系列单片机内部都集成了大容量的 EEPROM。利用 ISP/IAP 技术可将内部 Data Flash 当 EEPROM,擦写次数在 10 万次以上。EEPROM 可分为若干个扇区,每个扇区包含 512 字节。
以 STC8G1K08 为例,芯片集成了 4K(即 4096 Byte) 的 EEPROM (0000h ~ 0FFFh)。
详见 STC8G 芯片手册:15 IAP/EEPROM/DATA-FLASH
擦除操作
在了解擦除操作前,需要了解:EEPROM 的写操作只能将 1 写为 0,如果需要将 0 写为 1,就必须先擦除整个扇区。
IAP_CONTR,EEPROM 控制寄存器。
IAP_TRIG,EEPROM 触发寄存器,每次对 EEPROM 操作后都需要按顺序写入 0x5a 和 0xa5,才能生效。
IAP_ADDRH 和 IAP_ADDRL,分别是 EEPROM 地址的高8位和低8位。
- 以 STC8G1K08 为例,IAP_ADDR 的范围在 0000h ~ 0FFFh
IAP_TPS = SYSCLK / 1000000,EEPROM 等待时间空间寄存器。
- 如果芯片工作频率是 11.0592MHz,IAP_TPS 就设置为 11
- 如果芯片工作频率是 12MHz,IAP_TPS 就设置为 12
- 小数部分四舍五入取整
/* * void IapIdle() * @brief 关闭 IAP 功能 */void IapIdle(){ IAP_CONTR = 0; // 15.2.5 禁止 EEPROM 操作 IAP_CMD = 0; // 15.2.3 空操作 清除命令寄存器 IAP_TRIG = 0; // 15.2.4 清除触发寄存器 IAP_ADDRH = 0x80; // 15.2.2 将地址设置到非IAP区域 IAP_ADDRL = 0;}
/* * void IapErase(int addr) * @brief 擦除 addr 所在扇区 */void IapErase(int addr){ IAP_CONTR = 0x80; // 15.2.5 使能 EEPROM 操作 IAP_TPS = 11; // 15.2.6 设置等待参数11.0592MHz IAP_CMD = 0x03; // 15.2.3 设置IAP擦除命令 IAP_ADDRL = addr; //设置IAP低地址 IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a) IAP_TRIG = 0xa5; //写触发命令(0xa5) _nop_(); IapIdle(); //关闭IAP功能}
写操作
写操作前先擦除目标地址所在区块,以保证目标地址的原始数据是 0xFF!
IAP_DATA,EEPROM 数据寄存器(8 bit)。
/* * void IapProgram(int addr, char dat) * @brief 在 addr 处写入 dat 字节 */void IapProgram(int addr, char dat){ IAP_CONTR = 0x80; //使能IAP IAP_TPS = 11; //设置等待参数11.0592MHz IAP_CMD = 2; //设置IAP写命令 IAP_ADDRL = addr; //设置IAP低地址 IAP_ADDRH = addr >> 8; //设置IAP高地址 IAP_DATA = dat; //写IAP数据 IAP_TRIG = 0x5a; //写触发命令(0x5a) IAP_TRIG = 0xa5; //写触发命令(0xa5) _nop_(); IapIdle(); //关闭IAP功能}
读操作
/* * char IapRead(int addr) * @brief 读取在 addr 处的字节数据 */char IapRead(int addr){ char dat;
IAP_CONTR = 0x80; //使能IAP IAP_TPS = 11; //设置等待参数11.0592MHz IAP_CMD = 1; //设置IAP读命令 IAP_ADDRL = addr; //设置IAP低地址 IAP_ADDRH = addr >> 8; //设置IAP高地址 IAP_TRIG = 0x5a; //写触发命令(0x5a) IAP_TRIG = 0xa5; //写触发命令(0xa5) _nop_(); dat = IAP_DATA; //读IAP数据 IapIdle(); //关闭IAP功能
return dat;}
完整代码
代码 - 点击查看详情
#include <STC8G.h>#include <intrins.h>
/* * void IapIdle() * @brief 关闭 IAP 功能 */void IapIdle(){ IAP_CONTR = 0; // 15.2.5 禁止 EEPROM 操作 IAP_CMD = 0; // 15.2.3 空操作 清除命令寄存器 IAP_TRIG = 0; // 15.2.4 清除触发寄存器 IAP_ADDRH = 0x80; // 15.2.2 将地址设置到非IAP区域 IAP_ADDRL = 0;}
/* * char IapRead(int addr) * @brief 读取在 addr 处的字节数据 */char IapRead(int addr){ char dat;
IAP_CONTR = 0x80; //使能IAP IAP_TPS = 11; //设置等待参数11.0592MHz IAP_CMD = 1; //设置IAP读命令 IAP_ADDRL = addr; //设置IAP低地址 IAP_ADDRH = addr >> 8; //设置IAP高地址 IAP_TRIG = 0x5a; //写触发命令(0x5a) IAP_TRIG = 0xa5; //写触发命令(0xa5) _nop_(); dat = IAP_DATA; //读IAP数据 IapIdle(); //关闭IAP功能
return dat;}
/* * void IapProgram(int addr, char dat) * @brief 在 addr 处写入 dat 字节 */void IapProgram(int addr, char dat){ IAP_CONTR = 0x80; //使能IAP IAP_TPS = 11; //设置等待参数11.0592MHz IAP_CMD = 2; //设置IAP写命令 IAP_ADDRL = addr; //设置IAP低地址 IAP_ADDRH = addr >> 8; //设置IAP高地址 IAP_DATA = dat; //写IAP数据 IAP_TRIG = 0x5a; //写触发命令(0x5a) IAP_TRIG = 0xa5; //写触发命令(0xa5) _nop_(); IapIdle(); //关闭IAP功能}
/* * void IapErase(int addr) * @brief 擦除 addr 所在扇区 */void IapErase(int addr){ IAP_CONTR = 0x80; // 15.2.5 使能 EEPROM 操作 IAP_TPS = 11; // 15.2.6 设置等待参数11.0592MHz IAP_CMD = 0x03; // 15.2.3 设置IAP擦除命令 IAP_ADDRL = addr; //设置IAP低地址 IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a) IAP_TRIG = 0xa5; //写触发命令(0xa5) _nop_(); IapIdle(); //关闭IAP功能}
bit busy = 0;
void UartIsr() interrupt 4{ if (TI) { TI = 0; busy = 0; } if (RI) { RI = 0; }}
void UartSend(char dat){ while (busy); busy = 1; SBUF = dat;}
void UartSendStr(char *p){ while (*p) { UartSend(*p++); }}
void TimeInit(void){ AUXR = 0x40; TMOD = 0x00; SCON = 0x50;
TL1 = 0xE8; TH1 = 0xFF;
ET1 = 0; TR1 = 1; ES = 1;
EA = 1;}
void Delay1000ms() //@11.0592MHz{ unsigned char i, j, k;
i = 57; j = 27; k = 112; do { do { while (--k); } while (--j); } while (--i);}
char EEPROM_Dat;
void main(){ P1M0 = 0x00; P1M1 = 0x00; P3M0 = 0x00; P3M1 = 0x00; P5M0 = 0x00; P5M1 = 0x00;
TimeInit(); Delay1000ms(); Delay1000ms();
UartSendStr("0000"); Delay1000ms(); Delay1000ms();
/* STC8G1K08 * EEPROM 0000h ~ 0FFFh 4K */ //擦除 0x0400 所在扇区 IapErase(0x0400); EEPROM_Dat = IapRead(0x0400); UartSend(EEPROM_Dat); Delay1000ms();
//在 0x0400 和 0x0401 处写入字节 0x12 和 0x0c IapProgram(0x0400, 0x12); IapProgram(0x0401, 0x0c);
//读取在 0x0400 和 0x0401 处的数据,并通过串口发送 EEPROM_Dat = IapRead(0x0400); UartSend(EEPROM_Dat); Delay1000ms();
EEPROM_Dat = IapRead(0x0401); UartSend(EEPROM_Dat); Delay1000ms();
while (1);}
STC EEPROM基础操作
https://fuwari.vercel.app/posts/嵌入式/stc/stc-eeprom基础操作/