单片机交流
直播中

kasdlak

8年用户 1201经验值
擅长:光电显示
私信 关注
[问答]

如何使用51单片机自制电子万年历?

如何使用51单片机自制电子万年历?

回帖(1)

李欣海

2021-11-10 10:46:05
归档51单片机制作电子万年历,以及proteus仿真威廉希尔官方网站 图,本设计涵盖蜂鸣器、uart、timer、矩阵扫描、lcd1602显示、基本万年历(年/月/日/时/分/秒)、闹钟、日程、修改时间和小游戏等各项功能,基本上覆盖使用了51单片机内部所有资源。
仿真结果展示

基本万年历运行结果:





设定闹钟运行结果:





设定日程运行结果:





修改时间运行结果:





小游戏运行结果:





仿真威廉希尔官方网站 图

仿真平台使用proteus7.10。





代码目录结构

|—source # 电子万年历源码
|—|---include.h # 公共定义
|—|---main.c # 主函数
|—|---main.h
|—±–base # 基本万年历
|—|-------clock.c
|—|-------clock.h
|—±–drv # 电子万年历驱动
|—|---±–buzzer # 蜂鸣器
|—|---|-------buzzer.c
|—|---|-------buzzer.h
|—|---±–keyboard # 矩阵键盘
|—|---|-------keyboard.c
|—|---|-------keyboard.h
|—|---±–lcd1602 # lcd1602
|—|---|-------lcd1602.c
|—|---|-------lcd1602.h
|—|---±–timer # 定时器
|—|---|-------timer.c
|—|---|-------timer.h
|—|---|—uart # 串口
|—|-----------uart.c
|—|-----------uart.h
|—|---ext # 电子万年历扩展功能
|-------±–alarm
|-------|-------alarm.c # 闹钟
|-------|-------alarm.h
|-------|-------schedule.c # 日程
|-------|-------schedule.h
|-------±–game # 小游戏
|-------|-------catch_rabbit.c
|-------|-------catch_rabbit.h
|-------|—set # 修改时间
|---------------change_time.c
|---------------change_time.h
51单片机 - 电子万年历(项目 + 仿真)

包含工程和仿真威廉希尔官方网站 ,工程结构清晰。
下载链接://download.csdn.net/download/weixin_44413515/12178845
51单片机 - 电子万年历(全部代码)

所有代码放到了同一文件,有少量增删,功能一致,代码结构不清晰。
下载链接://download.csdn.net/download/weixin_44413515/12178806
51单片机 - 电子万年历(proteus仿真威廉希尔官方网站 )

下载链接://download.csdn.net/download/weixin_44413515/12178811
电子万年历子模块软件介绍

访问链接:



电子万年历功能枚举
罗列万年历各项功能,如:基本万年历(FUN_CLOCK ),闹钟(FUN_ALARM),日程(FUN_SCHEDULE),修改时间(FUN_CHANGE_TIME)和小游戏(FUN_CATCH_RABBIT)。抽象数据类型fun_t。


typedef enum {  // 功能判断
    FUN_CLOCK = 0,
    FUN_ALARM,
    FUN_SCHEDULE,
    FUN_CHANGE_TIME,
    FUN_CATCH_RABBIT,
    FUN_BUTT
} fun_t;


功能切换
功能切换通过按键KEY_FUN完成,检测到KEY_FUN按键按下,切换到下一工作模式。


/*******************************************************************************
* 函 数 名         : response_key
* 函数功能         : 按键响应
* 输    入         : key:按键值
* 输    出         : void
* 说    名         : none
*******************************************************************************/
void response_key(key_t key)  // 按键响应
{
    switch (key) {
        case KEY_0:
        case KEY_1:
        case KEY_2:
        case KEY_3:
        case KEY_4:
        case KEY_5:
        case KEY_6:
        case KEY_7:
        case KEY_8:
        case KEY_9:
        case KEY_ADD:
        case KEY_SUB:
        case KEY_ENTER:
        case KEY_TRANS: break;
        case KEY_FUN: {  // 加1
            fun++;
            fun_change = 1;
            if (fun >= FUN_BUTT) {
                fun = FUN_CLOCK;
            }
            break;
        }
        case KEY_BACK: {
            fun_change = 1;
            fun = FUN_CLOCK;
            break;
        }
        default: break;
    }
}


功能选择
通过当前fun值,抉择出当前选择执行的功能,并进行执行和显示。首次调用某功能都会进行一次初始化,在退出某功能时,可能调用去初始化接口完成退出的清理工作。


/*******************************************************************************
* 函 数 名         : fun_select
* 函数功能         : 功能选择
* 输    入         : fun:功能号
* 输    出         : void
* 说    名         : none
*******************************************************************************/
void fun_select(fun_t fun)  // 功能选择
{
    switch (fun) {
        case FUN_CLOCK: {
            if (fun_change) {
                fun_change = 0;
                timer_set_update_level(1);
                clock_init();
            }
            clock_display_update();
            break;
        }
        case FUN_ALARM: {
            if (fun_change) {
                fun_change = 0;
                alarm_init();
            }
            alarm_response_key(key);
            alarm_display();
            break;
        }
        case FUN_SCHEDULE: {
            if (fun_change) {
                fun_change = 0;
                schedule_init();
            }
            schedule_response_key(key);
            schedule_display();
            break;
        }
        case FUN_CHANGE_TIME: {
            if (fun_change) {
                fun_change = 0;
                change_time_init();
            }
            change_time_response_key(key);
            change_time_display();
            break;
        }
        case FUN_CATCH_RABBIT: {
            if (fun_change) {
                fun_change = 0;
                catch_rabbit_init();
            }
            catch_rabbit_response_key(key);
            break;
        }
        default: break;
    }
}


主函数
负责初始化各个硬件模块,初始化51单片机内部系统,而后循环扫描矩阵键盘并将按键值映射到按键功能,做闹钟、日程提醒的检测,完成功能的切换。


/*
################################################################


                                万年历


################################################################
*/
void main(void)
{
    u8 state = 0;


    buzzer_enable_passive();
    lcd1602_init();
    timer_init();
    uart_init();


    while (1) {
        key = keyboard_map_to_key(keyboard_scan());


        fun_select(fun);


        state = alarm_check(time.hour, time.miunte);
        if (state && (key == KEY_TRANS) && (fun != FUN_ALARM) && (fun != FUN_SCHEDULE)) {
            alarm_close();
        }
        state = schedule_check(time.month, time.day, time.hour, time.miunte);
        if (state && (key == KEY_TRANS) && (fun != FUN_ALARM) && (fun != FUN_SCHEDULE)) {
            schedule_close();
        }


        response_key(key);


#if 0
        uart_send_time();
#endif
    }
}


附录 - 电子万年历(main.h)
#ifndef __MAIN_H__
#define __MAIN_H__


#include "include.h"
#include "keyboard.h"


typedef enum {  // 功能判断
    FUN_CLOCK = 0,
    FUN_ALARM,
    FUN_SCHEDULE,
    FUN_CHANGE_TIME,
    FUN_CATCH_RABBIT,
    FUN_BUTT
} fun_t;


void response_key(key_t key);  // 按键响应
void fun_select(fun_t fun);  // 功能选择


#endif


附录 - 电子万年历(main.c)
/* 晶振fosc = 12MHZ */
#include "main.h"
#include "lcd1602.h"
#include "keyboard.h"
#include "timer.h"
#include "buzzer.h"
#include "uart.h"
#include "clock.h"
#include "alarm.h"
#include "schedule.h"
#include "change_time.h"
#include "catch_rabbit.h"


key_t key = KEY_BUTT;  // 按键值
fun_t fun = FUN_CLOCK;  // 功能判断
u8 fun_change = 1;  // 功能改变,0无效,other有效


/*
################################################################


                                万年历


################################################################
*/
void main(void)
{
    u8 state = 0;


    buzzer_enable_passive();
    lcd1602_init();
    timer_init();
    uart_init();


    while (1) {
        key = keyboard_map_to_key(keyboard_scan());


        fun_select(fun);


        state = alarm_check(time.hour, time.miunte);
        if (state && (key == KEY_TRANS) && (fun != FUN_ALARM) && (fun != FUN_SCHEDULE)) {
            alarm_close();
        }
        state = schedule_check(time.month, time.day, time.hour, time.miunte);
        if (state && (key == KEY_TRANS) && (fun != FUN_ALARM) && (fun != FUN_SCHEDULE)) {
            schedule_close();
        }


        response_key(key);
#if 0
        uart_send_time();
#endif
    }
}


/*******************************************************************************
* 函 数 名         : response_key
* 函数功能         : 按键响应
* 输    入         : key:按键值
* 输    出         : void
* 说    名         : none
*******************************************************************************/
void response_key(key_t key)  // 按键响应
{
    switch (key) {
        case KEY_0:
        case KEY_1:
        case KEY_2:
        case KEY_3:
        case KEY_4:
        case KEY_5:
        case KEY_6:
        case KEY_7:
        case KEY_8:
        case KEY_9:
        case KEY_ADD:
        case KEY_SUB:
        case KEY_ENTER:
        case KEY_TRANS: break;
        case KEY_FUN: {  // 加1
            fun++;
            fun_change = 1;
            if (fun >= FUN_BUTT) {
                fun = FUN_CLOCK;
            }
            break;
        }
        case KEY_BACK: {
            fun_change = 1;
            fun = FUN_CLOCK;
            break;
        }
        default: break;
    }
}


/*******************************************************************************
* 函 数 名         : fun_select
* 函数功能         : 功能选择
* 输    入         : fun:功能号
* 输    出         : void
* 说    名         : none
*******************************************************************************/
void fun_select(fun_t fun)  // 功能选择
{
    switch (fun) {
        case FUN_CLOCK: {
            if (fun_change) {
                fun_change = 0;
                timer_set_update_level(1);
                clock_init();
            }
            clock_display_update();
            break;
        }
        case FUN_ALARM: {
            if (fun_change) {
                fun_change = 0;
                alarm_init();
            }
            alarm_response_key(key);
            alarm_display();
            break;
        }
        case FUN_SCHEDULE: {
            if (fun_change) {
                fun_change = 0;
                schedule_init();
            }
            schedule_response_key(key);
            schedule_display();
            break;
        }
        case FUN_CHANGE_TIME: {
            if (fun_change) {
                fun_change = 0;
                change_time_init();
            }
            change_time_response_key(key);
            change_time_display();
            break;
        }
        case FUN_CATCH_RABBIT: {
            if (fun_change) {
                fun_change = 0;
                catch_rabbit_init();
            }
            catch_rabbit_response_key(key);
            break;
        }
        default: break;
    }
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分