请选择 进入手机版 | 继续访问电脑版
查看: 3315|回复: 2

[原创] 【LPC11U68】5、RTC时钟的使用

[复制链接]
  • TA的每日心情
    擦汗
    2023-12-19 16:25
  • 签到天数: 14 天

    [LV.3]偶尔看看II

    10

    主题

    63

    帖子

    25

    中级会员

    Rank: 3Rank: 3

    积分
    367
    最后登录
    2023-12-19
    发表于 2018-12-9 14:09:05 | 显示全部楼层 |阅读模式
    本帖最后由 縋逐ЮDreams 于 2018-12-9 14:11 编辑

    已经有一周没用这个板子了,因为上周和这周是在太忙了。今天写了一个RTC时钟程序。本来申请板子的时候就说的是要做一个闹钟,现在离目标也越来越近了,争取早日做完。

    废话不多说,直接上代码,代码是在官方的例程上修改的,例程的功能是实现定时唤醒与休眠,我不需要这些功能,所以直接将唤醒功能禁掉了。我只需要用到计数功能和alarm功能,频率是1HZ,一秒钟中断一次。

    初始化:
    1. void RTC_Init(void)
    2. {
    3.         /* Enable the RTC oscillator, oscillator rate can be determined by
    4.            calling Chip_Clock_GetRTCOscRate()        */
    5.         Chip_Clock_EnableRTCOsc();

    6.         /* Initialize RTC driver (enables RTC clocking) */
    7.         Chip_RTC_Init(LPC_RTC);

    8.         /* RTC reset */
    9.         Chip_RTC_Reset(LPC_RTC);

    10.         /* Start RTC at a count of 0 when RTC is disabled. If the RTC is enabled, you
    11.            need to disable it before setting the initial RTC count. */
    12.         Chip_RTC_Disable(LPC_RTC);
    13.         Chip_RTC_SetCount(LPC_RTC, 0);

    14.         /* Set a long alarm time so the interrupt won't trigger */
    15.         Chip_RTC_SetAlarm(LPC_RTC, 1);
    16.         
    17.         /* Enable RTC and high resolution timer - this can be done in a single
    18.            call with Chip_RTC_EnableOptions(LPC_RTC, (RTC_CTRL_RTC1KHZ_EN | RTC_CTRL_RTC_EN)); */
    19.         Chip_RTC_Enable1KHZ(LPC_RTC);
    20.         Chip_RTC_Enable(LPC_RTC);

    21.         /* Clear latched RTC interrupt statuses */
    22.         Chip_RTC_ClearStatus(LPC_RTC, (RTC_CTRL_OFD | RTC_CTRL_ALARM1HZ/* | RTC_CTRL_WAKE1KHZ*/));

    23.         /* Enable RTC as a peripheral wakeup event */
    24. //        Chip_SYSCTL_EnablePeriphWakeup(SYSCTL_WAKEUP_RTCINT);

    25.         /* Don't power down WDT (or BOD) during deep sleep. */
    26. //        Chip_SYSCTL_SetDeepSleepPD(0);

    27.         /* Power everything up except for ADC, USB and temp sensor on wake up from
    28.            deep sleep. */
    29. //        Chip_SYSCTL_SetWakeup(SYSCTL_SLPWAKE_ADC_PD    |
    30. //                                                  SYSCTL_SLPWAKE_USBPLL_PD |
    31. //                                                  SYSCTL_SLPWAKE_USBPAD_PD |
    32. //                                                  SYSCTL_SLPWAKE_TS_PD
    33. //                                                  );

    34.         /* Enable RTC interrupt */
    35.         NVIC_EnableIRQ(RTC_IRQn);
    36.         
    37.         /* Enable RTC alarm interrupt */
    38.         Chip_RTC_EnableWakeup(LPC_RTC, (RTC_CTRL_ALARMDPD_EN/* | RTC_CTRL_WAKEDPD_EN*/));
    39.         
    40.         Set_Date(2018,12,9,16,20,50);    //设置年月日时分秒
    41. }
    复制代码


    因为例程中没有可以直接设置时间的库函数(我没有找到,不知道有没有),所以就自己写了一个。
    首先是初始化时间结构体:
    1. //定义时间结构体,年月日时分秒
    2. struct Time{
    3.         uint16_t year;               
    4.         uint8_t month;
    5.         uint8_t        day;
    6.         uint8_t hour;
    7.         uint8_t min;
    8.         uint8_t sec;
    9. };
    复制代码


    然后是时间初始化函数,设定一个初始时间,年月日时分秒:
    1. void Set_Date(uint16_t year, uint8_t mon, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec)
    2. {
    3.         time.sec = sec;
    4.         time.min = min;
    5.         time.hour = hour;
    6.         time.day = day;
    7.         time.month = mon;
    8.         time.year = year;
    9. }
    复制代码


    然后就是时间的累积函数,里面包括的大小月的判断,闰年的判断。如下:

    1. //时间函数
    2. void Clock_Run(void)
    3. {
    4.         time.sec ++;
    5.         if(time.sec >= 60)
    6.         {
    7.                 time.sec = 0;
    8.                 time.min ++;
    9.                 if(time.min >= 60)
    10.                 {
    11.                         time.min = 0;
    12.                         time.hour ++;
    13.                         if(time.hour >= 24)
    14.                         {
    15.                                 time.hour = 0;
    16.                                 time.day ++;
    17.                                 if(time.day > month_number_judge())
    18.                                 {
    19.                                         time.day = 1;
    20.                                         time.month ++;
    21.                                         if(time.month > 12)
    22.                                         {
    23.                                                 time.month = 1;
    24.                                                 time.year++;
    25.                                         }
    26.                                 }
    27.                         }
    28.                 }
    29.         }
    30. }

    31. //月份天数判断
    32. uint8_t month_number_judge(void)
    33. {
    34.         if(time.month==2)
    35.         {
    36.                 if(if_leap_year()==0)
    37.                 {
    38.                         return 28;
    39.                 }else
    40.                 {
    41.                         return 29;
    42.                 }
    43.         }
    44.         else if(time.month==1||time.month==3||time.month==5||time.month==7||time.month==8||time.month==10||time.month==12)
    45.         {
    46.                 return 31;
    47.         }else
    48.         {
    49.                 return 30;
    50.         }
    51. }
    52. //闰年判断
    53. unsigned char if_leap_year(void)
    54. {
    55.         if(((time.year%4==0) && (time.year%100)!=0) || (time.year%400==0))
    56.         {
    57.                 return 1; //表示闰年
    58.         }else
    59.         {
    60.                 return 0; //平年
    61.         }
    62. }
    复制代码


    最后是RTC中断函数
    我的时间更新是在这里面做的。
    重点说一下这句话:Chip_RTC_SetAlarm(LPC_RTC, Chip_RTC_GetCount(LPC_RTC)+1);
    这句话是下一次进入中断的时间的话,想要1s进一次中断就要设定下一次的count值,如上面,不加这句话中断时进不了的,我就在这卡了一段时间,查了数据手册才明白时怎么回事。
    1. //RTC中断函数
    2. void RTC_IRQHandler(void)
    3. {
    4.         Board_LED_Toggle(0);
    5.         Clock_Run();
    6.         OLED_Display_Time();   //刷新时间显示
    7.         
    8.         DEBUGOUT("Date:%d-%d-%d  %d:%d:%d\r\r\n",
    9.                  time.year,time.month,time.day,time.hour,time.min,time.sec);        //将时间打印到串口
    10.         
    11.         Chip_RTC_SetAlarm(LPC_RTC, Chip_RTC_GetCount(LPC_RTC)+1);//当前count+1,这个必须加,下一次才能够进入到中断
    12.         /* Clear only latched RTC status */
    13.         Chip_RTC_EnableOptions(LPC_RTC, (RTC_CTRL_ALARM1HZ));
    14. }
    复制代码


    最后是显示函数:我的程序使用的OLED显示的,所以有了OLED的处理函数,不知道OLED怎么操作的,可以参考我的上一篇帖子:
    https://www.nxpic.org.cn/module/forum/thread-615608-1-1.html

    如果你没有OLED的话,可以使用串口试验该程序,已经在代码中处理了,OLED程序如下:
    1. //OLED时间显示
    2. void OLED_Display_Time(void)
    3. {
    4.         //显示年月日
    5.         OLED_ShowNum(24,32,time.year,4,16);
    6.         OLED_ShowChar(24+4*8,32,'-',16,1);
    7.         OLED_ShowNum(24+5*8,32,time.month,2,16);
    8.         OLED_ShowChar(24+7*8,32,'-',16,1);
    9.         OLED_ShowNum(24+8*8,32,time.day,2,16);
    10.         
    11.         //显示时分秒
    12.         OLED_ShowNum(32,48,time.hour,2,16);
    13.         OLED_ShowChar(32+2*8,48,':',16,1);
    14.         OLED_ShowNum(32+3*8,48,time.min,2,16);
    15.         OLED_ShowChar(32+5*8,48,':',16,1);
    16.         OLED_ShowNum(32+6*8,48,time.sec,2,16);
    17.         
    18.         OLED_Refresh_Gram();  //刷新GRAM
    19. }
    复制代码


    串口显示,请加这句话,已经在RTC中断中写上了:
    1. DEBUGOUT("Date:%d-%d-%d  %d:%d:%d\r\r\n",
    2.                  time.year,time.month,time.day,time.hour,time.min,time.sec);        //将时间打印到串口
    复制代码


    设定初始化时间,已经在RTC初始化的时候写上了,但是这里可以强调一下
    1. Set_Date(2018,12,9,16,20,50);
    复制代码


    最后放上显示效果:
    首先是串口:
    1.png

    OLED的显示效果
    2.png 3.png



    好了,最后放上代码,可以直接使用该工程进行验证,有问题欢迎指正,谢谢

    程序: RTC_OLED.zip (4.1 MB, 下载次数: 6)
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    5

    帖子

    0

    新手上路

    Rank: 1

    积分
    10
    最后登录
    2018-12-21
    发表于 2018-12-21 09:12:55 | 显示全部楼层
    写的好详细啊
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    7 天前
  • 签到天数: 1478 天

    [LV.10]以坛为家III

    203

    主题

    2万

    帖子

    64

    超级版主

    Rank: 8Rank: 8

    积分
    92608
    最后登录
    2024-4-9
    发表于 2018-12-22 11:15:05 | 显示全部楼层
    不错,支持一下
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-16 13:30 , Processed in 0.138046 second(s), 23 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表