当前位置: 首页 > article >正文

51单片机应用开发(进阶)---定时器应用(电子时钟)

实现目标

1、巩固定时器的配置流程;

2、掌握按键、数码管与定时器配合使用;

3、功能1:(1)简单显示时间。显示格式:88-88-88(时-分-秒)

4、功能2:(1)K1功能键,按下按键选中时分秒进行调节;(2)K2:数值+1;(3)K3:数值-1;(4)K4:确认键,设置数值后按下确认,开始走时;(5)显示格式:88-88-88(时-分-秒)

5、功能3:(1)上面功能上,轮流显示年月日


一、电子时钟

        电子时钟是一种使用电子技术来显示当前时间的设备。与传统的机械时钟不同,电子时钟通过电子电路和显示器来展示时间,通常具有更高的准确性和更多的功能。以下是关于电子时钟的简介:

1.1 基本结构

  1. 显示器:电子时钟的核心部分,用于显示时间。常见的显示器类型包括液晶显示屏(LCD)、发光二极管显示屏(LED)以及近年来逐渐兴起的有机发光二极管显示屏(OLED)。
  2. 电子电路:负责时间的计算、存储与显示。电子电路可以由模拟电路或数字电路构成,现代电子时钟多采用微处理器控制的数字电路。
  3. 电源:为电子时钟提供工作所需的电能。常见的电源类型包括电池、交流电源或两者的结合。

1.2 主要功能

  1. 时间显示:电子时钟可以准确显示当前的时间,包括小时、分钟和秒。
  2. 日期和星期显示:许多电子时钟还具备显示当前日期和星期的功能。
  3. 定时功能:可以设置闹钟或提醒功能,以便在特定时间发出声音或光信号。
  4. 其他功能:如温度显示、湿度显示、计时器、倒计时等附加功能,使电子时钟更加实用。

1.3 种类与特点

  1. 数字电子时钟:以数字形式显示时间,具有简洁明了的特点。数字电子时钟通常采用LED或LCD显示屏,易于读取且耗电量低。
  2. 模拟电子时钟:通过指针和表盘来模拟传统机械时钟的显示方式。模拟电子时钟通常具有更高的装饰性,适合追求复古或经典风格的用户。
  3. 智能电子时钟:结合了智能技术,如Wi-Fi连接、语音识别等,可以实现更多高级功能,如天气预报、音乐播放、智能家居控制等。智能电子时钟通常与智能手机或其他智能设备配合使用,提供更加个性化的用户体验。

1.4 技术原理

        电子时钟的工作原理主要基于晶体振荡器产生的稳定频率信号。这个信号经过分频、计数等处理后,可以得到精确的时间信息。微处理器或专用的时间控制芯片会根据这些信息来控制显示器的显示内容,从而实现时间的准确显示。

1.5应用领域

        电子时钟广泛应用于各个领域,包括家庭、办公室、公共场所等。由于其准确度高、功能丰富且易于携带,电子时钟已成为现代生活中不可或缺的时间测量工具。

二、原理图设计

  

三、程序设计

3.1  基本程序(不带按键功能)

#include <REGX52.H>
 
//定义数码管位选信号控制脚
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;
 
sbit K1 = P3^1;//按键K1
sbit K2 = P3^0;//按键K2
 
char  H   = 22; //时计数
char  M   = 58; //分计数
char  S   = 45; //秒计数
 
//共阴极数码管显示0~F的段码数据
unsigned char gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
				0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};
 
void delay_10us(int ten_us)
{
	while(ten_us--);	
}

 
unsigned int g_Count;  //全局变量默认初始化为0
 
void Timer1_Init(void)
{
    TMOD = 0x10; //设置定时器1 工作模式1   0001 0000  
    TR1 = 1;     //开启定时器1
    TH1 = (65536-1000)/256;  //设置定时初值,高8位
    TL1 = (65536-1000)%256;  //设置定时初值,低8位
    ET1 = 1;  //开启定时器1 中断
	EA  = 1;  //开启总中断
}
 
void main(void)
{
	Timer1_Init();  //定时器1初始化
	while(1)
	{
	   	LSC=1;LSB=1;LSA=1;
		P0 = gsmg_code[H/10];
		delay_10us(5);
		P0 = 0x00;//消影
		
	   	LSC=1;LSB=1;LSA=0;
		P0 = gsmg_code[H%10];		
		delay_10us(5);
		P0 = 0x00;//消影
		
	   	LSC=1;LSB=0;LSA=1;
		P0 = gsmg_code[16];
		delay_10us(5);
		P0 = 0x00;//消影
		
	   	LSC=1;LSB=0;LSA=0;
		P0 = gsmg_code[M/10];		
		delay_10us(5);
		P0 = 0x00;//消影	

		LSC=0;LSB=1;LSA=1;
		P0 = gsmg_code[M%10];
		delay_10us(5);
		P0 = 0x00;//消影
		
	   	LSC=0;LSB=1;LSA=0;
		P0 = gsmg_code[16];
		delay_10us(5);
		P0 = 0x00;//消影
		
	   	LSC=0;LSB=0;LSA=1;
		P0 = gsmg_code[S/10];		
		delay_10us(5);
		P0 = 0x00;//消影	

		LSC=0;LSB=0;LSA=0;
		P0 = gsmg_code[S%10];
		delay_10us(5);
		P0 = 0x00;//消影		
	}
}
 
void Timer1_Rountine(void) interrupt 3  //1ms进一次中断
{
    TH1 = (65536-1000)/256;  //
    TL1 = (65536-1000)%256;  //重新赋初值才能保证下一次还是1ms
	  
    g_Count++;
    if(g_Count>=1000)  // 1S 计时
	{
		g_Count = 0;   //计数清零
		S++;
		if(S > 59)//1Min
		{
			S = 0;
			M++;
			if(M > 59)//1H
			{
				M = 0;
				H++;
			   if(H > 23)//1H
			   {
					H = 0;				
			   }
			}
		}	
	}
}



3.2  带按键调值功能程序

#include <REGX52.H>
 
//定义数码管位选信号控制脚
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;
 
sbit K1 = P3^1;//按键K1
sbit K2 = P3^0;//按键K2
sbit K3 = P3^2;//按键K3
sbit K4 = P3^3;//按键K4
 
char  H   = 22; //时计数
char  M   = 58; //分计数
char  S   = 45; //秒计数
 
char  mode = 0; //模式 
 
//共阴极数码管显示0~F的段码数据
unsigned char gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
				0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};
 
void delay_10us(int ten_us)
{
	while(ten_us--);	
}
 
 
unsigned int g_Count;  //全局变量默认初始化为0
 
void Timer1_Init(void)
{
    TMOD = 0x10; //设置定时器1 工作模式1   0001 0000  
    TR1 = 1;     //开启定时器1
    TH1 = (65536-1000)/256;  //设置定时初值,高8位
    TL1 = (65536-1000)%256;  //设置定时初值,低8位
    ET1 = 1;  //开启定时器1 中断
	EA  = 1;  //开启总中断
}
 
void main(void)
{
	Timer1_Init();  //定时器1初始化
	while(1)
	{
	   	LSC=1;LSB=1;LSA=1;
		P0 = gsmg_code[H/10];
		delay_10us(5);
		P0 = 0x00;//消影
		
	   	LSC=1;LSB=1;LSA=0;
		P0 = gsmg_code[H%10];		
		delay_10us(5);
		P0 = 0x00;//消影
		
	   	LSC=1;LSB=0;LSA=1;
		P0 = gsmg_code[16];
		delay_10us(5);
		P0 = 0x00;//消影
		
	   	LSC=1;LSB=0;LSA=0;
		P0 = gsmg_code[M/10];		
		delay_10us(5);
		P0 = 0x00;//消影	
 
		LSC=0;LSB=1;LSA=1;
		P0 = gsmg_code[M%10];
		delay_10us(5);
		P0 = 0x00;//消影
		
	   	LSC=0;LSB=1;LSA=0;
		P0 = gsmg_code[16];
		delay_10us(5);
		P0 = 0x00;//消影
		
	   	LSC=0;LSB=0;LSA=1;
		P0 = gsmg_code[S/10];		
		delay_10us(5);
		P0 = 0x00;//消影	
 
		LSC=0;LSB=0;LSA=0;
		P0 = gsmg_code[S%10];
		delay_10us(5);
		P0 = 0x00;//消影	


		if(K1 == 0)//如果按键K1按下
		{
			while(!K1);//松手检测
		    TR1 = 0;
			mode++;
			if(mode >3)
				mode = 1;
		}
		if(K4 == 0)//如果按键K4按下
		{
			while(!K4);//松手检测
            TR1 = 1; 
			mode = 0;
		}		
		
		if(K2 == 0)//如果按键K2按下
		{
			while(!K2);//松手检测
			switch (mode)
			{
				case 1:
					H++;
				    if(H > 23)
			        {
					   H = 0;				
			        }
					break;
				case 2:
					M++;
				    if(M > 59)
			        {
					   M = 0;				
			        }					
					break;
				case 3:
					S++;
				    if(S > 59)
			        {
					   S = 0;				
			        }										
					break;
			}
		}
		if(K3 == 0)//如果按键K2按下
		{
			while(!K3);//松手检测
			switch (mode)
			{
				case 1:
					H--;
				    if(H < 0)
			        {
					   H = 23;				
			        }
					break;
				case 2:
					M--;
				    if(M < 0)
			        {
					   M = 59;				
			        }					
					break;
				case 3:
					S--;
				    if(S < 0)
			        {
					   S = 59;				
			        }										
					break;
			}
		}
	}
}
 
void Timer1_Rountine(void) interrupt 3  //1ms进一次中断
{
    TH1 = (65536-1000)/256;  //
    TL1 = (65536-1000)%256;  //重新赋初值才能保证下一次还是1ms
	  
    g_Count++;
    if(g_Count>=1000)  // 1S 计时
	{
		g_Count = 0;   //计数清零
		S++;
		if(S > 59)//1Min
		{
			S = 0;
			M++;
			if(M > 59)//1H
			{
				M = 0;
				H++;
			   if(H > 23)//1H
			   {
					H = 0;				
			   }
			}
		}	
	}
}
 
 
 

3.3  轮换显示年月日功能程序

#include <REGX52.H>
 
//定义数码管位选信号控制脚
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;
 
sbit K1 = P3^1;//按键K1
sbit K2 = P3^0;//按键K2
sbit K3 = P3^2;//按键K3
sbit K4 = P3^3;//按键K4
 
char  H   = 22; //时计数
char  M   = 58; //分计数
char  S   = 45; //秒计数
 
char  mode = 0; //模式 
bit   Display_falg = 0; //显示标志位
char  S1   = 0; //秒计数
char  S2   = 0; //秒计数
//共阴极数码管显示0~F的段码数据
unsigned char gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
				0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};
 
void delay_10us(int ten_us)
{
	while(ten_us--);	
}
 
 
unsigned int g_Count;  //全局变量默认初始化为0
 
void Timer1_Init(void)
{
    TMOD = 0x10; //设置定时器1 工作模式1   0001 0000  
    TR1 = 1;     //开启定时器1
    TH1 = (65536-1000)/256;  //设置定时初值,高8位
    TL1 = (65536-1000)%256;  //设置定时初值,低8位
    ET1 = 1;  //开启定时器1 中断
	EA  = 1;  //开启总中断
}
 
void main(void)
{
	Timer1_Init();  //定时器1初始化
	while(1)
	{
        if (Display_falg == 1)
        {
			LSC=1;LSB=1;LSA=1;
			P0 = gsmg_code[2];
			delay_10us(5);
			P0 = 0x00;//消影
			
			LSC=1;LSB=1;LSA=0;
			P0 = gsmg_code[4];		
			delay_10us(5);
			P0 = 0x00;//消影
			
			LSC=1;LSB=0;LSA=1;
			P0 = gsmg_code[16];
			delay_10us(5);
			P0 = 0x00;//消影
			
			LSC=1;LSB=0;LSA=0;
			P0 = gsmg_code[1];		
			delay_10us(5);
			P0 = 0x00;//消影	
	 
			LSC=0;LSB=1;LSA=1;
			P0 = gsmg_code[1];
			delay_10us(5);
			P0 = 0x00;//消影
			
			LSC=0;LSB=1;LSA=0;
			P0 = gsmg_code[16];
			delay_10us(5);
			P0 = 0x00;//消影
			
			LSC=0;LSB=0;LSA=1;
			P0 = gsmg_code[0];		
			delay_10us(5);
			P0 = 0x00;//消影	
	 
			LSC=0;LSB=0;LSA=0;
			P0 = gsmg_code[8];
			delay_10us(5);
			P0 = 0x00;//消影		
			
		}
		else
		{
			LSC=1;LSB=1;LSA=1;
			P0 = gsmg_code[H/10];
			delay_10us(5);
			P0 = 0x00;//消影
			
			LSC=1;LSB=1;LSA=0;
			P0 = gsmg_code[H%10];		
			delay_10us(5);
			P0 = 0x00;//消影
			
			LSC=1;LSB=0;LSA=1;
			P0 = gsmg_code[16];
			delay_10us(5);
			P0 = 0x00;//消影
			
			LSC=1;LSB=0;LSA=0;
			P0 = gsmg_code[M/10];		
			delay_10us(5);
			P0 = 0x00;//消影	
	 
			LSC=0;LSB=1;LSA=1;
			P0 = gsmg_code[M%10];
			delay_10us(5);
			P0 = 0x00;//消影
			
			LSC=0;LSB=1;LSA=0;
			P0 = gsmg_code[16];
			delay_10us(5);
			P0 = 0x00;//消影
			
			LSC=0;LSB=0;LSA=1;
			P0 = gsmg_code[S/10];		
			delay_10us(5);
			P0 = 0x00;//消影	
	 
			LSC=0;LSB=0;LSA=0;
			P0 = gsmg_code[S%10];
			delay_10us(5);
			P0 = 0x00;//消影		
		}

		if(K1 == 0)//如果按键K1按下
		{
			while(!K1);//松手检测
		    TR1 = 0;
			mode++;
			if(mode >3)
				mode = 1;
		}
		if(K4 == 0)//如果按键K4按下
		{
			while(!K4);//松手检测
            TR1 = 1; 
			mode = 0;
		}		
		
		if(K2 == 0)//如果按键K2按下
		{
			while(!K2);//松手检测
			switch (mode)
			{
				case 1:
					H++;
				    if(H > 23)
			        {
					   H = 0;				
			        }
					break;
				case 2:
					M++;
				    if(M > 59)
			        {
					   M = 0;				
			        }					
					break;
				case 3:
					S++;
				    if(S > 59)
			        {
					   S = 0;				
			        }										
					break;
			}
		}
		if(K3 == 0)//如果按键K2按下
		{
			while(!K3);//松手检测
			switch (mode)
			{
				case 1:
					H--;
				    if(H < 0)
			        {
					   H = 23;				
			        }
					break;
				case 2:
					M--;
				    if(M < 0)
			        {
					   M = 59;				
			        }					
					break;
				case 3:
					S--;
				    if(S < 0)
			        {
					   S = 59;				
			        }										
					break;
			}
		}
	}
}
 
void Timer1_Rountine(void) interrupt 3  //1ms进一次中断
{
    TH1 = (65536-1000)/256;  //
    TL1 = (65536-1000)%256;  //重新赋初值才能保证下一次还是1ms
	  
    g_Count++;
    if(g_Count>=1000)  // 1S 计时
	{
		g_Count = 0;   //计数清零
		S++;
		if(++S1 == 5)
		{
			S1 = 0;
			Display_falg = 1;
		}
		if(Display_falg == 1)
		{
			if(++S2 == 2)
			{
				S2 = 0;
				Display_falg = 0;
			}
		}		
		if(S > 59)//1Min
		{
			S = 0;
			M++;
			if(M > 59)//1H
			{
				M = 0;
				H++;
			   if(H > 23)//1H
			   {
					H = 0;				
			   }
			}
		}	
	}
}
 
 
 

四、实验效果

五、仿真实现


总结


http://www.kler.cn/a/397043.html

相关文章:

  • 【redis】—— 环境搭建教程
  • react 中 useCallback Hook 作用
  • 【eNSP】企业网络架构实验——vlan间的路由通信(三)
  • 使用 npm 安装 Yarn
  • 系统架构设计师第二版口诀
  • 【大模型实战篇】vLLM的由来以及大模型部署、推理加速实践
  • JVM垃圾回收详解(重点)
  • LSTM(长短期记忆网络)详解
  • 【jvm】一个空Object对象的占多大空间
  • 第 16 章 - Go语言 通道(Channel)
  • 用魔方做存储器
  • Go语言中AES加密算法的实现与应用
  • 通过物流分拣系统来理解RabbitMQ的消息机制
  • 《网络硬件设备完全技术宝典》
  • AI风向标|算力与通信的完美融合,SRM6690解锁端侧AI的智能密码
  • 前端文件优化
  • Linux中虚拟内存详解
  • Java项目实战II基于微信小程序的个人行政复议在线预约系统微信小程序(开发文档+数据库+源码)
  • 报错 No available slot found for the embedding model
  • 中科蓝讯修改蓝牙名字:【图文讲解】
  • 童年的快乐,矫平机为玩具打造安全品质
  • Vue和Vue-Element-Admin(十四):vue3.x与vue2区别分析
  • Linux(CentOS)安装达梦数据库 dm8
  • 期末考核-机器学习-期末考核
  • 将 SQL 数据库连接到云:PostgreSQL、MySQL、SQLite 和云集成说明
  • C++ 多线程std::thread以及条件变量和互斥量的使用