用中颖8位MCU做产品的人,十有**会在EEPROM上栽跟头。不是写进去的数据读出来不对,就是程序莫名其妙跑飞了,更有甚者整个扇区的数据都丢了。很多人把问题归咎于芯片质量,其实八成是操作流程没卡准时序要求。中颖的类EEPROM和真正的EEPROM有本质区别,它是用Flash模拟的,擦除和写入必须按扇区操作,不能按单个字节随意改写。
先看几个硬指标。中颖Flash型MCU的类EEPROM区域,编程和擦除次数至少是10万次,数据保存年限至少10年。听起来很耐用,但有个致命限制,要向某个地址写入新数据,必须先擦除整个扇区,每个扇区通常是512字节,早期产品是256字节。这和真正的EEPROM完全不同,后者可以按字节改写,而这个必须整块擦除再写入,操作之前一定要做好数据备份规划。
操作类EEPROM有两条铁律,第一条是必须关闭所有中断。在擦除或写入期间,任何中断响应都可能打断SSP扇区自编程流程,导致数据错乱甚至程序跑飞。正确做法是用_push_(IEN0)保存中断状态,然后IEN0 &= 0x7F关总中断,操作完成后再用_pop_(IEN0)恢复。第二是操作前清看门狗,用RSTSTAT = 0防止操作期间看门狗超时复位。
下面这段代码是中颖官方的扇区擦除例程,来自SH79F9476的数据手册
c
void EEPromSectorErase(UCHAR nAddrH)
{
uchar ssp_flag = 0xA5;
_push_(IEN0);
IEN0 &= 0x7F; // 关闭总中断
FLASHCON = 0x01; // FAC位置1,访问EEPROM区
RSTSTAT = 0; // 清看门狗
XPAGE = nAddrH << 1; // 扇区地址左移1位
IB_CON1 = 0xE6;
IB_CON2 = 0x05;
IB_CON3 = 0x0A;
IB_CON4 = 0x09;
if(ssp_flag != 0xA5) // 抗干扰判断
goto Error;
IB_CON5 = 0x06;
_nop_();_nop_();_nop_();_nop_(); // 等待编程完成
Error:
ssp_flag = 0;
IB_CON1 = 0x00; // 清除控制寄存器
FLASHCON = 0x00; // 切回主Flash区
_pop_(IEN0); // 恢复中断
}
代码里有个容易被忽略的细节,XPAGE = nAddrH << 1这句,擦除地址需要左移一位才能正确映射到扇区起始位置。ssp_flag判读机制用来防干扰,如果标志位在操作过程中被篡改,程序会跳过写入步骤直接退出,避免错误数据污染EEPROM。
EEPROM的访问切换靠寄存器FLASHCON的FAC位来控制,FAC为0时MOVC指令访问主Flash程序区,FAC为1时访问类EEPROM区。记住每次操作结束后把FAC清零切回主Flash区,否则后续程序读取常量或查表时会读到错误数据,这个坑很多人踩过却找不到原因。写单字节时先擦除整个扇区再写入数据,如果扇区里还有其他有效数据,需要先读到RAM缓冲里,擦除后再连同新数据一起写回去。掉电存储场景里要开启低电压检测中断,在中断里尽量少写数据,只保存最关键的状态变量就退出,避免电压跌落过程中写入一半导致数据损坏。 |
|