51单片机编程基础(C语言):电子时钟(LED1602作为显示)

题目要求:

审题时这个题是用数码管来显示的,数码管显示时钟我完成了一个,只是要求跟他不一样,所以这次想用LCD1602来显示,所以我先用LCD1602完成,再用数码管完成(其实也只要在我之前的项目基础上改一下就OK了)。

其实从第一个要求就看出来了,数码管无法显示:,只能显示.这次我用LCD显示,把所以得.改为:

1、显示“时.分”进行显示,例如“12.18”,其中.每秒闪烁一次。

2、能够校正时间的时和分,按键分为5个功能键

(1)设定键:在计时模式时,按下此键时停止计时,进入设置状态,并切换到分钟的设置状态,再按一次切换到小时的设置状态,每按下一次完成时.分设置的切换,用点亮时.分个位的数码管小数点表示分或秒处于设置状态。在闹钟时间设定状态时,按下此键同样进入设置状态,完成分、秒设置的切换。

(2)递增键:在设置状态时,按一次递增键,被设置的分钟数字或时钟数字增1,持续按下数字自动增1。

(3)递减键:在设置状态时,按一次递减键,被设置的分钟数字或时钟数字减1,持续按下数字自动增1。

(4)计时键:在设置状态或闹钟时间设定状态时,按下此键则单片机切换到计时的显示模式,按照新的时.分设置值进行计时。如果已经在计时状态则此键无效。

(5)闹钟键:在计时模式时,按下此键则单片机切换到闹钟时间设定状态的显示模式。等待“设定键”、“递增键”、“递减键”来设定分钟和秒钟。

3、当计时到闹钟设定时间,用发光二极管闪烁,十秒钟后结束闪烁,正常计时

总代码:

main.c     剩下的都是模块化编程好的,在我的模块化编程大全里面,

调试视频在我视频里

#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "MatrixKey"
#include "Timer0.h"unsigned char hour=23;  //小时位
unsigned char min=57;  //分钟位  
unsigned char miao=0;   //秒位
unsigned char keyNumber;     //接收矩阵键盘的返回值
unsigned char Mode=0;       // :显示标志位
unsigned char Start=0;       // 0为开始计时,1暂停计时
unsigned char min_hour_set; //当S1按下时,切换到计时小时和分钟设置位
unsigned char clock_hour;//闹钟的小时位
unsigned char clock_min;  //闹钟的分钟位 
unsigned char clock_miao;   //闹钟的秒位
unsigned char clock_counttime=0; //界面显示标记位,0为显示时钟模式,1为显示clock模式
unsigned char clock_min_clock_hour_set; //在闹钟模式显示下,切换到闹钟小时和分钟设置位   //按键不可能同时是两个值。
unsigned char flag=0;  //处于计时界面下,flag=0,处于clock界面下,flag=1,//flag=0时,此时按下S1就是时钟模式设置键,flag=1,此时就是clock模式设置键
unsigned char who=0;   //由于加加,减减键是对min,hour起作用,即使进入闹钟模式,按下s1,按加加键无法改变闹钟的设置//反而让计时模式下的时钟改变了,因为min_hour_set非0即1,//所以对加加,减减键设置标志位,
sbit  LED=P2^0;
sbit BEEP=P2^5;
unsigned int i=1000;    //蜂鸣器报警时长。
unsigned int j=10;void main()
{Timer0Init();LCD_Init();LCD_ShowChar(2,3,':');while(1){keyNumber=MatrixKey();if(Mode==0){LCD_ShowChar(2,3,':');}if(Mode==1){LCD_ShowChar(2,3,' ');}if(clock_counttime==0){LCD_ShowString(1,1,"count time");LCD_ShowNum(2,4,min,2);//更新显示LCD_ShowNum(2,15,miao,2);//更新显示LCD_ShowNum(2,1,hour,2);}if(clock_counttime==1){LCD_ShowString(1,1,"clock      ");LCD_ShowString(2,7,"           ");LCD_ShowNum(2,4,clock_min,2);//更新为闹钟模式显示LCD_ShowNum(2,1,clock_hour,2);//更新为闹钟模式显示}if(keyNumber==5)//S5按下,进入闹钟模式界面{clock_counttime=1;LCD_ShowString(1,12,"        ");flag=1;who=1;}if(keyNumber==4)//S4按下,进入计时模式界面{clock_counttime=0;LCD_ShowString(2,7,"           ");LCD_ShowString(1,12,"        ");Start=0;flag=0;who=0;}if(flag==0){if(keyNumber==1)//S1按下 进入设置按键{Start=1;min_hour_set++;LCD_ShowString(2,7,"min ");if(min_hour_set>=2){min_hour_set=0;LCD_ShowString(2,7,"hour");}		}}if(flag==1){	if(keyNumber==1)//S1按下 进入设置按键{clock_min_clock_hour_set++;LCD_ShowString(1,12,"min        ");if(clock_min_clock_hour_set>=2){clock_min_clock_hour_set=0;LCD_ShowString(1,12,"hour       ");}		}}if(keyNumber==2)//S2按下,设置加加键{if(who==0){if(min_hour_set==1)//分钟设置状态{min++;if(min>=60){min=0;}}if(min_hour_set==0)//小时设置状态{hour++;if(hour>=24){hour=0;}}}if(who==1){if(clock_min_clock_hour_set==1)//时钟分钟设置状态{clock_min++;if(clock_min>=60){clock_min=0;}}if(clock_min_clock_hour_set==0)//时钟小时设置状态{clock_hour++;if(clock_hour>=24){clock_hour=0;}}}}if(keyNumber==3)//S2按下  设置减减键{if(who==0){if(min_hour_set==1)//分钟设置时间{if(min==0){min=60;}min--;}if(min_hour_set==0)//小时设置状态{if(hour==0){hour=24;}hour--;}}if(who==1){if(clock_min_clock_hour_set==1)//时钟分钟设置状态{if(clock_min==0){clock_min=60;}clock_min--;}if(clock_min_clock_hour_set==0)//时钟小时设置状态{if(clock_hour==0){clock_hour=24;}clock_hour--;}}}if(clock_hour==hour&&clock_min==min){
//			LED=0;
//			while(j--)//LED闪烁
//			{
//			 LED=~LED;
//			 Delay(1);
//			}while(i--){BEEP=!BEEP;Delay(1);}i=1000;}}
}
//定时器0中断函数模板
void Timer0_Routine() interrupt 1
{static unsigned int T0Count;TL0 = 0x18;		//设置定时初值TH0 = 0xFC;		//设置定时初值T0Count++;if(T0Count>=1000){T0Count=0;if(Start==0){	miao++;if(miao>=60){min++;miao=0;}if(min>=60){hour++;min=0;}if(hour>=24&&min==0){hour=0;}Mode++;if(Mode>=2){Mode=0;}}}
}

设计思路:

一个一个功能实现,但是要有自己的整体框架,不然后面会越敲越晕,因为都是嵌套的,这个跳到那个,没有系统的框图是不行的,我刚开始就没设计闹钟的那一块代码,所以定时器模块写完之后,突然加闹钟模块就很乱,思绪就没有了,后面就休息了,特别累的时候,想不明白的时候一定要好好休息,也许休息好了就会有灵感了,我就是休息之后,想到应该要设置两个界面显示。一个是闹钟界面,一个是时钟界面,通过按键来切换,

项目总结:

其实在设计的时候,我都是一步一步调试的,每写一段代码自己去找问题,去发现跟自己预期的是不是一样的。有问题就去找解决方案,确实这一个过程是极其费时间的,特别遇到一些bug,更会折磨人的心态,但是往往是这些问题,才会让我们更加去思考,

比如我在实现第一个功能时,就花了很多时间,也遇到了bug.

1.先实现第一个要求(wo当时第一步开始想的是这样的)

直接调用LCD1602模块和延时函数模块,下面是main函数代码

#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
unsigned char hour=12;
unsigned char min=18;void main()
{LCD_Init();LCD_ShowNum(2,1,hour,2);LCD_ShowNum(2,4,min,2);LCD_ShowChar(2,3,':');while(1){ Delay(1000);LCD_ShowChar(2,3,' ');Delay(1000);LCD_ShowChar(2,3,':');}
}

虽然很好的实现了,但是后面又出现问题了。。。。。

但是配上定时器扫描后,就会让秒每隔2秒显示一次。 因为Delay了2秒,然而,定时器与CPU是分开工作的,虽然题目不对秒显示有要求,但是我觉得上面显示不妥,所以我把:的显示放在定时器中断里面,这样:就会按秒每加一而闪烁。 下面是代码。

#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "MatrixKey"
#include "Timer0.h"
unsigned char hour=12;//小时位
unsigned char min=18;//分钟位  
unsigned char miao=0;   //秒位
unsigned char keyNumber;   //接收矩阵键盘的返回值
unsigned char Mode=0;  // :显示标志位void main()
{Timer0Init();LCD_Init();LCD_ShowNum(2,1,hour,2);while(1){ LCD_ShowNum(2,4,min,2);LCD_ShowNum(2,15,miao,2);}
}//定时器0中断函数模板
void Timer0_Routine() interrupt 1
{static unsigned int T0Count;TL0 = 0x18;		//设置定时初值TH0 = 0xFC;		//设置定时初值T0Count++;if(T0Count>=1000){T0Count=0;miao++;if(miao==60){min++;miao=0;}if(Mode==0){LCD_ShowChar(2,3,':');}Mode++;if(Mode>=2){LCD_ShowChar(2,3,' ');Mode=0;}}
}

刚开始效果还是可以,但是把显示放在定时器中断中,就会出现bug.

在我完成第二个要求的时候。

2.实现第二个要求: 

第二个要求有点多,我们细分为5个小要求来完成。

要有5个功能键,独立按键只有四个,所以我选择矩阵键盘按键,(当然,你也可以选择独立按键,按一次是这个功能,按两次是另外一个功能,可以设置一个符号位,通过按键改变符号位,从而根据符号位不同来选择想要功能)

所以我矩阵键盘按键模块再次调用过来

1)设定键:在计时模式时,按下此键时停止计时,进入设置状态,并切换到分钟的设置状态,再按一次切换到小时的设置状态,每按下一次完成时.分设置的切换,用点亮时.分个位的数码管小数点表示分或秒处于设置状态。在闹钟时间设定状态时,按下此键同样进入设置状态,完成分、秒设置的切换。(我把这个键用矩阵键盘S1表示)

看到计时,肯定要计数器中断模块,我再把计时器中断调用过来。当然了,这个题只让显示分,小时,没有秒,所以我们设置一个变量来控制秒,秒=60时,min加一,min>60时,hour加一。

产生一个新的问题:我的LCD_ShowNum(2,1,hour,2);放在while循环里时,为了更新显示。为啥min显示后面总会出现一个0,或者一个奇怪的数字,我明明规定hour是两位显示啊,产生一个新的bug希望有人能帮我找到问题,上面的那个代码我没有放在while,没有更新显示,也没有出现min后面多个0;之前写的时钟都没问题的,按理说这个也没问题的。(bug)

为了解决上述问题,我把LCD_ShowNum(2,1,hour,2);放在了定时器中断中。(继续接连出现bug)

由于前面的bug,我把hour放在定时器中断中,暂停后,hour也不会更新显示,矛盾了,所以我还是放到了while(1)循环里更新显示了,bug还需要大家帮我解决啊,不然,看起来好别扭,

好奇怪,明明之前是坏的,写完矩阵键盘控制突然又好了。bug消失了,我觉得是单片机内部问题,可能你们应该不会遇到。但是为了想解决这个花了好多时间。(但是bug时好时坏)。

按下此键无法计时,所以我们又要设置一个标志位。Start=0; // 0为开始计时,1暂停计时,按下按键,Start=1,实现暂停。

切换到分钟的设置状态,再按一次,切换到小时的设置状态,(所以我们继续设置标志位,1为小时键,0位分钟位)切换是不是要调时间,我们顺道把第(2)(3)个要求完成。

(2)递增键:在设置状态时,按一次递增键,被设置的分钟数字或时钟数字增1,持续按下数字自动增1。(完成)(S2键)

(3)递减键:在设置状态时,按一次递减键,被设置的分钟数字或时钟数字减1,持续按下数字自动增1。(完成)  (S3键)

(4)计时键:在设置状态或闹钟时间设定状态时,按下此键则单片机切换到计时的显示模式,按照新的时.分设置值进行计时。如果已经在计时状态则此键无效。(S4键)(完成)

按下此键,进入计时状态,在设置状态或(闹钟时间设定状态)时,闹钟计时状态我们先不管,我还没做,

在设置状态时,我们不是把时和分设置好了。按下计时键,则单片机切换到计时的显示模式,按照新的时.分设置值进行计时。(所以这个键就是开始计时,因为之前暂停了。)如果已经在计时状态则此键无效。是不是要在Start==1,才能生效。

(5)闹钟键:在计时模式时,按下此键则单片机切换到闹钟时间设定状态的显示模式。等待“设定键”、“递增键”、“递减键”来设定分钟和秒钟。

在计时模式时,才能按下此按键,所以Start==0才能生效。进入闹钟模式是不是要回来,第四个要求,按下计时键回来

(这一部分的思路就完全错了)后面自己就再也没设计了。

第二天的时候,自己就从新开始构思,1s闪,为啥不用标志位去变呢1.以及后面遇到的问题,自己都一步一步去思考,去解决,

代码遇到的错误,中午括号

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/682295.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[计算机网络]---网络编程套接字

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、基础知识…

C++ //练习 6.7 编写一个函数,当它第一次被调用时返回0,以后每次被调用返回值加1。

C Primer&#xff08;第5版&#xff09; 练习 6.7 练习 6.7 编写一个函数&#xff0c;当它第一次被调用时返回0&#xff0c;以后每次被调用返回值加1。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /**********************…

如何将字体添加到 ONLYOFFICE 文档服务器 8.0

作者&#xff1a;VincentYoung 阅读本文&#xff0c;了解如何为自己的在线办公软件 ONLYOFFICE 文档服务器的字体库添加字体 ONLYOFFICE 文档是什么 ONLYOFFICE 文档是一个功能强大的文档编辑器&#xff0c;支持处理文本文档、电子表格、演示文稿、可填写表单、PDF 和电子书…

EsayExcel文件导入导出

目录 准备工作 监听器类 导入测试 导出测试 上传Excel 下载Excel 混合导出模板导出 headRowNumber(1)&#xff1a;从第几行开始读 准备工作 导入依赖 <!--easyexcel--> <dependency><groupId>com.alibaba</groupId>x<artifactId>easye…

QTabWidget和QTabBar控件样式设置(qss)

QTabWidget和QTabBar控件样式设置 1、QTabWidget样式可自定义的有哪些示例&#xff1a;效果图 2、QTabBar样式可自定义的有哪些示例效果图 1、QTabWidget样式可自定义的有哪些 QTabWidget::pane{} 定义tabWidgetFrameQTabWidget::tab-bar{} 定义TabBar的位置QTabWidget::tab{}定…

基于物联网的实时数据分析(简单介绍)

在当今这个信息化、数字化飞速发展的时代&#xff0c;物联网&#xff08;Internet of Things, IoT&#xff09;和实时数据分析成为了技术革新的两大支柱。对于刚入行的新手来说&#xff0c;理解这两个概念及其相互作用不仅是迈入这一领域的第一步&#xff0c;更是掌握未来技术趋…

Acwing---842.排列数字

排列数字 1.题目2.基本思想3.代码实现 1.题目 给定一个整数 n&#xff0c;将数字 1∼n排成一排&#xff0c;将会有很多种排列方法。 现在&#xff0c;请你按照字典序将所有的排列方法输出。 输入格式 共一行&#xff0c;包含一个整数 n。 输出格式 按字典序输出所有排列方案…

flask+python儿童福利院管理系统pycharm毕业设计项目

本系统解决了儿童福利院管理事务中的主要问题&#xff0c;包括首页、个人中心、爱心人士管理、员工管理、后勤人员管理、儿童信息管理、院所风采管理、活动管理、食谱管理、领养流程管理、政策法规管理、楼栋管理、宿舍管理、领养申请管理、义工申请管理、捐赠信息管理、宿舍物…

CTFshow web(php命令执行59-67)

web59 <?php /* # -*- coding: utf-8 -*- # Author: Lazzaro # Date: 2020-09-05 20:49:30 # Last Modified by: h1xa # Last Modified time: 2020-09-07 22:02:47 # email: h1xactfer.com # link: https://ctfer.com */ // 你们在炫技吗&#xff1f; if(isset($_POST…

一个 SpringBoot 项目能同时处理多少请求?

目录 1 问题分析 2 Demo 3 答案 4 怎么来的&#xff1f; 5 标准答案及影响参数一Tomcat配置 6 影响参数二 Web容器 7 影响参数三 Async 1 问题分析 一个 SpringBoot 项目能同时处理多少请求&#xff1f; 不知道你听到这个问题之后的第一反应是什么&#xff1f; 我大概…

支付交易——BIN服务

摘要 老王的杂货店里货很多&#xff0c;国产的&#xff0c;进口的&#xff0c;不同种类、不同品牌、不同型号的货&#xff0c;应有尽有。 货多了&#xff0c;老王就弄了个小本本记下店里卖的货有哪些&#xff0c;记得很详细&#xff0c;包括有哪些种类&#xff0c;每个种类里有…

ClickHouse--05--MergeTree 表引擎

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 MergeTree 系列表引擎前言MergeTree 系列表引擎 --功能MergeTree 系列表引擎 --种类 1.MergeTree1.1MergeTree 建表语句&#xff1a;1.2 MergeTree 引擎表目录解析查…

Acwing二分和前缀和(一)

数的范围 原题链接&#xff1a;https://www.acwing.com/problem/content/791/ 整数二分步骤&#xff0c;找一个区间&#xff0c;使得答案一定在区间中。找一个判断条件&#xff0c;使得该判断条件具有二段性&#xff0c;并且答案一定是该二段性的分界点。分析终点在该判断条件下…

toString()、equals()、clone()用法

Java中所有类的对象都可以直接使用Object类中提供的一些方法 1. toString()&#xff1a;返回对象的字符串表示形式&#xff0c;通常在类中重写&#xff0c;以便于返回的是对象的内容 2. equals()&#xff1a;判断两个对象的地址是否相等&#xff0c;直接使用也一样&#xff0c;…

社区店选址地理位置评估:大数据分析的力量

大家好&#xff0c;我是一名有着 5 年开店经验的鲜奶吧创业者。在这 5 年的时间里&#xff0c;我深切地体会到了选址对于一家社区鲜奶吧的重要性。一个好的地理位置可以为你的店铺带来源源不断的客流&#xff0c;而一个糟糕的位置则可能让你的创业之路充满坎坷。 在这里&#…

Qt之条件变量QWaitCondition详解

QWaitCondition内部实现结构图&#xff1a; 相关系列文章 C之Pimpl惯用法 目录 1.简介 2.示例 2.1.全局配置 2.2.生产者Producer 2.3.消费者Consumer 2.4.测试例子 3.原理分析 3.1.辅助函数CreateEvent 3.2.辅助函数WaitForSingleObject 3.3.QWaitConditionEvent …

一个小例子,告诉你什么是衍生式设计

之前好多小伙伴想让我介绍介绍Dynamo与衍生式设计&#xff0c;奈何最近太忙了&#xff0c;实在没时间弄这些~趁着端午节&#xff0c;今天用一个小案例&#xff0c;先简单让大家对衍生式设计有个初步认识&#xff0c;之后有时间&#xff0c;我再多写几篇关于这方面的文章&#x…

Java使用opencsv完成对csv批量操作

文章目录 前言一、maven二、造数三、代码部分1.OpenCsvController2.OpenCsvUtil3.StudentInfo4.CodeToValue 三、效果展示1.download2.upload 总结 前言 csv文件是不同于excel文件的另一种文件&#xff0c;常常以,作为分隔符&#xff0c;本篇将通过JavaBean的形式完成对csv文件…

Linux_进程地址空间

我们用c语言写的程序&#xff0c;经过编译后形成可执行程序存放在硬盘。当运行该程序时&#xff0c;操作系统将该程序加载到内存中&#xff0c;创建进程控制块&#xff0c;变为进程&#xff0c;然后开始执行该程序。大家是否想过&#xff0c;操作系统是如何加载的呢&#xff1b…

25天物理探索旅程 - 第三天:相对论时空观的构建

第三天的课堂&#xff0c;我们将踏上一段穿越时空的奇幻旅程&#xff0c;探索那个由爱因斯坦用天才智慧构建起来的相对论世界。想象一下&#xff0c;你手握一把名为“狭义相对论”的神奇钥匙&#xff0c;准备开启一扇通往全新宇宙观的大门。 首先&#xff0c;我们来聊聊同时性…