在线时间42 小时
UID3156990
注册时间2017-12-12
NXP金币0
TA的每日心情 | 擦汗 2023-12-19 16:25 |
---|
签到天数: 14 天 [LV.3]偶尔看看II
中级会员
- 积分
- 367
- 最后登录
- 2023-12-19
|
本帖最后由 縋逐ЮDreams 于 2018-12-9 14:11 编辑
已经有一周没用这个板子了,因为上周和这周是在太忙了。今天写了一个RTC时钟程序。本来申请板子的时候就说的是要做一个闹钟,现在离目标也越来越近了,争取早日做完。
废话不多说,直接上代码,代码是在官方的例程上修改的,例程的功能是实现定时唤醒与休眠,我不需要这些功能,所以直接将唤醒功能禁掉了。我只需要用到计数功能和alarm功能,频率是1HZ,一秒钟中断一次。
初始化:
- void RTC_Init(void)
- {
- /* Enable the RTC oscillator, oscillator rate can be determined by
- calling Chip_Clock_GetRTCOscRate() */
- Chip_Clock_EnableRTCOsc();
- /* Initialize RTC driver (enables RTC clocking) */
- Chip_RTC_Init(LPC_RTC);
- /* RTC reset */
- Chip_RTC_Reset(LPC_RTC);
- /* Start RTC at a count of 0 when RTC is disabled. If the RTC is enabled, you
- need to disable it before setting the initial RTC count. */
- Chip_RTC_Disable(LPC_RTC);
- Chip_RTC_SetCount(LPC_RTC, 0);
- /* Set a long alarm time so the interrupt won't trigger */
- Chip_RTC_SetAlarm(LPC_RTC, 1);
-
- /* Enable RTC and high resolution timer - this can be done in a single
- call with Chip_RTC_EnableOptions(LPC_RTC, (RTC_CTRL_RTC1KHZ_EN | RTC_CTRL_RTC_EN)); */
- Chip_RTC_Enable1KHZ(LPC_RTC);
- Chip_RTC_Enable(LPC_RTC);
- /* Clear latched RTC interrupt statuses */
- Chip_RTC_ClearStatus(LPC_RTC, (RTC_CTRL_OFD | RTC_CTRL_ALARM1HZ/* | RTC_CTRL_WAKE1KHZ*/));
- /* Enable RTC as a peripheral wakeup event */
- // Chip_SYSCTL_EnablePeriphWakeup(SYSCTL_WAKEUP_RTCINT);
- /* Don't power down WDT (or BOD) during deep sleep. */
- // Chip_SYSCTL_SetDeepSleepPD(0);
- /* Power everything up except for ADC, USB and temp sensor on wake up from
- deep sleep. */
- // Chip_SYSCTL_SetWakeup(SYSCTL_SLPWAKE_ADC_PD |
- // SYSCTL_SLPWAKE_USBPLL_PD |
- // SYSCTL_SLPWAKE_USBPAD_PD |
- // SYSCTL_SLPWAKE_TS_PD
- // );
- /* Enable RTC interrupt */
- NVIC_EnableIRQ(RTC_IRQn);
-
- /* Enable RTC alarm interrupt */
- Chip_RTC_EnableWakeup(LPC_RTC, (RTC_CTRL_ALARMDPD_EN/* | RTC_CTRL_WAKEDPD_EN*/));
-
- Set_Date(2018,12,9,16,20,50); //设置年月日时分秒
- }
复制代码
因为例程中没有可以直接设置时间的库函数(我没有找到,不知道有没有),所以就自己写了一个。
首先是初始化时间结构体:
- //定义时间结构体,年月日时分秒
- struct Time{
- uint16_t year;
- uint8_t month;
- uint8_t day;
- uint8_t hour;
- uint8_t min;
- uint8_t sec;
- };
复制代码
然后是时间初始化函数,设定一个初始时间,年月日时分秒:
- void Set_Date(uint16_t year, uint8_t mon, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec)
- {
- time.sec = sec;
- time.min = min;
- time.hour = hour;
- time.day = day;
- time.month = mon;
- time.year = year;
- }
复制代码
然后就是时间的累积函数,里面包括的大小月的判断,闰年的判断。如下:
- //时间函数
- void Clock_Run(void)
- {
- time.sec ++;
- if(time.sec >= 60)
- {
- time.sec = 0;
- time.min ++;
- if(time.min >= 60)
- {
- time.min = 0;
- time.hour ++;
- if(time.hour >= 24)
- {
- time.hour = 0;
- time.day ++;
- if(time.day > month_number_judge())
- {
- time.day = 1;
- time.month ++;
- if(time.month > 12)
- {
- time.month = 1;
- time.year++;
- }
- }
- }
- }
- }
- }
- //月份天数判断
- uint8_t month_number_judge(void)
- {
- if(time.month==2)
- {
- if(if_leap_year()==0)
- {
- return 28;
- }else
- {
- return 29;
- }
- }
- else if(time.month==1||time.month==3||time.month==5||time.month==7||time.month==8||time.month==10||time.month==12)
- {
- return 31;
- }else
- {
- return 30;
- }
- }
- //闰年判断
- unsigned char if_leap_year(void)
- {
- if(((time.year%4==0) && (time.year%100)!=0) || (time.year%400==0))
- {
- return 1; //表示闰年
- }else
- {
- return 0; //平年
- }
- }
复制代码
最后是RTC中断函数
我的时间更新是在这里面做的。
重点说一下这句话:Chip_RTC_SetAlarm(LPC_RTC, Chip_RTC_GetCount(LPC_RTC)+1);
这句话是下一次进入中断的时间的话,想要1s进一次中断就要设定下一次的count值,如上面,不加这句话中断时进不了的,我就在这卡了一段时间,查了数据手册才明白时怎么回事。
- //RTC中断函数
- void RTC_IRQHandler(void)
- {
- Board_LED_Toggle(0);
- Clock_Run();
- OLED_Display_Time(); //刷新时间显示
-
- DEBUGOUT("Date:%d-%d-%d %d:%d:%d\r\r\n",
- time.year,time.month,time.day,time.hour,time.min,time.sec); //将时间打印到串口
-
- Chip_RTC_SetAlarm(LPC_RTC, Chip_RTC_GetCount(LPC_RTC)+1);//当前count+1,这个必须加,下一次才能够进入到中断
- /* Clear only latched RTC status */
- Chip_RTC_EnableOptions(LPC_RTC, (RTC_CTRL_ALARM1HZ));
- }
复制代码
最后是显示函数:我的程序使用的OLED显示的,所以有了OLED的处理函数,不知道OLED怎么操作的,可以参考我的上一篇帖子:
https://www.nxpic.org.cn/module/forum/thread-615608-1-1.html
如果你没有OLED的话,可以使用串口试验该程序,已经在代码中处理了,OLED程序如下:
- //OLED时间显示
- void OLED_Display_Time(void)
- {
- //显示年月日
- OLED_ShowNum(24,32,time.year,4,16);
- OLED_ShowChar(24+4*8,32,'-',16,1);
- OLED_ShowNum(24+5*8,32,time.month,2,16);
- OLED_ShowChar(24+7*8,32,'-',16,1);
- OLED_ShowNum(24+8*8,32,time.day,2,16);
-
- //显示时分秒
- OLED_ShowNum(32,48,time.hour,2,16);
- OLED_ShowChar(32+2*8,48,':',16,1);
- OLED_ShowNum(32+3*8,48,time.min,2,16);
- OLED_ShowChar(32+5*8,48,':',16,1);
- OLED_ShowNum(32+6*8,48,time.sec,2,16);
-
- OLED_Refresh_Gram(); //刷新GRAM
- }
复制代码
串口显示,请加这句话,已经在RTC中断中写上了:
- DEBUGOUT("Date:%d-%d-%d %d:%d:%d\r\r\n",
- time.year,time.month,time.day,time.hour,time.min,time.sec); //将时间打印到串口
复制代码
设定初始化时间,已经在RTC初始化的时候写上了,但是这里可以强调一下:
- Set_Date(2018,12,9,16,20,50);
复制代码
最后放上显示效果:
首先是串口:
OLED的显示效果
好了,最后放上代码,可以直接使用该工程进行验证,有问题欢迎指正,谢谢
程序:
RTC_OLED.zip
(4.1 MB, 下载次数: 6)
|
|