咨询掉电自动存储设计方案
您好,项目使用了STC8H8K64U芯片,现在有一个电能参数,需要再检测到设备掉电时,自动保存一次,请推荐一个比较简便的方案,尽量不增加外部器件,谢谢!完整的系统设计参考原理图@8H8K64U, @32G12K128 - 电源/复位/省电模式/外部晶振/内部时钟/对外时钟输出/PLL-144MHz时钟 国芯人工智能技术交流网站 - AI32位8051交流社区
EEPROM的使用 请 配合比较器做掉电检测 | 唯一正解,电力系统标准应用 - EEPROM/DataFlash 国芯人工智能技术交流网站 - AI32位8051交流社区
啥也不需要,打开低压中断就行了,好用的很 程序开始运行时就准备一块擦除后的EEPROM扇区,然后在低压中断里写入EEPROM,这样可以较为快速的保存。
低压检测电压设置到最高,提前测一下掉电时VCC电压下降的曲线,看低压中断到保存参数完成的时间够不够,多留点余量。 xiaobendan 发表于 2026-5-7 13:04
啥也不需要,打开低压中断就行了,好用的很
您好,低压中断是哪个中断,能发一下吗?谢谢
etec 发表于 2026-5-7 14:33
您好,低压中断是哪个中断,能发一下吗?谢谢
本示例主要针对频繁掉电保存重要数据设计的方案,由于内置EEPROM有擦除次数寿命限制,本方案可以延寿百倍(理论值)。限制条件是保存的数据不可以等于0xff。因为EEPROM只可写0不可写1,只有擦除扇区才全部置1。
//测试条件:STC8H实验板,MCU型号STC8H3K48S2
//注意:测试本示例时,需在ISP下载时将【允许低压复位(禁止低压中断)】关闭
#include <STC8H.H>
#include <intrins.h> //库头文件
#define uint unsigned int //宏定义数据类型uint
#define uchar unsigned char //宏定义数据类型uchar
#define IAP_ADDRESS 0x0000 //测试地址
//顺序共阴极数码管段码表,段码a-h顺序接PX0-PX7
uchar code table[]={//共阴数码管段码"0~f-."
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x40,0x80};
uchar data dis_buf; //缓存数组
uintnum,sec;
uchar i;
uintsign;
voidTimer0Init(); //定时器初始化声明
voidIapIdle(); //关闭IAP/EEPROM
uchar IapRead(uint addr); //读取EEPROM数据
voidIapProgram(uint addr, uchar dat);//写入EEPROM数据
voidIapErase(uint addr); //擦除EEPROM扇区
//初始化单片机端口
void McuInit()
{
P0M0 = 0xff; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P6M0 = 0x00; P6M1 = 0x00;
P7M0 = 0x00; P7M1 = 0x00;
}
//关闭单片机端口
void McuSleep()
{
P0M0 = 0x00; P0M1 = 0xff;
P1M0 = 0x00; P1M1 = 0xff;
P2M0 = 0x00; P2M1 = 0xff;
P3M0 = 0x00; P3M1 = 0xff;
P4M0 = 0x00; P4M1 = 0xff;
P5M0 = 0x00; P5M1 = 0xff;
P6M0 = 0x00; P6M1 = 0xff;
P7M0 = 0x00; P7M1 = 0xff;
}
void main()
{
McuInit();
if(IapRead(IAP_ADDRESS)==0xff)//如果没有保存过数据
{
IapProgram(IAP_ADDRESS, 0);//扇区首地址写0
sec=0;
sign=1;
}
else
{
// for(i=1;i<12;i++) //测试写10次
for(i=1;i<511;i++) //测试写满510个字节
{
if(IapRead(IAP_ADDRESS+i)==0xff)//如果遇到没有保存数据的单元
{
sec=IapRead(IAP_ADDRESS+i-1);//读取前一个字节保存的数据
sign=i; //地址缓存
break; //跳出循环
}
}
}
// if(sign==11) //测试写10次
if(sign==510) //如果写满510
{
IapErase(IAP_ADDRESS); //擦除扇区
IapProgram(IAP_ADDRESS, 0);//首地址写0
sign=1;
}
PCON &= 0xDF; //清0掉电标志
ELVD = 1; //开低压中断
EA = 1; //开总中断
Timer0Init(); //初始化定时器
while(1)
{
if(TF0) //查询T0中断请求标志
{
TF0=0; //T0中断请求标志清0
if(++num>=1000) //1秒
{
num=0;
sec=++sec%250;
}
dis_buf=table;
dis_buf=table;
dis_buf=table;
P0=0x00; //段消隐
P2=~(0x01<<i); //送段码
P0=dis_buf; //送位码
i=++i%3; //循环计数
}//耗时569us
}
}
void PowerLost() interrupt 6 //低压中断
{
EA = 0; //关闭总中断
McuSleep(); //关闭所有端口(停止所有耗电电路)
IapProgram(IAP_ADDRESS+sign,sec);//写数据到EEPROM
while((PCON & 0x20) != 0) //复查低压标志
{
PCON &= 0xDF; //清除低压标志
_nop_();
_nop_(); //坐等掉电
}
IAP_CONTR = 0x20; //发现是误报,重启单片机,恢复正常工作
}
void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初始值
TH0 = 0xD4; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
//关闭IAP/EEPROM
void IapIdle()
{
IAP_CONTR = 0; //关闭IAP功能
IAP_CMD = 0; //清除命令寄存器
IAP_TRIG = 0; //清除触发寄存器
IAP_ADDRH = 0x80; //将地址设置到非IAP区域
IAP_ADDRL = 0;
}
//读取EEPROM数据
uchar IapRead(uint addr)
{
uchar dat;
IAP_CONTR = 0x80; //使能IAP
IAP_TPS = 12; //设置等待参数12MHz
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;
}
//写入EEPROM数据
void IapProgram(uint addr, uchar dat)
{
IAP_CONTR = 0x80; //使能IAP
IAP_TPS = 12; //设置等待参数12MHz
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(uint addr)
{
IAP_CONTR = 0x80; //使能IAP
IAP_TPS = 12; //设置等待参数12MHz
IAP_CMD = 3; //设置IAP擦除命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //
IapIdle(); //关闭IAP功能
}
好的,谢谢,我看下
etec 发表于 2026-5-7 17:09
好的,谢谢,我看下
下载工具里面设置低压检测电压选最高的 etec 发表于 2026-5-7 17:09
好的,谢谢,我看下
提醒:第100行与第101行的注释颠倒 感谢!
页:
[1]
2