Funpack5-4 基于 FRDM-MCXN236实现电子时钟
该项目使用了FRDM-MCXN236,实现了电子时钟的设计,它的主要功能为:使用 RTC 获取系统时间,串口显示当前时、分、秒信息,使用按键实现时间调整,并且掉电后时间能够保持。
标签
嵌入式系统
Funpack活动
数字逻辑
开发板
cc1989summer
更新2026-10-16
10

项目介绍

 

本项目基于任务1:电子时钟设计

基于 FRDM-MCXN236 开发板,实现一个电子时钟系统,能够显示当前时间并支持时间设置功能。

功能要求:

使用 RTC 获取系统时间   完成

显示当前时、分、秒信息  完成

使用按键实现时间调整    完成

通过串口输出当前时间    完成

掉电后时间能够保持      完成,由于FRDM-MCXN236没有引出VDD_VBAT(RTC供电),而是通过R76电阻接在VDD上,不太方便焊接并引出VDD_VBAT引脚接电池,实现掉电后时间保持。因此本项目通过按下RESET键复位MCU一段时间,让MCU停止工作,而RTC由于接在VDD,没有断电继续计时运行,当松开RESET时,MCU开始工作,获取RTC的最近计时并显示,从而实现模拟掉电(MCU停止工作RTC继续工作)时间能够保持。

 

手册介绍:

image.png

 

电路图:

image.png

 

简短的所有使用到的硬件介绍

 

本项目使用的硬件就只有FRDM-MCXN236,通过数据线连接至电脑,实现串口通信(显示时间),串口使用的是开发板默认调试口DEBUG_UART

 

image.png

 

 

 

方案框图和项目设计思路介绍

 

项目框图如下:

主要功能是

1. 主循环每秒读取并串口打印 RTC 时间,同时查询按键按下标志,如果按下,则执行对应操作,如果SW3按下:切换要修改的时间项(年 / 月 / 日 / 时 / 分 / 秒),如果SW2按下:当前选中项数值 + 1,自动做月份、日期、闰年边界判断,写入 RTC。不直接在中断里修改时间(中断只置按键按下标志)

2. 外部中断INT_0_IRQHANDLER判断按键是否按下,如果有按键按下,对应的按键置按下标志,然后立即清除中断位。


image.png


设计思路:按任务1:电子时钟设计,主要涉及RTC时钟,串口,按键。

RTC时钟和串口直接参考官方例程frdmmcxn236_irtc,都已经配置好基本外设,然后在此基础上加上按键中断,并完善程序功能即可。

需要注意一点,官方例程是在代码里给时钟赋值一个初始值,而我们要实现掉电时间保持,就不能一运行就给RTC赋值,不然掉电/复位后,程序一运行就恢复到初始时间,而应该是上电运行后,获取RTC当前时间,第一次烧录时间是出厂默认时间:2112/1/1 0:0:0,我们通过按键设置好时间后,后面只要不断开发板电源,随便怎么复位,RTC都在实时运行走时,MCU只要一运行,就可以获取RTC最新时间,从而完美实现掉电时间保持。

 

 

调试软件介绍、软件流程图及关键代码介绍

 

本项目使用MCUXpresso IDE v25.6.136,在IDE内下载FRDM-MCXN236开发板的SDK,包含了各类例程,我们可以在官方例程基础上修改,从而实现所需功能。

image.png

 

 

软件流程如下:

image.png


关键代码介绍

1.       由于没有屏幕,在设置时间时,是按时间位切换,但需要显示当前调整的是哪个时间位(年、月、日、时、分、秒),才能方便的条件。

于是设计了一个数组

unsigned char set_time[7][12]={"","Set Year","Set Month","Set Day","Set Hour","Set Minute","Set Second"};

 

每按下一次SW3,set_time[set_time_flag][12]中的set_time_flag就加1,这样我们就可以指示调整时间位,

 

if(flag_switch == 1)   //SW3按下,设置时间位

        {

            flag_switch = 0;  //清标志

            set_time_flag ++;

            if(set_time_flag>6)

            {

                // 退出设置模式,写入RTC

                set_time_flag = 0;

 

            }

        }

 

 

并通过spintf功能,把调整时间位加在时间字符串后面,实现只是功能。

sprintf(time, "%d/%d/%d %d:%d:%2d %s\r\n",

                datetimeGet.year, datetimeGet.month, datetimeGet.day,

                datetimeGet.hour, datetimeGet.minute, datetimeGet.second,set_time[set_time_flag]);

        // 串口格式化输出年月日时分秒

PRINTF(time);

 

 

2.       SW2的功能是,在设置好调整时间位后,每按下一次SW2,对应时间位(根据set_time_flag的值判读)就加1,但加到最大后要归位,比如年加到2099以上就归位到2000,月加到12以上就归1,但每月天数有4种情况,1/3/5/7/8/12月31天,4/6/9/11月30天,闰年2月29天,平年2月28天,这些要通过各自条件判断去实现,否则如果只设置大于31天置0,那4/6/9/11月永远加不到31(RTC内部会根据月份限制),那就永远无法置0。

                            if(flag_add ==1)     //SW2按下,时间位+1

                   {

                            flag_add =0;

 

                            datetime = datetimeGet;

                                     switch(set_time_flag)

                            {

                                     case 1: datetime.year++;if(datetime.year>2099) datetime.year=2000; break;

                                     case 2: datetime.month++; if(datetime.month>12) datetime.month=1; break;

                                     case 3:

                                               datetime.day++;

                                     {

                                         uint8_t maxday = 31;

                                         if(datetime.month == 4 || datetime.month ==6 || datetime.month ==9 || datetime.month ==11)

                                             maxday =30;

                                         else if(datetime.month ==2)

                                         {

                                             if( ((datetime.year%4==0)&&(datetime.year%100!=0)) || (datetime.year%400==0) )

                                                 maxday=29;

                                             else

                                                 maxday=28;

                                         }

                                         if(datetime.day > maxday) datetime.day=1;

                                     }

                                     break;

                                     case 4: datetime.hour++; if(datetime.hour>23) datetime.hour=0; break;

                                     case 5: datetime.minute++; if(datetime.minute>59) datetime.minute=0; break;

                                     case 6: datetime.second++; if(datetime.second>59) datetime.second=0; break;

                                     default: break;

                            }
}

 

 

3.       修改时间需要先关闭RTC写保护,允许修改RTC时间,写入时间后再打开写保护,否则在设置时间时MCU会运行报错。


                                // =========关闭IRTC写保护,允许修改RTC时间=========

                                     IRTC_SetWriteProtection(RTC, false);

                                     // 写入时间

                                     IRTC_SetDatetime(RTC, &datetime);

                                     // 写入完成,重新上锁(可选,推荐)

                                     IRTC_SetWriteProtection(RTC, true);

            

 

功能展示图及说明

 

image.png

 

 

项目中遇到的难题及解决方法

遇到的最大难题是:一开始没进行RTC写保护这块的设置,导致设置时间时,在Debug状态下,经常收到CPU Fault的报错信息,后面查阅了一些资料才知道NXP的MCU有这项设置,放置异常修改时间,加上解除写保护,设置好时间再写保护就正常了。

 

 

心得体会

通过本项目,我完整的实现了实时时钟的完整功能,特别是在没有外接显示屏,仅依靠串口显示的方式,就实现了人机交互,通过一个二维数组set_time[7][12],实现2重功能,

功能1:根据对应的调整时间位set_time_flag ,将set_time[set_time_flag][12]字符串显示在时间后面,指示当前调整的是哪个时间位(年、月、日、时、分、秒);

功能2:根据对应的调整时间位set_time_flag ,将RTC对应时间位+1。

非常感谢硬禾举办这样的活动,即增长了知识,也收获了项目经验。

 

附件下载
rtc.zip
团队介绍
本人是一名业余的嵌入式电子开发爱好者,喜欢捣鼓一些小玩意。
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号