STC89C52单片机启动--综合案例秒表

代码功能:


1.自动开始计数,一共5个数码管来显示时间。一位数码管显示0-9,对应分度值是0.1s;两位数码管显示00-59,对应分度值1s;两位数码管显示00-59,对应分度值1min;上电后自动开始计时模式。

2.按下开关K1,计时暂停;按下开关K2,计时清0,从头开始计时;按下开关K3,显示520.1314,再次按下开关回到计时模式,显示520.1314期间计时仍在进行。

代码如下

delay.h  delay.c  main.c  SMG.h  SMG.c部分

//main.c
#include<regx52.h>
#include"function.h"
#include"delay.h"
#include"SMG.h"
void main(){
	Init_T0();
	while(1){
        //一直检测是否有按键按下,从而执行下面三个函数
		pause();
		clear();
		love();
        //这个flag变量其实没有必要写,但这里我想借这个别的文件中的变量来说明一个知识点
//因为当不显示520.1314的时候flag==1是肯定的,就会自动腾出来数码管来执行clock函数显示时间
		if(flag==1){
			clock();
		}
	}
}

//delay.h
#ifndef __delay_H__
#define __delay_H__
void delay(unsigned int t);
#endif

//delay.c
#include"delay.h"
void delay(unsigned int t){
	while(t--);
}

//SMG.h
#ifndef __SMG_H__
#define __SMG_H__
//传入显示哪个数码管,显示哪个数字,显示不显示小数点三个参数
void SMG_show(unsigned char pos,unsigned char num,unsigned char dot);
#endif

//SMG.c
#include<regx52.h>
#include"delay.h"
#include"SMG.h"
sbit A1=P2^2;
sbit B1=P2^3;
sbit C1=P2^4;
//这里是共阴数码管,定义了两个数组,分别是不显示点和显示点的
//第二的SMGdot[]数组第11个数据表示单独仅一个小数点
//用来显示520.1314中让一个数码管仅仅显示一个.
//最需要注意的是pos和C1,C2,C3对应顺序
unsigned char SMGndot[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
unsigned char SMGdot[11]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0x80};
void SMG_show(unsigned char pos,unsigned char num,unsigned char dot){
	switch(pos){
		case 1:C1=0;B1=0;A1=0;break;
		case 2:C1=0;B1=0;A1=1;break;
		case 3:C1=0;B1=1;A1=0;break;
		case 4:C1=0;B1=1;A1=1;break;
		case 5:C1=1;B1=0;A1=0;break;
		case 6:C1=1;B1=0;A1=1;break;
		case 7:C1=1;B1=1;A1=0;break;
		case 8:C1=1;B1=1;A1=1;break;
	}
		if(dot==1){
			P0=SMGdot[num];
		}
		else{
			P0=SMGndot[num];
		}

}

function.h function.c部分

//function.h
#ifndef __function_H__
#define __function_H__
extern unsigned int s;
extern unsigned int min;
extern unsigned int ms10;//0.5s
extern unsigned char flag;//控制显示静态520还是动态时钟
void Init_T0();
void pause();
void clear();
void love();
void clock();
#endif

//function.c
#include<regx52.h>
#include"delay.h"
#include"function.h"
#include"SMG.h"
unsigned int s=0;
unsigned int min=0;
unsigned int ms10=0;
unsigned char flag=1;
void clock(){
	SMG_show(1,ms10/2,0);
	delay(50);
	SMG_show(2,s%10,1);
	delay(50);
	SMG_show(3,s/10,0);
	delay(50);
	SMG_show(4,min%10,1);
	delay(50);
	SMG_show(5,min/10,0);
	delay(50);
}
void Init_T0(){
	TMOD=0x01;
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	ET0=1;
	EA=1;
	TR0=1;
}
void service_T0()interrupt 1{
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	ms10++;
	if(ms10==20){
		s++;
		ms10=0;
	}
	if(s==60){
		min++;
		s=0;
	}
}
void pause(){
	if(P3_1==0){
		delay(20);
		if(P3_1==0){
			while(P3_1==0);
				TR0=~TR0;//注意让定时器暂停我们改变的是TR0
		}
	}
}
void clear(){
	if(P3_0==0){
		delay(20);
		if(P3_0==0){
			while(P3_0==0);
				ms10=0;
				s=0;
				min=0;
		}
	}
}
void love(){
//这小段代码是检测按键有没有按下,从而改变变量flag的值
	if(P3_2==0){
		delay(100);
		if(P3_2==0){
			while(P3_2==0);
			if(flag==0){
				flag=1;
			}
			if(flag==1){
				flag=0;
			}
			//1.这段代码是在flag==0时一直让数码管显示数字,
因为这里多位数码管的显示都是利用不断循环刷新,视觉暂留效果,
所以我们要写到while(flag==0){}里面,目的是:没有再次按下按键K3的时候一直运行这段代码,
一直刷新才能一直显示8位数字。同时在这个函数中也要加上一段按键检测的代码,
来检测有没有按键再次按下,不然就永远困在这个while循环了。
//2.所以我们说刚刚在main.c中的if(flag==1)执行时钟代码时没有用的其实,完全可以不加
			if(flag==0){
				while(flag==0){
					if(P3_2==0){
						delay(100);
							if(P3_2==0){
								while(P3_2==0);
								flag=1;
							}
					}	
					SMG_show(8,5,0);delay(50);
					SMG_show(7,2,0);delay(50);
					SMG_show(6,0,0);delay(50);
					SMG_show(5,10,1);delay(50);
					SMG_show(4,1,0);delay(50);
					SMG_show(3,3,0);delay(50);
					SMG_show(2,1,0);delay(50);
					SMG_show(1,4,0);delay(50);
				}
			}
		}
	}
}

收获

1.定时器0暂停为什么是对TR0操作?

从图中我们可以看出来想让定时器计数暂停就要让控制信号K来断开,所以最好的方式就是通过TRx来控制定时器的启动和停止,这样同时也能保留当前加1计数器中的数字不变。如果是改变了我们IE寄存器的使能端,只能是让定时器中断过去不了,但前面计数仍在继续。

2.全局变量如何跨文件使用

在上面代码中我们在function.c文件中使用了flag全局变量,但是我们还想在main.c中使用这个全局变量,我们应该如何写代码?

其实这和让函数在被别的文件中使用差不多,都是在.h中声明,在.c中实现,在别的文件中用到的时候包含.h头文件就可以了,但是为什么变量的声明前面要额外加extern呢?

在 C 语言中,使用 extern 关键字来声明变量时,是为了告诉编译器该变量是在其他文件中定义的,需要在当前文件中进行引用。而对于函数的声明,通常不需要使用 extern 关键字是因为函数的声明本身就隐含了 extern 的含义。

3.并不是所有在.c文件中使用的全局变量和函数都要在.h文件添加声明

我们只用将那些,我们想让外面可以看到全局变量和函数在.h文件中声明。对于比如SMGndot[10]数组,又比如中断服务函数(中断服务函数都是自动调用的,一般就不会写到.h中,供应别的函数使用),这些变量和函数没必要或者我们不想提供给别的文件使用就可以不用在.h文件中添加声明。对于flag这个全局变量我们在main.c中要用到,就需要在.h文件添加声明了

4.巩固了学过的知识

在这个代码中使用到了独立按键,需要用到独立按键的去抖动处理。

使用到了数码管,需要我们通过74HC138译码器来实现对8个数码管的循环提供信号,利用视觉再留达到同时显示的效果,同时回顾了这里使用的是switch,代码上要注意的是C1对应译码器的高位,还要注意其他对应问题,这里我们还是用了两个数组来保存字段码。

使用到了定时器的知识,需要我们来进行一开始定时器的各个变量的初始化,定时器的启动和暂停,要编写中断服务函数。

5.加强了模块化编程

这里我们将暂停,清除,显示8位静态码,显示时间变化,定时器初始化,中断服务函数,这些功能函数写到了一个文件中。(再想说一下,并不是所有的这些数组,或者函数必须要在.h文件中添加说明)

将数码管具体显示实现也单独写到了一个文件中

这样写更清晰明了。

6.残留的缺点

就是这个在使用clear,pause函数的时候,在按下按键之后就不能保持原来正在计数的状态,因为函数会卡在while(P3_1==0)这些地方,在我们松开按键之后才能变为暂停的数字,中间会有一点没有显示的时候,当然快速按下按键然后松开就几乎可以达到连贯的感觉。

在我刚刚写完上面的那段话的时候我忽然就想到了解决方法,代码如下,就是卡在while(P3_1==0)的时候让它来执行clock();同样在clear函数中和love函数中也可做此优化。

while(P3_0==0){clock();};//clear

while(P3_2==0){clock();};//love

这样在按下后但没松开时可以保持原状态

void pause(){
	if(P3_1==0){
		delay(20);
		if(P3_1==0){
			while(P3_1==0){clock();};
				TR0=~TR0;
		}
	}
}

参考文章:关于C语言全局变量的定义和用法_c语言全局变量的定义与调用-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C# 提示信息的几种方式,总有一种是你不知道的

很久没写文章了&#xff0c;今天有时间就总结一下关于提示信息的几种写法。 &#xff08;1&#xff09;第一种提示信息是winform中的提示信息MessageBox.Show() 开发C#的朋友们肯定都用过这个提示信息&#xff0c;这个方法中有几个参数。 平时用的比较多的形式有&#xff1a;…

Springboot笔记-03

1.properties配置文件 #配制oerson的值 person.lastname张三 person.age12 person.birth2017/12/12 person.bossfalse person.dog.namedag person.dog.age15 person.maps.k1v1 person.maps.k212 person.listsa,b,c运行结果乱码 因为idea默认是utf-8编码而properties是ascall编…

奇客PDF评论:优点、缺点和个人的结论

作为一个在职业中接触大量PDF文档的人&#xff0c;PDF编辑器对我来说是基本必需品。我希望我的 PDF 编辑器使用起来非常简单&#xff0c;同时还提供普通的编辑和转换功能。 我对功能足够强大、又不失简单性的 PDF 编辑器的追求最初让我想到了奇客PDF。 在过去的1年里我一直在…

Stompy:一款针对时间戳的Timestomp工具

关于Stompy Stompy是一款功能强大的时间戳管理工具&#xff0c;在该工具的帮助下&#xff0c;广大研究人员能够轻松对指定文件或目录的时间戳进行修改和操作。该工具基于PowerShell开发&#xff0c;并且支持对目标目录中的所有文件执行递归时间戳操作。 功能介绍 1、修改独立…

鸿蒙Harmony应用开发—ArkTS(@Extend装饰器:定义扩展组件样式)

在前文的示例中&#xff0c;可以使用Styles用于样式的扩展&#xff0c;在Styles的基础上&#xff0c;我们提供了Extend&#xff0c;用于扩展原生组件样式。 说明&#xff1a; 从API version 9开始&#xff0c;该装饰器支持在ArkTS卡片中使用。 装饰器使用说明 语法 Extend(UI…

【NC】:追踪 CeO2上 Pt 单位点的形成、归宿和催化活性结果

摘要&#xff1a;铂单中心由于其高原子经济性而非常有吸引力&#xff0c;并且可以通过氧化高温处理在CeO2上生成。然而&#xff0c;它们的位置和活动引起了激烈的争论。此外&#xff0c;迄今为止&#xff0c;反应驱动的结构动力学尚未得到解决。在这项研究中&#xff0c;我们能…

JavaEE 初阶篇-多线程属性和方法

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 创建线程对象并命名 2.0 线程属性 2.1 线程属性 - ID 2.2 线程属性 - 名称 2.3 线程属性 - 后台线程 2.4 线程属性 - 判断 PCB 是否存活 2.5 线程属性 - 终止线程…

Redis实战篇-1

实战篇Redis 开篇导读 短信登录 这一块我们会使用redis共享session来实现 商户查询缓存 通过本章节&#xff0c;我们会理解缓存击穿&#xff0c;缓存穿透&#xff0c;缓存雪崩等问题&#xff0c;让小伙伴的对于这些概念的理解不仅仅是停留在概念上&#xff0c;更是能在代码…

数据格式化方法

首先你需要一个可以展示代码的组件&#xff1b; 我使用的是tech-ui(内部组件库)&#xff1b; 你如果没有类似的组件&#xff0c;可以参考以下链接替代&#xff1a; react-monaco-editor -- 代码编辑器(适用Umi)_umi monaco editor-CSDN博客 Codemirror -- 代码编辑器(react…

Flutter Widget:StatefulWidgetStatelessWidgetState

Widget 概念 Widget 将是构建Flutter应用的基石&#xff0c;在Flutter开发中几乎所有的对象都是一个 Widget 。 在Flutter中的widget 不仅表示UI元素&#xff0c;也表示一些功能性的组件&#xff0c;如&#xff1a;手势 、主题Theme 等。而原生开发中的控件通常只是指UI元素。…

RK3568驱动指南|第十三篇 输入子系统-第145 章 输入子系统上报数据格式分析

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

CodeSys创建自定义的html5控件

文章目录 背景创建html5control.xml文件控件界面以及逻辑的实现使用的资源安装自定义的html5控件库 背景 查看官方的资料&#xff1a;https://content.helpme-codesys.com/en/CODESYS%20Visualization/_visu_html5_dev.html 官方的例子&#xff1a;https://forge.codesys.com/…

#Linux(VMwareTOOL安装)

&#xff08;一&#xff09;发行版&#xff1a;Ubuntu16.04.7 &#xff08;二&#xff09;记录&#xff1a; &#xff08;1&#xff09; &#xff08;2&#xff09;打开虚拟机然后安装&#xff0c;出现灰色可能是已经安装过但是自己没有找到 &#xff08;3&#xff09;删除VM…

React【Day1】

B站视频链接 一、React介绍 React由Meta公司开发&#xff0c;是一个用于 构建Web和原生交互界面的库 React的优势 相较于传统基于DOM开发的优势 组件化的开发方式不错的性能 相较于其它前端框架的优势 丰富的生态跨平台支持 React的市场情况 全球最流行&#xff0c;大…

烟火AI识别检测算法在新能源汽车充电桩站点的应用方案

新能源汽车作为现代科技与环保理念的完美结合&#xff0c;其普及和应用本应带给人们更加便捷和绿色的出行体验。然而&#xff0c;近年来新能源汽车充电火灾事故的频发&#xff0c;无疑给这一领域投下了巨大的阴影。这不禁让人深思&#xff0c;为何这一先进的交通工具在充电过程…

OpenCV+OpenCV-Contrib源码编译

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、OpenCV是什么&#xff1f;二、OpenCV 源码编译1.前期准备1.1 源码下载1.2 cmake安装1.3 vscode 安装1.4 git 安装1.5 mingw安装 2.源码编译2.1 打开cmake2.…

【科研基础】VAE: Auto-encoding Variational Bayes

[1]Kingma, Diederik P., and Max Welling. “Auto-encoding variational bayes.” arXiv preprint arXiv:1312.6114 (2013). 文章目录 1-什么是VAE1.1-目标1.2-Intractability:1.3-Approximation use NN:1.4-最大化 L ( θ , ϕ ; x ) L(\theta,\phi;x) L(θ,ϕ;x):1.5-优化 …

数据结构——二叉树-堆(堆的实现,堆排序,TopK问题)

目录 前言 1.树的概念及结构 1.1 树的概念 1.2 树的相关概念 1.3 树的表示 2. 二叉树的概念及结构 2.1概念 2.2 特殊的二叉树 2.3 二叉树的性质 2.4 二叉树的存储结构 3. 堆 3.1 堆的概念及结构 3.2 堆的实现 3.1.2 数据结构的设计和文件准备 3.1.2堆的初始化和销…

小字辈(左子右兄加强版)

文章目录 题目描述思路AC代码总结 题目描述 输入样例1 5 1 2 0 2 4 3 3 0 0 4 0 5 5 0 0 输出样例1 3 4 5输出样例2 5 2 5 3 1 2 0 3 0 0 4 0 0 5 0 4 输出样例2 3 4 5思路 dfs 二叉树 存储结构 1.用结构体数组存储每个节点的父节点、左右节点 2.用vector存储答案 具体做法 1.…

[论文笔记] Dual-Channel Span for Aspect Sentiment Triplet Extraction

一种利用句法依赖和词性相关性信息来过滤噪声&#xff08;无关跨度&#xff09;的基于span方法。 会议EMNLP 2023作者Pan Li, Ping Li, Kai Zhang团队Southwest Petroleum University论文地址https://aclanthology.org/2023.emnlp-main.17/代码地址https://github.com/bert-ply…