ڼС
梦回起点
做你害怕做的事,你会发现:不过如此
本站基于WordPress—主题by 设计窝
冀ICP备15003737号
梦回起点
Copyright © 2015-2024 All rights reserved.

51单片机的电子表程序

下午闲的没事就拿出来放了两年的开发板,然后写了个小东西。童年梦想,电子表的程序。

程序实现了整点报时,每分钟LED闪烁一次,使用共阴数码管动态扫描实现时间日期的显示,通过两个按键可以调整时间。

实现的代码如下

#include <reg52.h>

/****************************************
*程序名称:时钟
*作者:独行
*时间:2017.2.23
*****************************************/



//定义数据端口
#define DataPort P0

//定义喇叭接口
sbit BEE = P2^0;

//定义LED端口
sbit LED = P2^7;

//定义按键
sbit KEY_CHANGE = P3^0;
sbit KEY_MOVE = P3^2;


//定义锁存使能端口
sbit SEGMENT_LATCH = P2^2;
sbit BIT_LATCH = P2^3;

//模式
/*
	模式0:正常显示时间
	模式1:正常显示日期
	模式2:调整时间
	模式3:调整日期
*/
unsigned char mode = 1, pos = 0;  

//定义段码
unsigned char code segment_table[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
//定义位码
unsigned char code bit_table[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};
//月份天数表
unsigned char code day_table[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//时间表
unsigned char time_table[8];
//日期表
unsigned char date_table[8];

//定义时间日期变量
unsigned char year, month, day, h, m, s; 

//初始化定时器
void Init_Timer(void)
{
	TMOD |= 0x01; //使用模式1
	//初始化TH和TL即设置时间
	TH0 = (0xffff-2000)/0xff;
	TL0 = (0xffff-2000)%0xff;
	EA = 1;		//总中断开关
	ET0 = 1;	//定时器中断开关
	TR0 = 1;	//定时器0开关
}

//延时函数
void Delay(unsigned char i)
{
	while (i--);	
}


//延时函数单位毫秒
void DelayMs(unsigned int i)
{
	while (i--){
		Delay(245);
		Delay(245);
	}
}


//*************************增加数值函数区************************************
void AddYear()
{
	unsigned char temp = 0;
	if(!(++year%200)){//调整年,超过200年那么回来
		year = 0;
	}//year
	//显示表重置
	temp = year + 17;
	date_table[1] = segment_table[temp/100];
	date_table[2] = segment_table[temp/10];
	date_table[3] = segment_table[temp%10];
}

void AddMonth()
{
	unsigned char temp = 0;
	if(!(++month%12)){//调整月,整年调整年
		month = 0;
		//如果不是暂停模式,那么继续增加年
		if(!(0x80 & mode))AddYear();
	}//month
	temp = month + 1;
	date_table[4] = segment_table[temp/10];
	date_table[5] = segment_table[temp%10];	
}

void AddDay()
{
	unsigned char temp = 0;
	//这里调整天数做了一个偷懒的工作,不去判断闰年的问题
	if(!(++day%day_table[month])){//调整天,整月调整月
		day = 0;
		if(!(0x80 & mode))AddMonth();
	}//day
	temp = day +1;
	date_table[6] = segment_table[temp/10];
	date_table[7] = segment_table[temp%10];
}

void Addh()
{
	if(!(++h)%24){//调整时,整天调整天
		h = 0;
		if(!(0x80 & mode))AddDay();
	}//h
	time_table[0] = segment_table[h/10];
	time_table[1] = segment_table[h%10];
}

void Addm()
{
	if(!(++m%60)){//调整分,整时调整时
		m = 0;
		if(!(0x80 & mode))Addh();
	}//m
	time_table[3] = segment_table[m/10];
	time_table[4] = segment_table[m%10];
	LED = 0;
	Delay(200);
	LED = 1;
}

void Adds()
{
	if(!(++s%60)){//调整秒,整分调整分
		s = 0;
		if(!(0x80 & mode))Addm();
	}//s
	time_table[6] = segment_table[s/10];
	time_table[7] = segment_table[s%10];
}

//*************************增加数值函数区结束************************************

int main()
{
	year = month = day = h = m = s = 0; 
	//初始化时间表
	time_table[0] = segment_table[0];
	time_table[1] = segment_table[0];
	time_table[2] = 0x40;
	time_table[3] = segment_table[0];
	time_table[4] = segment_table[0];
	time_table[5] = 0x40;
	time_table[6] = segment_table[0];
	time_table[7] = segment_table[0];
	//初始化日期表
	date_table[0] = segment_table[2];
	date_table[1] = segment_table[0];
	date_table[2] = segment_table[1];
	date_table[3] = segment_table[7];
	date_table[4] = segment_table[0];
	date_table[5] = segment_table[1];
	date_table[6] = segment_table[0];
	date_table[7] = segment_table[1];
	Init_Timer();
	//循环处理按键
	while (1){
		//整点报时功能
		if(s < 10 && m == 0 && (0x01 & mode)){
			BEE = ~BEE;
		}
		//按键判断
		if(0 == KEY_CHANGE){
		//如果改变的按键按下
			DelayMs(10);//去抖
			if(0 == KEY_CHANGE){
				while (0 == KEY_CHANGE);
				if(0x01 & mode){
					//如果是正常显示模式,那么调整为调整时间模式
					mode |= 0x04;
					mode &= 0x84;
					pos = 0x01;
				}else if(!(0x80 & mode)){
					mode |= 0x80;
				}else if(0x04 & mode){
					//调整当前位置的时间数值
					if(0x01 & pos){
						Addh();
						//时+1
					}else if(0x02 & pos){
						Addm();
						//分+1
					}else if(0x04 & pos){
						Adds();
						//秒+1
					}
				}else if(0x08 & mode){
					//调整当前位置的日期数值
					if(0x40 & pos){
						AddYear();
						//年+1
					}else if(0x20 & pos){
						AddMonth();
						//月+1
					}else if(0x10 & pos){
						AddDay();
						//天+1;
					}
				}
			}
		}

		if(0 == KEY_MOVE){
			//移动键按下
			DelayMs(10);//去抖
			if(0 == KEY_MOVE){
				while (0 == KEY_MOVE);//等待释放
				if(0x01 & mode){//正常显示模式
					mode = 0x02;	//日期显示模式
					DelayMs(300);//显示一会儿
					mode = 0x01;	//正常显示模式
				}else if(0x04 & mode){
					//调整时间模式
					pos <<= 1;
					if(0x08 & pos){
						mode |= 0x08;
						mode &= 0x88;
						pos <<= 1;
					}
				}else if(0x08 & mode){
					pos <<= 1;
					if(0x80 & pos){
						mode |= 0x01;
						mode &= 0x81;
						pos = 0;
					}
				}
			}
		}	
	}
	return 0;
}


//时间日期显示函数
void DisPlay()
{
	static unsigned int t = 0;
	static unsigned char i = 0;
	static char status = 0;
	if(!(++t%500)){//一秒钟
		t = 0;
		status = ~status;
		//如果是正常显示模式
		if(!(0x80&mode)){
			//那么调整时间
			Adds();
		}//t
	}
	DataPort = bit_table[i];
	BIT_LATCH = 1;
	BIT_LATCH = 0;
	DataPort = time_table[i];
	if(0x01 & mode){
		//正常显示时间模式
		DataPort = time_table[i];
	}else if(0x02 & mode){
		//正常显示日期模式
		DataPort = date_table[i];
	}else if(0x04 & mode){
		//调整时间模式
		if(0x04 & pos){//调整秒的模式
			//闪烁
			if((6 == i || 7 == i) && status){
				DataPort = 0;
			}else{
				DataPort = time_table[i];
			}
		}else if(0x02 & pos){//调整分的模式
			if((3 == i || 4 == i) && status){
				DataPort = 0;
			}else{
				DataPort = time_table[i];
			}
		}else if(0x01 & pos){//调整时的模式
			if((0 == i || 1 == i) && status){
				DataPort = 0;
			}else{
				DataPort = time_table[i];
			}	
		}
	}else if(0x08 & mode){
		//调整日期模式
		if(0x40 & pos){//调整年的模式
			//闪烁
			if((0 == i || 1 == i || 2 == i || 3 == i) && status){
				DataPort = 0;
			}else{//如果不是上述模式,那么正常显示
				DataPort = date_table[i];
			}
		}else if(0x20 & pos){//调整月的模式
			if((4 == i || 5 == i) && status){
				DataPort = 0;
			}else{//如果不是上述模式,那么正常显示
				DataPort = date_table[i];
			}
		}else if(0x10 & pos){//调整日的模式
			if((6 == i || 7 == i) && status){
				DataPort = 0;
			}else{//如果不是上述模式,那么正常显示
				DataPort = date_table[i];
			}	
		}
	}
	i = ++i%8;
	SEGMENT_LATCH = 1;
	SEGMENT_LATCH = 0;
}

//定时器中断函数
void Timer0_isr(void) interrupt 1
{
	//设置定时器的时间 2ms
	TH0 = (0xffff-2000)/0xff;
	TL0 = (0xffff-2000)%0xff;
	DisPlay();
}

下面是变量pos和mod变量   每个方块是一个位。

图

2017-02-23
                         
  1. 增达**2290

    真是时光荏苒!

发表回复