TX-1C单片机实现多功能电子时钟

news2024/11/17 16:52:56

实验报告 电子时钟实验

  • 一、实验要求:
  • 二、实验结果
  • 三、实验思路
    • (一)模块整理
    • (二)流程图绘制
    • (三)C51编程
  • 四、实验总结
    • (一)未完成的部分
    • (二)待优化的部分

一、实验要求:

利用定时计数器,设计一个电子时钟,使用前面使用过的显示子程序。从左到右依次显示时分秒。有两种方法实现,一种是在中断程序中计数,产生时分秒计数,送显示缓冲区。另一种是中断程序每一秒清除一个位变量,而主程序通过监视位变量的变化来知道每秒的时间。
进而要求:
①加入时间调整程序,使用两个或三个按钮,调节当前的时间。类似平常使用的电子表。可以让正在调整的位闪烁显示。
②可以加入一个闹钟钟设置,当所定的时间到时,产生断续的蜂鸣声。可以加入日历的功能。

二、实验结果

数码管显示24小时制电子时钟;
矩阵按键S11时钟界面、S15倒计时界面、S12时间设置界面;
S12按下循环调整时、分、秒,处于时间设置界面时L8闪烁;
L1亮调整时、L2亮调整分、L3亮调整秒;
S13按下数值加1,S17按下数值减1;
倒计时结束后蜂鸣器间隔鸣叫;
S16按下一键清零时分秒

三、实验思路

(一)模块整理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(二)流程图绘制

在这里插入图片描述

(三)C51编程

#include <reg51.h>

sbit L8 = P1^7;
sbit LED = P2^5;
sbit BUZZ = P2^3;
sbit DULA =	P2^6;	
sbit WELA =	P2^7;	

unsigned char num[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,
					0x7D,0x07,0x7F,0x6F,};
 
unsigned char second,minute,hour = 0;	


void delay(unsigned int t) 
{ 
	while(t--);
}

void Init_Timer()	
{
	TMOD = 0x21; 	
	
	TH0 = 0x3C;  	//50ms=0.05s
	TL0 = 0xB0;  	
	TR0 = 1;  		
	ET0 = 1;  		
	
	TH1 = 0x00; 
	TL1 = 0x38;
	TR1 = 0;
	ET1 = 1;
	
	EA = 1;  		
}


unsigned char flag = 0;
unsigned char count = 0;	
void Service_Timer0() interrupt 1		//T0中断服务函数
{
	TH0 = 0x3C; 	
	TL0 = 0xB0;  	
		
	
	count++;
	if(count == 20)			//20 * 50ms = 1s
	{
		count = 0;
		if(flag == 0)		//正计时状态
		{
			second++;
			if(second == 60)
			{
				second = 0;
				minute++;
				if(minute == 60)
				{
					minute = 0;
					hour++;
					if(hour == 24)
					{
						hour = 0;		
					}
				}
			}
		}
		if(flag == 1)		//倒计时状态
		{
			if(second == 0)
			{
				if(minute == 0)
				{
					if(hour == 0)
					{
						TR0 = 0;		//终止倒计时
						TR1 = 1;
						flag = 3;		//蜂鸣器标志位
					}
					else{
						hour--;
						minute = 59;
					}
				}
				else{
					minute--;
					second = 59;
				}
			}
				else
				second--;
			
		}
	}
}


unsigned int count2 = 0;
void Service_Timer1() interrupt 3		//T1中断服务函数
{
	count2++;
	if(count2 == 1500)		//0.2ms * 1500 = 0.2s
	{
		L8 = ~L8;
		count2 = 0;
		if(flag == 3)
		{
			BUZZ = ~BUZZ;
		}
	}
}


void s_Display(unsigned char sec)
{
	DULA=1;			
	P0=num[sec%10];	
	DULA=0;			
	WELA=1;			
	P0=0XDF;		//POS_6
	WELA=0;			
	delay(150);		

	DULA=1;
	P0=num[sec/10];
	DULA=0;
	WELA=1;
	
	P0=0XEF;		//POS_5
	WELA=0;
	delay(150);
}
	
void m_Display(unsigned char min)
{
	DULA=1;
	P0=num[min%10];
	DULA=0;
	WELA=1;
	P0=0XF7;		//POS_4		
	WELA=0;
	delay(150);
	
	DULA=1;
	P0=num[min/10];	
	DULA=0;
	WELA=1;
	P0=0XFB;		//POS_3	
	WELA=0;
	delay(150);
}
	
void h_Display(unsigned char hor)
{
	DULA=1;
	P0=num[hor%10];
	DULA=0;
	WELA=1;
	P0=0XFD;		//POS_2		
	WELA=0;
	delay(150);
	
	DULA=1;
	P0=num[hor/10];	
	DULA=0;
	WELA=1;
	P0=0XFE;		//POS_1		
	WELA=0;
	delay(150);
}

void SMG_Display()
{
	s_Display(second);
	m_Display(minute);
	h_Display(hour);
}


sbit R1 = P3^0;
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;

sbit C1 = P3^4;		
sbit C2 = P3^5;
sbit C3 = P3^6;
sbit C4 = P3^7;

unsigned char stat = 0; 
void Key_Scan()
{
	C2 = 0;
	C1 = C3 = C4 = 1;
	if(R2 == 0)			//S11按下,暂停/启动正计时界面
	{
		flag = 0;
		SMG_Display();
		TR1 = 0;		//不属于调整时间状态
		
		LED = 1;
		P1 = 0xff;
		LED = 0;
		
		if(R2 == 0)
		{
			TR0 = ~TR0;		
		}
		while(R2 == 0)
		{
			SMG_Display();
		}
	}
	if(R3 == 0)			//S16按下,暂停/启动倒计时界面
	{
		flag = 1;
		SMG_Display();
		TR1 = 0;		//不属于调整时间状态
		
		LED = 1;
		P1 = 0xff;
		LED = 0;
		
		if(R3 == 0)
		{
			TR0 = ~TR0;		
		}
		while(R3 == 0)
		{
			SMG_Display();
		}
	}
	
	
	C3 = 0;
	C1 = C2 = C4 = 1;
	if(R2 == 0)			//S12按下,调整时间界面按键
	{
		LED = 1;
		SMG_Display();
		if(R2 == 0)
		{
			if(TR0 == 0)		//必须在停止界面下调整时间
			{
				TR1 = 1;
				switch(stat)
				{
					case 0: stat = 1; P1 = 0xFE; break;		//s位调整
					case 1: stat = 2; P1 = 0xFD; break;		//m位调整
					case 2: stat = 0; P1 = 0xFB; break;		//h位调整
				}
			}
			
		}
		while(R2 == 0)
		{
			SMG_Display();
		}
	}
	if(R3 == 0)			//S15按下,复位按键
	{
		SMG_Display();
		
		LED = 1;
		P1 = 0xff;
		LED = 0;
		
		if(R3 == 0)
		{
			TR0 = 0;		
			TR1 = 0;
			LED = 0;
			second = minute = hour = 0;	
			
		}
		while(R3 == 0)
		{
			SMG_Display();
		}
	}
	
	
	C4 = 0;
	C1 = C2 = C3 = 1;
	if(R2 == 0)		//S13按下,加1
	{
		SMG_Display();
		if(TR1 == 1)
		{
			if(R2 == 0)
		{
			switch(stat)
			{
				case 1 : 
					second++;
					if(second == 60)
					second = 0;
					break;
				case 2 :
					minute++;
					if(minute == 60)
					minute = 0;
					break;
				case 0 : 
					hour++;
					if(hour == 24)
					hour = 0;
					break;
			}
		}
		}
		
		while(R2 == 0)
		{
			SMG_Display();
		}
	}
	if(R3 == 0)		//S17按下,减1
	{
		SMG_Display();
		if(TR1 == 1)
		{
			if(R3 == 0)
			{
				switch(stat)
				{
					case 1 : 
						if(second == 0)		//先判断,后减1
						second = 59;
						else
						second--;
						break;
					case 2 :
						if(minute == 0)
						minute = 59;
						else
						minute--;
						break;
					case 0 : 
						if(hour == 0)
						hour = 23;
						else
						hour--;
						break;
				}
			}
		}
		while(R3 == 0)
		{
			SMG_Display();
		}
	}
		
}

 
void main(){
	second = 54;		
	minute = 59;
	hour = 23;
	LED = 0;
	Init_Timer();		
	while(1)
	{	
		SMG_Display();	
		Key_Scan();		
	}
}

四、实验总结

(一)未完成的部分

1.让正在调整的位数码管闪烁显示。
从TX-1C的原理图中可以看到其位选和段选都需要通过P0口赋值,所以分别用了两个74HC573锁存器来分别锁存两个值,使两者互不干扰。所以想要实现位闪烁,一方面应该要选中相应的位选,在该位上实现闪烁功能;另一方面利用定时器写一个延时程序,赋当前要显示的值持续一段时间,再赋熄灭数码管显示的值持续一段时间,两个赋值之间循环,间隔点亮实现闪烁功能。
2.实现日历功能。实际上也是一个数码管显示界面,需要对年、月、日进行设定。方法一,通过定时器对日期进行累加,但是稍显麻烦,且中断需要快进快出,所以这个方法不太理想;方法二,通过时钟的24小时计时对日进行累加,再到月、年的累加,用此方法实现较为可行。

(二)待优化的部分

1.进一步实现从倒计时界面切换到时钟界面时,不影响时钟持续的运行。此实验中,时钟和倒计器用了同一个定时器,所以没能够实现两者之间互不影响的功能。后续可以用两个定时器将二者功能分开,利用switch-case状态机实现按键控制时钟和倒计时之间循环切换,且不干扰时钟的持续运行。
2.进一步实现温度显示界面。TX-1C实验板上有DS18B20温度模块,可以编写相关程序,实现时钟、闹钟、温度相互切换显示的功能

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

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

相关文章

layui框架实战案例(22):多附件上传实战开发实录(php后端、文件删除、数据库删除)

layUI框架实战案例系列文章 layui框架实战案例(21)&#xff1a;layui上传的哪些事(layui.upload组件、 file文件域、php后台上传)layui框架实战案例(20)&#xff1a;常用条件判断和信息展示技巧(图片预览、动态表格、短信已读未读、链接分享、信息脱敏、内置框架页)layui框架实…

【Spring Cloud系列】-Eureka服务端高可用详解

【Spring Cloud系列】-Eureka服务端高可用详解 文章目录 【Spring Cloud系列】-Eureka服务端高可用详解一. 序言二. 什么是高可用性三. 什么是CAP一致性&#xff08;Consistency&#xff09;可用性&#xff08;Availability&#xff09;分区容错&#xff08;Partition-toleranc…

2.8 基于DPDK的UDP用户态协议栈实现

目录 一、网络协议栈1、**网络通信过程**2、**dpdk** 二、dpdk环境1、dpdk环境开启2、Windowe下配置IP和MAC地址的映射 三、实现用户态协议栈ustack1、UDP协议2、代码 四、dpdk一些基本函数接口rte_eal_init()rte_pktmbuf_pool_create()rte_socket_id()rte_eth_dev_configure()…

Java连接MySQL对数据实现增删改查

在实现好的窗口实现 添加修改删除查询数据的方法 以如下数据实验 statement自带的函数使用说明execute &#xff08;SQL&#xff09;执行给定的SQL语句返回一个或多个结果结果集 execute方法应该仅在语句能返回多个ResultSet对象、多个更新计数或ResultSet对象与更新计数的组…

Verilog | 基4 booth乘法器

上接乘法器介绍 原理 跟基2的算法一样&#xff0c;假设A和B是乘数和被乘数&#xff0c;且有&#xff1a; A ( a 2 n 1 a 2 n ) a 2 n − 1 a 2 n − 2 … a 1 a 0 ( a − 1 ) B b 2 n − 1 b 2 n − 2 … b 1 b 0 \begin{align}A&(a_{2n1}a_{2n})a_{2n−1}a_{2n−2}……

安卓期末考试知识总结(3)

文章目录 第五章 数据存储文件存储(非重点)内部存储获取或者打开目录操作文件 外部存储区 SharedPreferences存储写入Shared Preferences读取数据 SQLite数据库SQLite数据库的创建操作数据库数据Curosr数据库的事务 第五章 数据存储 简述Android数据存储的方式 Android平台提供…

FreeRTOS:任务通知

目录 一、任务通知简介二、发送任务通知2.1 函数xTaskNotify()2.2函数xTaskNotifyFromISR()2.3函数xTaskNotifyGive()2.4函数vTaskNotifyGiveFromISR()2.5函数xTaskNotifyAndQuery()2.6函数xTaskNotifyAndQueryFromISR() 三、获取任务通知3.1函数ulTaskNotifyTake()3.2函数xTas…

[进阶]Java:打印流、Properties、common-io框架

打印流&#xff1a; 作用&#xff1a;打印流可以实现方便、高效的打印数据到文件中去。打印流一般是&#xff1a;PrintStream&#xff0c;PrintWriter两个类。可以实现打印什么数据就是什么数据&#xff0c;例如打印整数97写出去就是97&#xff0c;打印boolean的true&#xff…

chatgpt赋能python:Python截取某段文字的方法

Python截取某段文字的方法 在处理文本数据时&#xff0c;截取某段文字是常见需求。Python作为一门优秀的脚本语言&#xff0c;提供了多种方法来完成这个任务。本篇文章将介绍Python截取某段文字的几种方便易用的方法。 方法一&#xff1a;使用切片 Python中的切片操作可以方…

JavaScript的一些编程题分享

将字符串abc-def-ghi转换为驼峰格式 这里我们的思路是利用字符串方法和正则表达式 const str abc-def-ghi;const camelCaseStr str.replace(/[-_][^-_]/g, match > match.charAt(1).toUpperCase());console.log(camelCaseStr); // abcDefGhi 这里使用了 replace 方法&a…

haproxy

haproxy haproxy一&#xff1a;常见的Web集群调度器1.软件2.硬件3.LVS &#xff0c;Nginx &#xff0c;Haproxy 的区别&#xff1a; 二&#xff1a;Haproxy应用分析1.HAProxy的主要特性有&#xff1a;2.HAProxy负载均衡策略非常多&#xff0c;常见的有如下8种&#xff1a; 三&a…

MySQL8.0数据库开窗函数

简介 数据库开窗函数是一种在SQL中使用的函数&#xff0c;它可以用来对结果集中的数据进行分组和排序&#xff0c;以便更好地分析和处理数据。开窗函数与聚合函数不同&#xff0c;它不会将多行数据聚合成一行&#xff0c;而是保留每一行数据&#xff0c;并对其进行分组和排序。…

Linux中/dev/random和/dev/urandom的作用

1./dev/random和/dev/urandom介绍 在Linux环境中&#xff0c;我们会用到/dev/random和/dev/urandom&#xff0c;今天为大家讲讲/dev/random和/dev/urandom的作用以及使用场景。 1.1./dev/random介绍 /dev/random是一个特殊的字符设备文件&#xff0c;用于生成“高质量”的随…

Python面向对象编程1-面向过程的简单纸牌游戏程序 项目1.1 定义纸牌的花色和点数

总项目目标&#xff1a;用面向过程思想设计一个简单的纸牌游戏程序&#xff0c;称为"Higher or Lower"&#xff08;高还是低&#xff09;。游戏中&#xff0c;玩家需要猜测接下来的一张牌是比当前牌高还是低。根据猜测的准确性&#xff0c;玩家可以得到或失去相应的积…

Unity UGUI1——基础组件概述

一、UGUI 介绍 ​ UGUI 是 Unity 引擎内自带的 UI 系统&#xff0c;官方称之为&#xff1a;Unity UI ​ 是目前 Unity 商业游戏开发中使用最广泛的 UI 系统开发解决方案 ​ 它是基于 Unity 游戏对象的 UI 系统&#xff0c;只能用来做游戏 UI 功能 ​ 不能用于开发 Unity 编…

【MarkDown】CSDN Markdown之Git图gitGraph详解

Git图 Git图是对不同分支上的Git提交和Git操作&#xff08;命令&#xff09;的图形化表示。 这种类型的图特别适合开发人员和DevOps团队分享他们的Git分支策略。例如&#xff0c;它可以更容易地可视化git流的工作方式。 Mermaid可以呈现Git图,但是只有v10.2.3 才支持。 代码…

kubernets 笔记

kubernets 笔记 kubernets 安装 1. 环境准备 硬件要求 内存&#xff1a;2GBCPU&#xff1a;2 核硬盘&#xff1a;30GB 本次环境说明 操作系统&#xff1a;CentOS 7.9内核版本&#xff1a;3.10.0-1160.76.1.el7.x86_64k8s-m&#xff1a;192.168.222.3k8s-s01&#xff1a;192.…

安装Apache、MySQL、PHP、论坛实操

文章目录 一、安装Apache1、准备阶段2、开始安装3、浏览器访问验证 二、部署MySQL三、部署php四、部署BBS论坛 一、安装Apache 1、准备阶段 &#xff08;1&#xff09;准备源码包 httpd-2.4.29.tar.gz apr-1.6.2.tar.gz apr-util-1.6.0.tar.gz cd /opt tar xf apr-1.6.2.tar…

【Windows】创建Windows远程桌面快捷方式

【Windows】创建Windows远程桌面快捷方式 1、背景2、操作 1、背景 windows系统自带了远程连接工具&#xff0c;可以实现局域网内的远程控制&#xff0c;参考&#xff1a; 【Windows】局域网内远程桌面控制 https://blog.csdn.net/jn10010537/article/details/130926888 但是w…

【Leetcode -404.左子叶之和 -543.二叉树的直径】

Leetcode Leetcode -404.左子叶之和Leetcode -543.二叉树的直径 Leetcode -404.左子叶之和 题目&#xff1a;给定二叉树的根节点 root &#xff0c;返回所有左叶子之和。 示例 1&#xff1a; 输入: root [3, 9, 20, null, null, 15, 7] 输出 : 24 解释 : 在这个二叉树中&…