8H2K08U, 8H2K12U, 8H2K17U
8H2K32U
===以上这几个型号开始,CPU 复位, 不同步复位 RTC ======================================= 其他早期单片机的RTC模块,在单片机复位后RTC相关的特殊功能寄存器也会复位 本例程主要用于解决这些早期的MCU, ISP下载后用户的RTC参数被复位丢失的问题 解决思路:ISP下载前,先将RTC相关参数通过ISP下载软件的用户接口上传到PC保存, 等待ISP下载完成后,下载软件再将保存的相关参数写入到FLASH的指定地址(范例中指定的地址为FE0000H)。 ISP下载完成后会立即运行用户代码,用户程序在初始化RTC寄存器时, 可从FLASH的指定地址中读取之前上传的RTC相关参数对RTC寄存器进行初始化, 即可实现不停电下载保持RTC参数的目的。
- #include "stc8h.h"
- #include "intrins.h"
-
- #define FOSC 11059200UL
- #define BAUD (65536 - FOSC/4/115200)
-
- typedef bit BOOL;
- typedef unsigned char BYTE;
-
- struct RTC_INIT
- {
- BYTE bValidTag; //数据有效标志(0x5a)
- BYTE bIniYear; //年(RTC初始化值)
- BYTE bIniMonth; //月
- BYTE bIniDay; //日
- BYTE bIniHour; //时
- BYTE bIniMinute; //分
- BYTE bIniSecond; //秒
- BYTE bIniSSecond; //次秒
- BYTE bAlaHour; //时(RTC闹钟设置值)
- BYTE bAlaMinute; //分
- BYTE bAlaSecond; //秒
- BYTE bAlaSSecond; //次秒
- };
-
- struct RTC_INIT code InitBlock _at_ 0xfe00;
-
- void SysInit();
- void UartInit();
- void RTCInit();
- void SendUart(BYTE dat);
- void UnpackCmd(BYTE dat);
- void IapProgram(int addr, char dat);
-
- BOOL fUartBusy;
- BOOL fFetchRtc;
- BOOL fReset2Isp;
- BYTE bUartStage;
-
- BYTE bDump[7];
-
- void main()
- {
- SysInit(); //系统初始化
- UartInit();
- RTCInit();
- EA = 1;
-
- fUartBusy = 0;
- fFetchRtc = 0;
- fReset2Isp = 0;
- bUartStage = 0;
-
- while (1)
- {
- if (fFetchRtc) //获取RTC数据请求
- {
- fFetchRtc = 0;
-
- RTCCR = 0; //上传当前的RTC值时,必须临时停止RTC,以免发生进位错误
- bDump[0] = YEAR; //快速将当前的RTC值缓存,以缩短RTC暂停的时间,减小误差
- bDump[1] = MONTH;
- bDump[2] = DAY;
- bDump[3] = HOUR;
- bDump[4] = MIN;
- bDump[5] = SEC;
- bDump[6] = SSEC;
- RTCCR = 1;
-
- SendUart(0x5a); //上传12字节RTC参数
- SendUart(bDump[0]);
- SendUart(bDump[1]);
- SendUart(bDump[2]);
- SendUart(bDump[3]);
- SendUart(bDump[4]);
- SendUart(bDump[5]);
- SendUart(bDump[6]);
- SendUart(ALAHOUR);
- SendUart(ALAMIN);
- SendUart(ALASEC);
- SendUart(ALASSEC);
- }
-
- if (fReset2Isp) //重启请求
- {
- fReset2Isp = 0;
-
- IAP_CONTR = 0x60; //软件触发复位到系统ISP区
- }
- }
- }
-
- void uart_isr() interrupt UART1_VECTOR
- {
- BYTE dat;
-
- if (TI)
- {
- TI = 0;
-
- fUartBusy = 0;
- }
-
- if (RI)
- {
- RI = 0;
-
- dat = SBUF;
- switch (bUartStage++) //解析串口命令
- {
- default:
- case 0:
- L_Check1st:
- if (dat == '@') bUartStage = 1;
- else bUartStage = 0;
- break;
- case 1:
- if (dat == 'F') bUartStage = 2;
- else if (dat == 'R') bUartStage = 7;
- else goto L_Check1st;
- break;
- case 2:
- if (dat != 'E') goto L_Check1st;
- break;
- case 3:
- if (dat != 'T') goto L_Check1st;
- break;
- case 4:
- if (dat != 'C') goto L_Check1st;
- break;
- case 5:
- if (dat != 'H') goto L_Check1st;
- break;
- case 6:
- if (dat != '#') goto L_Check1st;
- bUartStage = 0;
- fFetchRtc = 1; //当前命令序列为获取RTC数据命令:"@FETCH#"
- break;
- case 7:
- if (dat != 'E') goto L_Check1st;
- break;
- case 8:
- if (dat != 'B') goto L_Check1st;
- break;
- case 9:
- case 10:
- if (dat != 'O') goto L_Check1st;
- break;
- case 11:
- if (dat != 'T') goto L_Check1st;
- break;
- case 12:
- if (dat != '#') goto L_Check1st;
- bUartStage = 0;
- fReset2Isp = 1; //当前命令序列为重启命令:"@REBOOT#"
- break;
- }
- }
- }
-
- void rtc_isr() interrupt RTC_VECTOR //RTC中断复位程序
- {
- RTCIF = 0x00; //清RTC中断标志
-
- P20 = !P20; //P2.0口每秒闪烁一次,测试用
- }
-
- void SysInit()
- {
- P_SW2 |= 0x80;
-
- 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;
-
- }
-
- void UartInit() //串口初始化函数
- {
- SCON = 0x50;
- AUXR = 0x40;
- TMOD = 0x00;
- TL1 = BAUD;
- TH1 = BAUD >> 8;
- TR1 = 1;
- ES = 1;
- }
-
- void RTCInit() //RTC初始化函数
- {
- // IRC32KCR = 0x80;
- // while (!(IRC32KCR & 0x01));
- // RTCCFG |= 0x02; //选择内部32K为RTC时钟源
-
- X32KCR = 0xc0;
- while (!(X32KCR & 0x01));
- RTCCFG &= ~0x02; //选择外部部32K为RTC时钟源
-
- if (InitBlock.bValidTag == 0x5a)
- {
- INIYEAR = InitBlock.bIniYear; //如果初始化数据块有效,则使用数据块初始化RTC
- INIMONTH = InitBlock.bIniMonth;
- INIDAY = InitBlock.bIniDay;
- INIHOUR = InitBlock.bIniHour;
- INIMIN = InitBlock.bIniMinute;
- INISEC = InitBlock.bIniSecond;
- INISSEC = InitBlock.bIniSSecond;
- ALAHOUR = InitBlock.bAlaHour;
- ALAMIN = InitBlock.bAlaMinute;
- ALASEC = InitBlock.bAlaSecond;
- ALASSEC = InitBlock.bAlaSSecond;
-
- IapProgram(0x0000, 0x00); //销毁初始化数据块,以免重复初始化
- }
- else
- {
- INIYEAR = 23; //否则初始化RTC为默认值
- INIMONTH = 1;
- INIDAY = 29;
- INIHOUR = 12;
- INIMIN = 0;
- INISEC = 0;
- INISSEC = 0;
- ALAHOUR = 0;
- ALAMIN = 0;
- ALASEC = 0;
- ALASSEC = 0;
- }
- RTCCFG |= 0x01; //写入RTC初始值
- RTCCR = 0x01; //RTC开始运行
- while (RTCCFG & 0x01); //等待RTC初始化完成
- RTCIF = 0x00;
- RTCIEN = 0x08; //使能RTC秒中断
- }
-
- void SendUart(BYTE dat) //串口发送函数
- {
- while (fUartBusy);
- SBUF = dat;
- fUartBusy = 1;
- }
-
- void IapProgram(int addr, char dat) //EEPROM编程函数
- {
- IAP_CONTR = 0x80;
- IAP_TPS = 12;
- IAP_CMD = 2;
- IAP_ADDRL = addr;
- IAP_ADDRH = addr >> 8;
- IAP_DATA = dat;
- IAP_TRIG = 0x5a;
- IAP_TRIG = 0xa5;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
复制代码
ISP下载软件中“用户接口”的设置如下:(注意,首次下载不能使能用户接口) |