视频教学,RTC实时时钟,年/月/日/时/分/秒,1/128秒

https://www.stcaimcu.com/forum.p ... 3184&extra=page%3D1
28.3 范例程序1.3.1 串口打印RTC时钟范例C语言代码
//测试工作频率为22.1184MHz,需要将C语言代码文件与下面的汇编代码文件加载到同一个项目里使用 #include "stc8h.h" #include "intrins.h" #include "stdio.h" #define MAIN_Fosc 22118400L #define Baudrate 115200L #define TM (65536-(MAIN_Fosc/Baudrate+2)/4) //加2操作是为了让Keil编译器 //自动实现四舍五入运算
bit B1S_Flag; void RTC_config(void);
void UartInit(void) { SCON= (SCON & 0x3f) | 0x40; T2L = TM; T2H = TM>>8; AUXR|= 0x15; } void UartPutc(unsigned char dat) { SBUF= dat; while(TI==0); TI= 0; } char putchar(char c) { UartPutc(c); returnc; } void RTC_Isr() interrupt 13 { if(RTCIF& 0x08) //判断是否秒中断 { RTCIF&= ~0x08; //清中断标志 B1S_Flag= 1; } } void main(void) { P_SW2|= 0x80; //使能XFR访问 P0M1= 0; P0M0 = 0; //设置为准双向口 P1M1= 0; P1M0 = 0; //设置为准双向口 P2M1= 0; P2M0 = 0; //设置为准双向口 P3M1= 0; P3M0 = 0; //设置为准双向口 P4M1= 0; P4M0 = 0; //设置为准双向口 P5M1= 0; P5M0 = 0; //设置为准双向口 UartInit(); RTC_config(); EA= 1; printf("RTCTest Programme!\r\n"); //UART发送一个字符串 while(1) { if(B1S_Flag) { B1S_Flag= 0; printf("Year=20%bd ", YEAR); printf("Month=%bd ", MONTH); printf("Day=%bd ", DAY); printf("Hour=%bd ", HOUR); printf("Minute=%bd ", MIN); printf("Second=%bd ", SEC); printf("\r\n"); } } } void RTC_config(void) { // //选择内部低速IRC // IRC32KCR = 0x80; //启动内部低速振荡器 // while (!(IRC32KCR & 0x01)); //等待时钟稳定 // RTCCFG |= 0x02; //选择内部低速IRC作为RTC时钟源 //选择外部32K X32KCR= 0xc0; //启动外部32K晶振 while(!(X32KCR & 0x01)); //等待时钟稳定 RTCCFG&= ~0x02; //选择外部32K作为RTC时钟源 INIYEAR= 21; //Y:2021 INIMONTH= 12; //M:12 INIDAY= 31; //D:31 INIHOUR= 23; //H:23 INIMIN= 59; //M:59 INISEC= 50; //S:50 INISSEC= 0; //S/128:0 RTCCFG|= 0x01; //触发RTC寄存器初始化 RTCIF= 0; //清中断标志 RTCIEN= 0x08; //使能RTC秒中断 RTCCR= 0x01; // RTC使能} }
汇编代码
;将以下代码保存为ASM格式文件,一起加载到项目里,例如:isr.asm CSEG AT 0123H JMP 006BH END
28.3.2 利用ISP软件的用户接口实现不停电下载保持RTC参数
C语言代码
//测试工作频率为11.0592MHz /************* 功能说明 ********************************************************************* 现有单片机系列的RTC模块,在单片机复位后RTC相关的特殊功能寄存器也会复位 本例程主要用于解决ISP下载后用户的RTC参数丢失的问题 解决思路:ISP下载前,先将RTC相关参数通过ISP下载软件的用户接口上传到PC保存,等待ISP下载完成后,下载软件再将保存的相关参数写入到FLASH的指定地址(范例中指定的地址为FE00H)。ISP下载完成后会立即运行用户代码,用户程序在初始化RTC寄存器时,可从FLASH的指定地址中读取之前上传的RTC相关参数对RTC寄存器进行初始化,即可实现不停电下载保持RTC参数的目的。 下载时, 选择时钟 11.0592MHZ ************************************************************************************************/ #include "stc8h.h" #include "intrins.h" #include "stdio.h" #include "stc8h.h" #include "intrins.h" #define FOSC 11059200UL #define BAUD (65536- FOSC/4/115200) typedef bit BOOL; typedef unsigned char BYTE; typedef unsigned int WORD; 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(WORD addr, BYTEdat); 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() interruptUART1_VECTOR { BYTEdat; if(TI) { TI = 0; fUartBusy = 0; } if(RI) { RI = 0; dat = SBUF; switch (bUartStage++) //解析串口命令 { default: case 0: L_Check1st: if (dat == '@') bUartStage = 1; elsebUartStage = 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') gotoL_Check1st; break; case 4: if (dat != 'C') gotoL_Check1st; break; case 5: if (dat != 'H') gotoL_Check1st; break; case 6: if (dat != '#') gotoL_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') gotoL_Check1st; break; case 11: if (dat != 'T') gotoL_Check1st; break; case 12: if (dat != '#') goto L_Check1st; bUartStage = 0; fReset2Isp = 1; //当前命令序列为重启命令:"@REBOOT#" break; } } } void rtc_isr() interruptRTC_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; //选择内部低速IRC为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(WORD addr, BYTEdat) //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_();} } 【新提醒】视频讲解:RTC 实时时钟,年月日时分秒,STC8H数据手册 RTC 内容 - 段码LCD/80mA大电流LED数码管自动刷新显示/RTC实时时钟/触摸按键/低功耗 国芯技术交流网站 - STC全球32位8051爱好者互助交流社区 https://www.stcaimcu.com/forum.p ... &extra=page%3D1
|