51单片机实践之数码管电子时钟/时间呈现及其设置

以下源码在keil内可直接使用,注意板子的型号(AT89C52)即可。

代码如下:

/*
需求:两个独立按键分别控制加减(KEY2和KEY3),一个独立按键控制移位(KEY1),且在移动到该位置时该位置闪烁。
开发板:普中-A2
*/
#include 
#define leds P0
typedef unsigned int uint;
typedef unsigned char uchar;
//独立按键模块
sbit KEY1 = P3^1;
sbit KEY2 = P3^0;
sbit KEY3 = P3^2;
sbit KEY4 = P3^3;
//0-F再加一个 - .数码管显示数字的数组
uchar leds_body [] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
					0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};
uchar time[] = {6,3,16,0,4,16,1,2};//时间数组,每个数字和符号都占一个数码管
uchar h = 0,m = 0,s = 0;//时分秒初始化
uint count = 0;//计数量
uchar set_pos = -1;//控制显示位置的变化
void caculate()//计算时分秒,将其每一位放到相应位置
{
	time[0] = s%10;
	time[1] = s/10;
	time[3] = m%10;
	time[4] = m/10;
	time[6] = h%10;
	time[7] = h/10;
}
void delay(uint xms)		//@11.0592MHz,1ms  延迟:以1ms为单位
{
	unsigned char k, j;
	while(xms)
	{
		k = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--k);
		xms--;
	}
}
void dynamic_hms()//动态显示时分秒
{
	if(count==1000)//for循环决定这里得是8的倍数
	{
		count = 0;
		if(set_pos == -1)//只有位置不变化时,才进行时间流动
		{
			s++;
			if(s == 60)
			{
				s = 0;
				m++;
				if(m == 60)
				{
					m = 0;
					h++;
					if(h == 24)
					{
						h = 0;
					}
				}
			}
		}
	}
}
void showtime()//控制时间显示在数码管上
{
	uchar i = 0;
	caculate();
	for(i=0;i<8;i++)
		{
			P2 = i<<2;//控制数码管的显示位置
			if(count<500 && set_pos==i)
			{
				leds = 0;//使得该位置的数码管闪烁,半秒内的每一轮都会处理该位置,使得该位置半秒不显示。
			}
			else
			{
				leds = leds_body [time[i]];//没有选中的位置内容每一次循环都会显示,半秒后,位置全部正常显示。
			}
			delay(1);//显示1ms
			count++;//动态显示时分秒的关键,在1ms后每次加上1,等差不多到1000ms后即为1秒
		}
	leds = 0;//消影
}
void button_control()//控制移位
{
	if(KEY1 == 0)
	{
		delay(50);//使频率稳定
		while(KEY1 == 0);//判断是否松开
		delay(50);//使得频率稳定
		set_pos++;//数码管进入闪烁阶段
		if(set_pos == 2)
			set_pos++;
		else if(set_pos == 5)
			set_pos++;
		else if(set_pos == 8)
			set_pos = -1;
	}
	if(KEY2 == 0)//控制数字加
	{
		delay(50);
		while(KEY2 == 0);
		delay(50);
		if(set_pos==0)
		{
			s++;
			s = s % 60;
			caculate();
		}
		else if(set_pos==1)
		{
			s = s + 10;
			s = s % 60;
			caculate();
		}
		else if(set_pos==3)
		{
			m++;
			m = m % 60;
			caculate();
		}
		else if(set_pos==4)
		{
			m = m + 10;
			m = m % 60;
			caculate();
		}
		else if(set_pos==6)
		{
			h++;
			h = h % 24;
			caculate();
		}
		else if(set_pos==7)
		{
			h = h + 10;
			h = h % 24;
			caculate();
		}
	}
	if(KEY3 == 0)//控制数字减
	{
		delay(50);
		while(KEY3 == 0);
		delay(50);
		if(set_pos==0)
		{
			if(s>0)
			{
				s--;
			}
			else
			{
				s = 0;
			}
			s = s % 60;//使s在[0,59]这个区间内,后面类似
			caculate();
		}
		else if(set_pos==1)
		{
			if(s>10)
			{
				s = s - 10;
			}
			else
			{
				s = 0;
			}
			s = s % 60;
			caculate();
		}
		else if(set_pos==3)
		{
			if(m>0)
			{
				m--;
			}
			else
			{
				m = 0;
			}
			m = m % 60;
			caculate();
		}
		else if(set_pos==4)
		{
			if(m>10)
			{
				m = m - 10;
			}
			else
			{
				m = 0;
			}
			m = m % 60;
			caculate();
		}
		else if(set_pos==6)
		{
			if(h>0)
			{
				h--;
			}
			else
			{
				h = 0;
			}
			h = h % 24;
			caculate();
		}
		else if(set_pos==7)
		{
			if(h>10)
			{
				h = h - 10;
			}
			else
			{
				h = 0;
			}
			h = h % 24;
			caculate();
		}
	}
}
void main()
{
	while(1)
	{
		showtime();//展示时间
		dynamic_hms();//时间流动
		button_control();//按键控制
	}
}

posted on 2025-10-22 20:05  ljbguanli  阅读(0)  评论(0)    收藏  举报