如何在51单片机实现电子万年历

news/2025/3/20 21:59:55/

如何在51单片机实现电子万年历

51单片机制作万年历的基本功能部分,软件特性可以在proteus上仿真,使用51单片机定时器T0做万年历计时信号源,电子万年历计时系统在timer模块,本模块主要是将年/月/日/星期/时/分/秒等信息输出到lcd1602上显示,以及将年月日换算为星期信息。单片机采用12MHz晶振,中断1ms计时方式,误差低。下面直接上代码:

引用timer系统变量

extern time_t time;        // 电子万年历变量
extern u8 time_update;  // 更新显示等级,值越小等级越高,1为最高等级,0为最低

对外接口

用于初始化/去初始化电子万年历系统,计算星期信息,以及在lcd1602上显示更新等。

void clock_init(void);    // 万年历初始化
void clock_deinit(void);    // 万年历去初始化
u8 clock_week_calc(u16 y, u8 m, u8 d);    // 星期计算
void clock_display_update(void);    // 显示更新

初始化模块

主要是预置年/月/日/星期/时/分/秒/毫秒信息显示格式和初始值。

/*******************************************************************************
* 函 数 名         : clock_init
* 函数功能         : 万年历初始化
* 输    入         : void
* 输    出         : void
* 说    名         : none
*******************************************************************************/
void clock_init(void)    // 万年历初始化
{lcd1602_write_cmd(LCD1602_DISPLAY_CONTROL);  // 关闭光标和闪烁lcd1602_clean();lcd1602_set_pos(0, 1);lcd1602_write_num(4, time.year);lcd1602_write_data('-');lcd1602_write_num(2, time.month);lcd1602_write_data('-');lcd1602_write_num(2, time.day);lcd1602_set_pos(0, 0);lcd1602_write_num(2, time.hour);lcd1602_write_data(':');lcd1602_write_num(2, time.miunte);lcd1602_write_data(':');lcd1602_write_num(2, time.second);lcd1602_set_pos(11, 0);lcd1602_write_num(3, time.ms);lcd1602_write_str("ms");
}

lcd1602显示实例:
在这里插入图片描述

去初始化

清理显示屏。

/*******************************************************************************
* 函 数 名         : clock_deinit
* 函数功能         : 万年历去初始化
* 输    入         : void
* 输    出         : void
* 说    名         : none
*******************************************************************************/
void clock_deinit(void)    // 万年历去初始化
{lcd1602_write_cmd(LCD1602_DISPLAY_CONTROL);  // 关闭光标和闪烁lcd1602_clean();
}

星期计算

通过给定年/月/日,通过星期计算公式,完成年月日到星期的换算,计算公式可通过星期的产生和定义得出。返回0表示周天,返回1到6表示周一到周六。

code s8 week[7][4]={{"Sun"}, {"Mon"}, {"Tue"}, {"Wed"}, {"Thu"}, {"Fri"}, {"Sat"}};
/*******************************************************************************
* 函 数 名         : clock_week_calc
* 函数功能         : 星期计算
* 输    入         : y/m/d:年/月/日
* 输    出         : u8:星期数
* 说    名         : none
*******************************************************************************/
u8 clock_week_calc(u16 y, u8 m, u8 d)    // 星期计算
{u16 week_cnt = 0;u8 week_num;switch (m) {     // 从这一年的元旦算到该天为止( 含该天) 的天数case 12: week_cnt += 30;case 11: week_cnt += 31;case 10: week_cnt += 30;case  9: week_cnt += 31;case  8: week_cnt += 31;case  7: week_cnt += 30;case  6: week_cnt += 31;case  5: week_cnt += 30;case  4: week_cnt += 31;case  3: week_cnt += 28;case  2: week_cnt += 31;case  1: week_cnt += d; break;default: break;}if ((!(y % 4) && ((y % 100) || !(y % 400))) && (m > 2)) {    // 闰年补一天week_cnt++;}week_num = (y - 1 + (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400 + week_cnt) % 7;return week_num;
}

显示更新

由于lcd1602写入信息耗时较高,另一方面也并不是时时刻刻年/月/日/星期/时/分/秒/毫秒等信息都在更新或者说有变化,因此利用time_update记录当前需要更新的时间信息有哪些,可以有效提高cpu利用率和性能,在51单片机场景优势非常明显。注:年/月/日/星期/时/分/秒/毫秒更新方向是线性向下的,即:更新年份,必定也需要更新月/日/星期/时/分/秒/毫秒等其他信息。

/*******************************************************************************
* 函 数 名         : clock_display_update
* 函数功能         : 显示更新
* 输    入         : void
* 输    出         : void
* 说    名         : time_update需要及时清除
*******************************************************************************/
void clock_display_update(void)   // 显示更新
{switch (time_update) {        // 判断更新case 1: time_update = 0;  // 年更新lcd1602_set_pos(0, 1);lcd1602_write_num(4, time.year);case 2: time_update = 0;  // 月更新lcd1602_set_pos(5, 1);lcd1602_write_num(2, time.month);case 3: time_update = 0;  // 日更新lcd1602_set_pos(8, 1);lcd1602_write_num(2, time.day);lcd1602_set_pos(11, 1);  // 星期更新lcd1602_write_str(week[clock_week_calc(time.year, time.month, time.day)]);case 4: time_update = 0;  // 时更新lcd1602_set_pos(0, 0);lcd1602_write_num(2, time.hour);case 5: time_update = 0;  // 分更新lcd1602_set_pos(3, 0);lcd1602_write_num(2, time.miunte);case 6: time_update = 0;  // 秒更新lcd1602_set_pos(6, 0);lcd1602_write_num(2, time.second);case 7: time_update = 0;  // 毫秒更新lcd1602_set_pos(11, 0);lcd1602_write_num(3, time.ms);break;default: break;   // 无更新}
}

附录 - 基本功能(clock.h)

#ifndef __CLOCK_H__
#define __CLOCK_H__#include "include.h"
#include "timer.h"extern time_t time;        // 电子万年历变量
extern u8 time_update;  // 更新显示等级,值越小等级越高,1为最高等级,0为最低void clock_init(void);    // 万年历初始化
void clock_deinit(void);    // 万年历去初始化
u8 clock_week_calc(u16 y, u8 m, u8 d);    // 星期计算
void clock_display_update(void);    // 显示更新#endif

附录 - 基本功能(clock.c)

#include "clock.h"
#include "lcd1602.h"code s8 week[7][4]={{"Sun"}, {"Mon"}, {"Tue"}, {"Wed"}, {"Thu"}, {"Fri"}, {"Sat"}};/*******************************************************************************
* 函 数 名         : clock_init
* 函数功能         : 万年历初始化
* 输    入         : void
* 输    出         : void
* 说    名         : none
*******************************************************************************/
void clock_init(void)    // 万年历初始化
{lcd1602_write_cmd(LCD1602_DISPLAY_CONTROL);  // 关闭光标和闪烁lcd1602_clean();lcd1602_set_pos(0, 1);lcd1602_write_num(4, time.year);lcd1602_write_data('-');lcd1602_write_num(2, time.month);lcd1602_write_data('-');lcd1602_write_num(2, time.day);lcd1602_set_pos(0, 0);lcd1602_write_num(2, time.hour);lcd1602_write_data(':');lcd1602_write_num(2, time.miunte);lcd1602_write_data(':');lcd1602_write_num(2, time.second);lcd1602_set_pos(11, 0);lcd1602_write_num(3, time.ms);lcd1602_write_str("ms");
}/*******************************************************************************
* 函 数 名         : clock_deinit
* 函数功能         : 万年历去初始化
* 输    入         : void
* 输    出         : void
* 说    名         : none
*******************************************************************************/
void clock_deinit(void)    // 万年历去初始化
{lcd1602_write_cmd(LCD1602_DISPLAY_CONTROL);  // 关闭光标和闪烁lcd1602_clean();
}/*******************************************************************************
* 函 数 名         : clock_week_calc
* 函数功能         : 星期计算
* 输    入         : y/m/d:年/月/日
* 输    出         : u8:星期数
* 说    名         : none
*******************************************************************************/
u8 clock_week_calc(u16 y, u8 m, u8 d)    // 星期计算
{u16 week_cnt = 0;u8 week_num;switch (m) {     // 从这一年的元旦算到该天为止( 含该天) 的天数case 12: week_cnt += 30;case 11: week_cnt += 31;case 10: week_cnt += 30;case  9: week_cnt += 31;case  8: week_cnt += 31;case  7: week_cnt += 30;case  6: week_cnt += 31;case  5: week_cnt += 30;case  4: week_cnt += 31;case  3: week_cnt += 28;case  2: week_cnt += 31;case  1: week_cnt += d; break;default: break;}if ((!(y % 4) && ((y % 100) || !(y % 400))) && (m > 2)) {    // 闰年补一天week_cnt++;}week_num = (y - 1 + (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400 + week_cnt) % 7;return week_num;
}/*******************************************************************************
* 函 数 名         : clock_display_update
* 函数功能         : 显示更新
* 输    入         : void
* 输    出         : void
* 说    名         : time_update需要及时清除
*******************************************************************************/
void clock_display_update(void)   // 显示更新
{switch (time_update) {        // 判断更新case 1: time_update = 0;  // 年更新lcd1602_set_pos(0, 1);lcd1602_write_num(4, time.year);case 2: time_update = 0;  // 月更新lcd1602_set_pos(5, 1);lcd1602_write_num(2, time.month);case 3: time_update = 0;  // 日更新lcd1602_set_pos(8, 1);lcd1602_write_num(2, time.day);lcd1602_set_pos(11, 1);  // 星期更新lcd1602_write_str(week[clock_week_calc(time.year, time.month, time.day)]);case 4: time_update = 0;  // 时更新lcd1602_set_pos(0, 0);lcd1602_write_num(2, time.hour);case 5: time_update = 0;  // 分更新lcd1602_set_pos(3, 0);lcd1602_write_num(2, time.miunte);case 6: time_update = 0;  // 秒更新lcd1602_set_pos(6, 0);lcd1602_write_num(2, time.second);case 7: time_update = 0;  // 毫秒更新lcd1602_set_pos(11, 0);lcd1602_write_num(3, time.ms);break;default: break;   // 无更新}
}

http://www.ppmy.cn/news/861813.html

相关文章

基于AT89C51单片机的电子万年历系统

点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/87708258 源码获取 主要内容: 电子万年历系统以实时时钟芯片DS1302和AT89C52单片机为主要研究对象,着重进行51单片机控制系统的设计研究和如…

基于单片机的电子万年历的设计

文末下载完整资料 基于51单片机的电子万年历的设计                                    摘 要    电子万年历是单片机系统的一个应用,由硬件和软件相配合使用。硬件由主控器、时钟电路、温度检测电路、显示电路、键盘接口5个模块组成。主控模块…

基于51单片机的电子万年历的设计-源代码

电子万年历的设计 设计要求: 利用51单片机、专用时钟芯片DS1302、DS18B20数字温度采集器及1602液晶显示器件设计一个万年历; 正确显示年月日,时分秒,星期等信息;显示环境温度;能够通过按键调整时间和设置…

电子万年历

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 一、实验内容(简述) 电子日历是通过单片机控制液晶显示器LCD1602实现电子日历功能。实验使用主要设备为计算机和单片机。在Keil软件平台上使用C51语言…

「电子万年历matlab仿真」——基于Matlab的电子万年历仿真实现

「电子万年历matlab仿真」——基于Matlab的电子万年历仿真实现 作为一种具有时间显示、日期查询、闹钟提醒等功能的电子产品,电子万年历已经成为了人们日常生活中不可或缺的一部分。而在现代科技的发展下,仿真技术的应用也越来越广泛,本篇文…

基于51单片机的电子万年历的设计

注意:全文word可在主页下载 摘 要 电子万年历是单片机系统的一个应用,由硬件和软件相配合使用。硬件由主控器、时钟电路、温度检测电路、显示电路、键盘接口5个模块组成。主控模块用AT89C52、时钟电路用时钟芯片DS1302、显示模块用LED数码管、温度检测采…

基于51单片机的电子钟万年历LCD1602显示

本设计是51单片机的电子钟万年历LCD1602显示(proteus仿真程序报告器件清单) 仿真图proteus 7.8 程序编译器:keil 4/keil 5 编程语言:C语言 编号C0002 资料文件下载链接: //https://docs.qq.com/doc/DS1NveWlLc0VXbGlI…

vue-element-admin || 后台管理三级/多级菜单设置

如图,基于vue-element-admin前端框架实现三级菜单,其中页面只对应三级菜单,无二级菜单的页面。 文件组织,在views文件夹下如下组织文件结构,其中第三级的菜单就是具体的.vue文件 在一级菜单hxb_sys下,要…