根据坛友的示例经修改实测成功,利用编程技巧不需要多大电容。TX-1C实验板上外围元件不少,电源滤波电容仅10uf,能够掉电后可靠保存2个字节(没有做保存更多字节试验)。测试掉电后能维持2.5ms。如需要保存更多字节应该要适当增大电容。
- //测试条件:TX-1C实验板,MCU型号IAP15W4K58S4,系统时钟11.0592MHz
- //注意:测试本示例时,需在ISP下载时将低压复位功能和低压时禁止EEPROM操作关闭
- #include "STC15Fxxxx.H"
- #include <intrins.h> //库头文件
- #define uint unsigned int //宏定义数据类型uint
- #define uchar unsigned char //宏定义数据类型uchar
- //宏定义ISP的操作命令
- #define CMD_IDLE 0 //空闲模式
- #define CMD_READ 1 //IAP字节读命令
- #define CMD_PROGRAM 2 //IAP字节编程命令
- #define CMD_ERASE 3 //IAP扇区擦除命令
- #define ENABLE_IAP 0x82 //CPU的等待时间
- #define IAP_ADDRESS 0x0800 //测试地址
- sbit duan=P2^6;
- sbit wein=P2^7;
- //顺序共阴极数码管段码表,段码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[8]; //缓存数组
- uint num,sec;
- uchar i;
- void Timer0Init(); //定时器初始化声明
- void IapIdle(); //关闭IAP/EEPROM
- uchar IapReadByte(uint addr); //读取EEPROM数据
- void IapProgramByte(uint addr, uchar dat);//写入EEPROM数据
- void IapEraseSector(uint addr); //擦除EEPROM数据
- void main()
- {
- P0M0 = 0x00;
- 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;
- sec=IapReadByte(IAP_ADDRESS)<<8|IapReadByte(IAP_ADDRESS+1);//读取保存的数据 用时11.75us
- if(sec==0xffff)//如果没有保存数据
- sec=0;//变量为0
- else IapEraseSector(IAP_ADDRESS);//擦除数据,为下次掉电保存数据做准备
-
- PCON &= 0xDF;//清0掉电标志
- ELVD = 1;//开低压中断
- EA = 1;//开总中断
- Timer0Init();//初始化定时器
- while(1)
- {
- if(TF0)//查询T0中断请求标志
- {
- TF0=0;//T0中断请求标志清0
- if(++num>=1000)//1秒
- {
- num=0;
- sec++;
- }
- dis_buf[0]=table[sec/10000%10];
- dis_buf[1]=table[sec/1000%10];
- dis_buf[2]=table[sec/100%10];
- dis_buf[3]=table[sec/10%10];
- dis_buf[4]=table[sec%10];
- //5位数码管动态显示
- P0=0x00;duan=1;duan=0;
- P0=~(0x01<<i);wein=1;wein=0;
- P0=dis_buf[i];duan=1;duan=0;
- i=++i%5;
- }
- }
- }
- void Timer0Init(void) //1毫秒@11.0592MHz
- {
- AUXR |= 0x80; //定时器时钟1T模式
- TMOD &= 0xF0; //设置定时器模式
- TL0 = 0xCD; //设置定时初始值
- TH0 = 0xD4; //设置定时初始值
- TF0 = 0; //清除TF0标志
- TR0 = 1; //定时器0开始计时
- }
- /*----------------------------
- 关闭IAP功能
- ----------------------------*/
- void IapIdle()
- {
- IAP_CONTR = 0; //关闭IAP功能
- IAP_CMD = 0; //清除命令寄存器
- IAP_TRIG = 0; //清除触发寄存器
- IAP_ADDRH = 0x80; //将地址设置到非IAP区域
- IAP_ADDRL = 0;
- }
- /*----------------------------
- 从ISP/IAP/EEPROM区域读取一字节
- ----------------------------*/
- uchar IapReadByte(uint addr)
- {
- uchar dat; //数据缓冲区
- IAP_CONTR = ENABLE_IAP; //使能IAP
- IAP_CMD = CMD_READ; //设置IAP命令
- IAP_ADDRL = addr; //设置IAP低地址
- IAP_ADDRH = addr >> 8; //设置IAP高地址
- IAP_TRIG = 0x5a; //写触发命令(0x5a)
- IAP_TRIG = 0xa5; //写触发命令(0xa5)
- _nop_(); //等待ISP/IAP/EEPROM操作完成
- dat = IAP_DATA; //读ISP/IAP/EEPROM数据
- IapIdle(); //关闭IAP功能
- return dat; //返回
- }
- /*-------------------------------
- 写一字节数据到ISP/IAP/EEPROM区域
- --------------------------------*/
- void IapProgramByte(uint addr, uchar dat)
- {
- IAP_CONTR = ENABLE_IAP; //使能IAP
- IAP_CMD = CMD_PROGRAM; //设置IAP命令
- IAP_ADDRL = addr; //设置IAP低地址
- IAP_ADDRH = addr >> 8; //设置IAP高地址
- IAP_DATA = dat; //写ISP/IAP/EEPROM数据
- IAP_TRIG = 0x5a; //写触发命令(0x5a)
- IAP_TRIG = 0xa5; //写触发命令(0xa5)
- _nop_(); //等待ISP/IAP/EEPROM操作完成
- IapIdle(); //关闭IAP功能
- }
- /*----------------------------
- ISP/IAP/EEPROM扇区擦除
- ----------------------------*/
- void IapEraseSector(uint addr)
- {
- IAP_CONTR = ENABLE_IAP; //使能IAP
- IAP_CMD = CMD_ERASE; //设置IAP命令
- IAP_ADDRL = addr; //设置IAP低地址
- IAP_ADDRH = addr >> 8; //设置IAP高地址
- IAP_TRIG = 0x5a; //写触发命令(0x5a)
- IAP_TRIG = 0xa5; //写触发命令(0xa5)
- _nop_(); //等待ISP/IAP/EEPROM操作完成
- IapIdle(); //关闭IAP功能
- }
- void PowerLost() interrupt 6 //剩余电量从中断开始到完全断电2.5ms
- {
- EA = 0; //关闭总中断
- P0M1 = 0xff; //所有端口高阻用时2.75us
- P1M1 = 0xff;
- P2M1 = 0xff;
- P3M1 = 0xff;
- P4M1 = 0xff;
- P5M1 = 0xff;
- P6M1 = 0xff;
- P7M1 = 0xff;
- IapProgramByte(IAP_ADDRESS,sec>>8);//写数据高8位到EEPROM
- IapProgramByte(IAP_ADDRESS+1,sec);//写数据低8位到EEPROM 写两个字节用时215.25us
- while((PCON & 0x20) != 0) //复查低压标志
- {
- PCON &= 0xDF; //清除低压标志
- _nop_();
- _nop_(); //坐等掉电
- }
- IAP_CONTR = 0x20; //发现是误报,重启单片机,恢复正常工作
- }
复制代码
|