本文为博主 LED-执棋困局,csdn原创首发。希望看完后能对你有所帮助,不足之处请指正!一起交流学习,共同进步!
> 发布人:LED-执棋困局
> 欢迎你为独创博主LED-执棋困局点赞❤❤❤+关注👍+收藏🌹+评论☺。系列专栏:CSDN-单片机学习系列🎁
> 我的格言是:“尽最大努力,做最好的自己!💪
版权声明:本文为CSDN博主「LCD-执棋困局」的原创文章,CSDN独一份。如需转载,还请通知一声噢⚠!
————————————————
版权声明:本文为CSDN博主「LCD-执棋困局」的原创文章,转载请附上原文出处链接及本声明。
一、项目要求及全景
1.1项目要求
电子时钟:
1.能正常显示时分秒
2.可以调节时分秒三个参数,第一个按键可以控制要调节哪个参数,第二个按键将要调节的参数+1。
1.2项目全景
基于51单片机的电子时钟具有如下的全景:
-
安装方便:由于单片机体积小、可编程性强,因此制作出的电子时钟体积小巧,易于安装搭配。
-
显示效果好:采用LED数码管进行显示,可清晰地显示时间、日期等信息,还可以实现多种显示效果,例如闪烁、滚动等。
-
功能丰富:电子时钟可具备多种功能,例如自动校正、闹钟、倒计时、温度显示等。
-
低功耗:单片机功耗低,电子时钟可以采用电池供电,无需频繁更换电池。
-
系统稳定:单片机具有强大的自动校正能力,可保证电子时钟的时间准确度和系统的稳定性。
-
系统可靠性高:由于单片机系统的稳定性和可靠性比较高,因此电子时钟的故障率较低,使用寿命长。
-
制作过程简单:基于51单片机制作电子时钟的过程相对简单,不需要太多专业的电子知识,适合初学者入门学习。
二、系统原理
2.1定时原理
用到两个定时器,定时器T0定时1ms,用于延时,从而显示数码管(数码管要显示,需要4步,消隐-位码-线码-延时1ms),而定时器T1定时50ms,用于时分秒正常显示,20次50ms=1s,1s*60次=1min,1min*60次=1hour
2.2数码管显示原理
因为不同窗口wnd,数码管屏幕不同,需要分别写正常显示函数、调节时函数、调节分函数、调节秒函数,并写一个服务函数key_service(),根据wnd值,采用switch-case语句,将这四个函数分别显示到数码管屏幕上。
2.3切屏原理
定义窗口变量wnd,用于调节不同窗口。
外部中断0,每按一次第一个按键,wnd加1,wnd>3时,wnd=0。
2.4调参数原理
外部中断1,秒变量min范围为0-60,min范围为0-60,hour范围为0-24,根据不同的wnd,调节不同的参数,每按一下按键,要调节的参数+1。
三、仿真图
四、项目代码
4.1代码思路
定义窗口变量wnd、时参数变量hour、分参数变量min、秒参数变量sec。正常显示:用定时器T0定时1ms显示数码管,定时器T1定时50ms,累加20次,sec加1,再次基础上,sec累加60次,min加1,min累加60,hour加1。利用外部中断0,调节窗口wnd,利用外部中断1,根据不同wnd值,采用switch-case语句,用于调节参数,wnd=1时,hour++,wnd=2时,min++,wnd=3时,写sec++。不同窗口对于不同的显示屏幕,可以分别写正常显示函数、调节时函数、调节分函数、调节秒函数。
4.2主模块与子模块
4.2.1时分秒显示模块
窗口0,正常显示时分秒。
void Timer1_Init(void) //50毫秒@12.000MHz
{
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10; //设置定时器模式
TL1 = 0xB0; //设置定时初始值
TH1 = 0x3C; //设置定时初始值
TF1 = 0; //清除TF1标志
ET1=1;
//TR1 = 1; //定时器1开始计时
}
void T1_timer() interrupt 3 //正常显示时分秒
{
TR1=0;
i++;
if(i>=20)
{
i=0;
sec++;
if(sec>=60)
{
sec=0;
min++;
if(min>=60)
{
min=0;
hour++;
if(hour>=24)
{
hour=0;
}
}
}
}
TL1 = 0xB0; //设置定时初始值
TH1 = 0x3C; //设置定时初始值
TR1=1;
}
4.2.2数码管显示模块
数码管要显示,display()要利用定时器定时延时1ms。
void Timer0_Init(void) //1毫秒@12.000MHz 定时器0
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
ET0=1;
TR0 = 1; //定时器0开始计时
}
void T0_timer() interrupt 1 //实现数码管动态刷新
{
TR0=0;
display();
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TR0=1;
}
display.c
#include "display.h"
unsigned char code leddata[]={
0x3F, //0
0x06, //1
0x5B, //2
0x4F, //3
0x66, //4
0x6D, //5
0x7D, //6
0x07, //7
0x7F, //8
0x6F, //9
0x77, //A
0x7C, //B
0x39, //C
0x5E, //D
0x79, //E
0x71, //F
0x76, //H
0x38, //L
0x37, //n
0x3E, //u
0x73, //P
0x5C, //o
0x40, //-
0x00 //熄灭
};//数码管段码表
unsigned char LEDBuf[]={0,0,0,0,0,0};//缓冲区
unsigned char code PLACE_COOE[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};//位码
/******************************************************************************************
函数名:display
功能:数码管显示函数
参数:无
返回值:无
******************************************************************************************/
void display()
{
static unsigned char i=0;
switch(i)
{
case 0:
IO_DIG=0x00;//消隐
IO_DIG=leddata[LEDBuf[0]];//段码
IO_PLACE=PLACE_COOE[0];//位码
i++;
break;
case 1:
IO_DIG=0x00;//消隐
IO_DIG=leddata[LEDBuf[1]];//段码
IO_PLACE=PLACE_COOE[1];//位码
i++;
break;
case 2:
IO_DIG=0x00;//消隐
IO_DIG=leddata[LEDBuf[2]];//段码
IO_PLACE=PLACE_COOE[2];//位码
i++;
break;
case 3:
IO_DIG=0x00;//消隐
IO_DIG=leddata[LEDBuf[3]];//段码
IO_PLACE=PLACE_COOE[3];//位码
i++;
break;
case 4:
IO_DIG=0x00;//消隐
IO_DIG=leddata[LEDBuf[4]];//段码
IO_PLACE=PLACE_COOE[4];//位码
i++;
break;
case 5:
IO_DIG=0x00;//消隐
IO_DIG=leddata[LEDBuf[5]];//段码
IO_PLACE=PLACE_COOE[5];//位码
i=0;
break;
}
}
display.h
#ifndef __DISPLAY_H__
#define __DISPLAY_H__
#include <reg51.h>
#define IO_DIG P0 //段码IO
#define IO_PLACE P2 //位码IO
#define N 6 //数码管个数
unsigned char code leddata[];//变量声明
extern unsigned char LEDBuf[];
void display();//数码管显示函数声明
#endif
4.2.3按键模块
外部中断0:用于调节窗口变量wnd
void EX0_init()
{
IT0=1;
EX0=1;
}
void EX0_timer() interrupt 0 //按键key1控制窗口
{
wnd++;
if(wnd==4)
wnd=0;
}
外部中断1:调节时分秒
void EX1_init()
{
IT1=1;
EX1=1;
}
void EX1_timer() interrupt 2 //调节时分秒
{
switch(wnd)
{
case 0:;break;
case 1:TR1=0;hour++;if(hour>=24) hour=0;break;
case 2:TR1=0;min++;if(min>=60) min=0;break;
case 3:TR1=0;sec++;if(sec>=60) sec=0;break;
}
}
调节参数在数码管的显示:
void key_service()//不同窗口的数码管显示
{
switch(wnd)
{
case 0:TR1=1;dis_service();break;
case 1:dishour();break;
case 2:dismin();break;
case 3:dissec();break;
}
}
void dishour()//调节时的窗口显示
{
LEDBuf[0]=hour/10;
LEDBuf[1]=hour%10;
LEDBuf[2]=23;
LEDBuf[3]=23;
LEDBuf[4]=23;
LEDBuf[5]=23;
}
void dismin()//调节分的窗口显示
{
LEDBuf[0]=23;
LEDBuf[1]=23;
LEDBuf[2]=min/10;
LEDBuf[3]=min%10;
LEDBuf[4]=23;
LEDBuf[5]=23;
}
void dissec()//调节秒的窗口显示
{
LEDBuf[0]=23;
LEDBuf[1]=23;
LEDBuf[2]=23;
LEDBuf[3]=23;
LEDBuf[4]=sec/10;
LEDBuf[5]=sec%10;
}
void dis_service()//正常显示的窗口显示
{
LEDBuf[0]=hour/10;
LEDBuf[1]=hour%10;
LEDBuf[2]=min/10;
LEDBuf[3]=min%10;
LEDBuf[4]=sec/10;
LEDBuf[5]=sec%10;
}
4.2.4主模块
#include <reg51.h>
#include "display.h"
#include "key.h"
void Timer0_Init();
void Timer1_Init();
void key_service();
void EX0_init();
void EX1_init();
void dis_service();
void dishour();
void dismin();
void dissec();
unsigned char sec=0;
unsigned char min=0;
unsigned char hour=0;
unsigned char wnd=0;
unsigned char i=0;
void main()
{
Timer0_Init();
Timer1_Init();
EX0_init();
EX1_init();
EA=1;
while(1)
{
key_service();
}
}
五、结果及扩展
5.1结果
窗口0(正常显示时分秒)
窗口1(调节时):
窗口2(调节分):
窗口3(调节秒):
调节时分秒:
5.2功能扩展
本次电子时钟,参数主要是时、分、秒。
电子时钟的功能可以扩展:
1.功能可以进行扩展,参数可以有年、月、日、时、分、秒。
调节年参数时,要考虑闰年和平年;调节月参数时,要考虑2月份的天数。
2.闹钟,到一定时间时,让蜂鸣器发出声响。
———————————————————————————————————————————
本次介绍了电子时钟,同时提供模块代码和仿真图,帮助大家理解相关编码思路。
hi!我是博主LED-执棋困局🔥,喜欢或期待更好作品的,可以关注一下我LED-执棋困局🙏🙏🙏,我们一起进步,另外欢迎大家的点评😊!!!
关注博主:点击支持——LED-执棋困局
———————————————————————————————————————————