SST89E516RD控制器IAP实现Flash变量读写及示例代码咨询
SST89E516RD IAP实现Flash读写单个char值方案
核心问题说明
用CODE关键字定义的变量是编译时固化到只读Flash区域的,运行时无法直接修改,这就是你遇到“未修改值错误”的原因。必须通过SST89E516RD的IAP自编程功能操作Flash可擦写区域,才能实现变量的掉电保存。
关键前置知识
1. Flash分区与安全锁
SST89E516RD的Flash分为两个主块:
- 主块0(0x0000-0x7FFF):默认存储主程序
- 主块1(0x8000-0xFFFF):可划分为IAP专用存储区(注意不要覆盖主程序)
安全锁默认锁定,需通过特定指令序列解锁才能执行擦写操作。
2. KEIL配置要点
- 在工程
Target选项中启用Enable IAP Functions(新版KEIL可能在IAP Options子菜单) - 配置链接脚本,将IAP代码与Flash存储区分开,避免擦写时破坏主程序
步骤拆解与代码实现
1. 解锁Flash安全锁
向固定地址写入解锁序列:
#define FLASH_UNLOCK_ADDR1 0x5555 #define FLASH_UNLOCK_ADDR2 0x2AAA #define UNLOCK_CMD1 0xAA #define UNLOCK_CMD2 0x55 void Flash_Unlock(void) { unsigned char xdata *unlock_addr; // 发送第一组解锁指令 unlock_addr = (unsigned char xdata *)FLASH_UNLOCK_ADDR1; *unlock_addr = UNLOCK_CMD1; // 发送第二组解锁指令 unlock_addr = (unsigned char xdata *)FLASH_UNLOCK_ADDR2; *unlock_addr = UNLOCK_CMD2; }
2. Flash扇区擦除
Flash只能从1写0,写入前必须先擦除目标扇区(每个扇区512字节):
#define FLASH_SECTOR_ERASE_CMD 0x80 #define FLASH_ERASE_CONFIRM 0x10 // addr为扇区起始地址,必须是512的倍数 void Flash_EraseSector(unsigned int addr) { unsigned char xdata *erase_addr; Flash_Unlock(); // 发送扇区擦除命令 erase_addr = (unsigned char xdata *)FLASH_UNLOCK_ADDR1; *erase_addr = FLASH_SECTOR_ERASE_CMD; Flash_Unlock(); // 确认擦除并指定扇区地址 erase_addr = (unsigned char xdata *)addr; *erase_addr = FLASH_ERASE_CONFIRM; // 等待擦除完成(PSW.7置1表示Flash忙) while(PSW & 0x80); }
3. 写入单个char值到Flash
#define FLASH_WRITE_CMD 0xA0 // 存储区起始地址(选主块1的空闲扇区,示例用0x8000) #define STORAGE_ADDR 0x8000 void Flash_WriteChar(unsigned int addr, unsigned char data) { unsigned char xdata *write_addr; Flash_Unlock(); // 发送写入命令 write_addr = (unsigned char xdata *)FLASH_UNLOCK_ADDR1; *write_addr = FLASH_WRITE_CMD; // 写入数据到指定地址 write_addr = (unsigned char xdata *)addr; *write_addr = data; // 等待写入完成 while(PSW & 0x80); }
4. 从Flash读取char值
读取无需解锁,直接访问地址即可:
unsigned char Flash_ReadChar(unsigned int addr) { unsigned char code *read_addr; read_addr = (unsigned char code *)addr; return *read_addr; }
5. 完整使用示例
void main(void) { unsigned char save_data = 0x12; unsigned char read_data; // 首次写入或更新前必须擦除目标扇区 Flash_EraseSector(STORAGE_ADDR); // 写入数据到Flash Flash_WriteChar(STORAGE_ADDR, save_data); // 从Flash读取数据 read_data = Flash_ReadChar(STORAGE_ADDR); // 验证读写结果 if(read_data == save_data) { // 读写成功,执行后续逻辑 } while(1); }
注意事项
- 地址合法性:存储地址必须选在主程序未占用的区域,可通过KEIL的
Linker选项设置Code Range规避冲突 - 擦写寿命:SST89E516RD的Flash擦写寿命约10000次,频繁写入需做磨损均衡处理
- 电源要求:Flash擦写过程中不能掉电,否则会损坏存储内容
- 重新锁定安全锁:如需锁定Flash,可向解锁地址写入序列:0xAA->0x55->0xFA
内容的提问来源于stack exchange,提问作者veerendra prasad
相关产品推荐
相关产品推荐

