在网上淘了一个PIC18F85K90自带RTCC功能的单片机,写了一段测试一下RTCC的精度,运作了5天,还好_精度达到了误差毫秒级.
随手加了一个AHT15温湿度
注:32.768(5ppm)晶振需要加两个30pF电容稳定震荡频率, 每30分钟与60分钟进位时秒显示。
制作出来的实物图如下:
单片机源程序如下:
#include "Delay.h"#include "RTCC.H" #include "Selection.h" RTC _RTCVALH; //定义_共同体变量1 RTC _RTCVALL; //定义_共同体变量2 void check_Data() //校准_【每秒钟调整一次将其加到 RTCC 定时器中】 { //如2小时快1秒的话则为 1/(2小时*3600秒)= 1s / 7200 = 0.1389ms //也就是说明每秒快了0.139MS,由此可推算出真正的【XI】晶振频率为:1.3472=XI/32768 //XI=1.0001389*32768 = 32772.55HZ 32772.55-32768 = 4.55即晶振频率为每秒钟多了约5个脉冲 //4.55*60= 每秒分钟多了 273个脉冲 273 / 4 = 68.25 取 69 【可以认为每秒分钟减去69个脉冲】即69*4 = 276 //- 69 = 0XBB; if (_RTCVALL.SECOND == 0 )//每秒钟调整一次 !HALFSEC RTCCAL = RTCCAL_Temp ; //时钟校准寄存器; //RTCC 校准寄存器 0x88【-120】; -120X4=-480 即在 RTCCAL“每分钟减少480”个时钟脉冲 } void RTCC_WD_Init() //*** RTCC预设初值* ****/ RTCC数据允许写入 { uchar temp ; /*********启动数据初始化**************/ _RTCVALH.YEAR = 0x21; //11 年 YEAR 【自动返回RTCC 值寄存器_初始地址】 _RTCVALH.MONTH = 0x05; //10 月 MONTH _RTCVALH.DAY = 0x07; //10 日 DAY _RTCVALH.WEEKDAY = 0x05; //01 星期 WEEKDAY _RTCVALH.HOUR = 0x12; //01 小时数 HOUR _RTCVALH.MINUTE = 0x01; //00 分钟数 MINUTE _RTCVALH.SECOND = 0x58; //00 秒数 SECOND EECON2 = 0X55; EECON2 = 0XAA; nop(); //在 55h/AA 解码序列和 RTCWREN置 1 之间只允许一个指令周期的时间窗口 RTCCFGbits.RTCWREN = 1; // 允许RTCCFG寄存器进行写操作 RTCCFG |= 0x03; // RTCC 值寄存器窗口指针位_指向地址【1 1】 GIE = 0; //关闭全局中断 /***********************RTCVALL ****************************/ /*通过读 / 写 RTCVALH 寄存器, RTCC 指针值(RTCPTR<1:0>)*/ /*递减 1,直到其达到 00。一旦达到00; MINUTES 和 SECONDS 值就可 */ /*通过 RTCVALH 和 RTCVALL 进行访问,直到手动更改指针值为止。 RTCVALH: 00 = 分钟数 01 = 星期 10 = 月 11 = 保留 RTCVALL: 00 = 秒数 01 = 小时数 10 = 日 11 = 年 **************************************************************/ RTCCFGbits. RTCPTR = 3; RTCVALL = _RTCVALH.YEAR ; temp = RTCVALH; //11 保留 RTCVALL = _RTCVALH.DAY; RTCVALH = _RTCVALH.MONTH ; RTCVALL = _RTCVALH.HOUR; RTCVALH = _RTCVALH.WEEKDAY ; RTCVALL = _RTCVALH.SECOND ; RTCVALH = _RTCVALH.MINUTE; RTCEN = 1; // RTCC使能 RTCCFGbits. RTCWREN = 0; //关闭RTCCFG寄存器写操作 /*******************************************************/ GIE = 1;// 恢复全局中断 } void READ_RTCC() //读时间寄存器操作 { uchar temp ; RTCCFGbits. RTCPTR = 3; temp = RTCVALH; //11 保留 Delay_uS(1); //延时10指令周期, 等待RTCC 值寄存器指针跳到【0 0】 /* 指针一旦达到【0 0】 【MINUTES 和 SECONDS 值就可通过 RTCVALH 和 RTCVALL 进行访问】*/ while(RTCPTR1 && RTCPTR0); RTCCFGbits. RTCPTR = 3; temp = RTCVALH; //11 保留-->【开始调用指针 】 RTCCFGbits. RTCPTR = 2; _RTCVALH.MONTH = RTCVALH; //10 月 RTCCFGbits. RTCPTR = 1; _RTCVALH.WEEKDAY = RTCVALH; //01 星期 RTCCFGbits. RTCPTR = 0; _RTCVALH.MINUTE = RTCVALH; //00 分钟数 RTCCFGbits. RTCPTR = 3; _RTCVALL.YEAR = RTCVALL; //11 年 RTCCFGbits. RTCPTR = 2; _RTCVALL.DAY = RTCVALL; //10 日 RTCCFGbits. RTCPTR = 1; _RTCVALL.HOUR = RTCVALL; //01 小时数 RTCCFGbits. RTCPTR = 0; _RTCVALL.SECOND = RTCVALL; //00 秒数 _RTCVALL.YEAR = Read_RTCC_Bin( _RTCVALL.YEAR); // 年 _RTCVALH.MONTH = Read_RTCC_Bin( _RTCVALH.MONTH); // 月 _RTCVALL.DAY = Read_RTCC_Bin( _RTCVALL.DAY); // 日 _RTCVALH.WEEKDAY = _RTCVALH.WEEKDAY & 0x07; // 星期 _RTCVALL.HOUR = Read_RTCC_Bin( _RTCVALL.HOUR); // 小时 _RTCVALH.MINUTE = Read_RTCC_Bin( _RTCVALH.MINUTE ); //分钟数 _RTCVALL.SECOND = Read_RTCC_Bin( _RTCVALL.SECOND); // 秒 }
复制代码