蓝桥单片机第九届模拟之电子钟

不积跬步无以至千里,不积小流无以成江海。


题目下载可以到官网<传送门>

代码参考可以上Github<传送门>


题目要求:

  • 初始化
    1)关闭蜂鸣器、继电器等无关外设;
    2)设备初始化时钟为 23 时 59 分 50 秒,闹钟提醒时间 0 时 0 分 0 秒。
  • 时间显示格式(时钟和闹钟)
    这里写图片描述
  • 温度显示格式
    这里写图片描述

  • 时钟设置
    按键 S7 定义为“时钟设置”按键,通过该按键可切换选择待调整的
    时、分、秒,当前选择的显示单元以 1 秒为间隔亮灭,时、分、秒
    的调整需注意数据边界属性。(有一点没提到,就是进入设置时钟设置模式后,数码管时间不再实时刷新,只需要调节的时候刷新!)
    蓝桥单片机第九届模拟之电子钟_第1张图片

  • 闹钟设置
    按键 S6 定义为“闹钟设置”按键,通过该按键可进入闹钟时间设置
    功能,数码管显示当前设定的闹钟时间。
    蓝桥单片机第九届模拟之电子钟_第2张图片
  • 按键 S5 定义为“加”按键,在“时钟设置”或“闹钟设置”状态下,
    每次按下该按键当前选择的单元(时、分或秒)增加 1 个单位。
  • 按键 S4 定义为“减”按键,在“时钟设置”或“闹钟设置”状态下,
    每次按下该按键当前选择的单元(时、分或秒)减少 1 个单位。
  • 按键 S4、S5 的“加”、“减”功能只在“时钟设置”或“闹钟设置”
    状态下有效;
  • 在 “时钟显示”状态下,按下 S4 按键,显示温度数据,松开按键,
    返回“时钟显示”界面。
  • 闹钟提示功能
    • 指示灯 L1 以 0.2 秒为间隔闪烁,持续 5 秒钟;
    • 闹钟提示状态下,按下任意按键,关闭闪烁提示功能。

思路提炼

  • 模块划分
    • 数码管、按键、DS18B20、DS1302、一个LED
  • 模式划分
    • 时钟显示
    • 时钟设置
    • 闹钟设置
  • 界面划分
    • 时钟显示界面
    • 时钟/闹钟设置界面
    • 温度显示界面
  • 细节实现注意
    • S5/S4的作用只在时钟设置或者闹钟设置的界面有效
    • 在时钟显示界面按下S4进入温度显示界面,松开S4恢复时钟显示界面
    • 时钟设置或者闹钟设置界面的光标1s为间隔闪烁
    • 闹钟定时到,L1以0.2s为间隔闪烁,闪烁5s停止
    • 闹钟定时到,按下任意键可以终止LED闪烁,即关闭闹钟提示
    • S4,S5, 切换 时 -> 分 -> 秒 -> 时钟显示

程序过程重现

上面已经分析了题目的具体要求,以及实现思路和细节注意。下面就让我们再来具体重现这个过程!!!

毫无疑问,顶层代码的正确使用前提是底层得确保无误!比赛的前2个半小时左右都是在实现底层的细节,顶层的验证也不能全部写完再进行,而是边写边验证。就上面的五个模块中(其实最后一个“LED”单独归为一个模块有点夸张了,但是鄙以为却真真切切的体现模块化编程的思想)数码管和按键的底层不涉及时序,较简单可以先行书写!

1、数码管和按键

蓝桥单片机第九届模拟之电子钟_第3张图片

这两底层代码可在KeyAction(u8 keycode)+ShowNumber(u32 dat)两个合起来同时验证一下底层的正确性!必须确保无误!

2、DS1302及time相关

接下来就是DS1302的底层.c .h的编写了,别忘了config中定义相关的IO口,完了之后也同样需要校验是否正确!

在主函数中验证,
蓝桥单片机第九届模拟之电子钟_第4张图片

注意结构体的访问方法,这里只能用点运算符

RefreshTime是在time.c中封装的函数,同时也封装了一个ShowLedNumber的函数,用来刷新显示时间到数码管!(注意,这里按照比赛常用的时间格式要求书写!)

蓝桥单片机第九届模拟之电子钟_第5张图片

确保无误后,再进行下一步!

3、毫无疑问下一步就改来到了最后一个底层DS18B20

编写完成底层后然后就行验证了,

蓝桥单片机第九届模拟之电子钟_第6张图片

Refresh18B20同样定义到了time.c

蓝桥单片机第九届模拟之电子钟_第7张图片

刷新温度到数码管!!

3、上层逻辑

所有的底层工作完毕后,就是上层的“组装”了。当然不会是简单的拼接,还需要深入的逻辑!

模式划分,三种:时钟显示,时钟设置,闹钟设置
这里就可以作为系统的三种状态,同时这三种状态,在某一个时刻肯定只有一个成立,所以设置一个枚举变量会是个不错的选择!

enum eSystemSta{//分别对应 时钟显示模式,时钟该设置模式,闹钟设置模式
    E_NORMAL, E_SET_TIME, E_STE_ALARM
};

这个模式的工作做好之后,下面就是具体的细节实现了!
看一下轮廓。
蓝桥单片机第九届模拟之电子钟_第8张图片

蓝桥单片机第九届模拟之电子钟_第9张图片

几个实现的细节地方:

1、闹钟定时并可以任意键取消。

void AlarmMonitor()
{
    static u8 AlarmCnt=0;
    static bit staLED=0;

    if((AlarmHour==buffTime.hour) && (AlarmMin==buffTime.min) && (AlarmSec==buffTime.sec))//定时监控
    {   
        flagAlarm = 1;  
    }
    if(flagAlarm)       
    {
        AlarmCnt++;
        if(!staMute)
        {
            if(staLED==0)
            {
                staLED = 1;
                P2 = (P2&0x1F)|0x80;
                P0 = 0xFE;
                P2 = P2&0x1F;   
            }           
            else
            {
                staLED = 0;
                P2 = (P2&0x1F)|0x80;
                P0 = 0xFF;
                P2 = P2&0x1F;   
            }
        }
        if(AlarmCnt >= 25)
        {
            AlarmCnt = 0;
            flagAlarm = 0;
            P2 = (P2&0x1F)|0x80;
            P0 = 0xFF;
            P2 = P2&0x1F;   
        }

    }
}

以及KeyAction()里面的

    if((flagAlarm==1) && (SystemSta==E_NORMAL))//时钟显示模式下,任意按键按下,都可以停止闹钟
    {
        staMute = 1;
        P2 = (P2&0x1F)|0x80;//确保停止响铃的时候灯是灭的!
        P0 = 0xFF;
        P2 = P2&0x1F;   
    }

注意这里是设置了两重保障,flagAlarm以及staMute..在KeyAction()里面操作的只是staMute,只是不再闪灯了而已。如果一重保障,无法做到按下按键立即停止闹铃,不知道为什么。。。

2、BCD码的加减

蓝桥单片机第九届模拟之电子钟_第10张图片

蓝桥单片机第九届模拟之电子钟_第11张图片

你可能感兴趣的:(蓝桥杯之单片机,蓝桥之单片机设计)