基于AT89C51的电子时钟系统

课设作业

代码写得不好,只是记录一下

基于AT89C51的电子时钟系统,通过配置定时器实现电子时钟,秒表计时,记录年月日等。

可以通过按键调整时间,年月日

State——修改对象 

m:秒        f:分        s:时        t:天        y:月        n:年        j:计时模式

Clock——时间

CountT——秒表计时

以仿真界面看,除RST按键外,从上到下,分别为按键1,按键2,按键3

按键1:增加

按键2:减少

按键3:切换修改对象

电路仿真:

        

相关代码:

 主函数

#include "REGX52.H"
#include "LCDLM041L.h"
#include "key.h"
#include "Delay.h"
#include "sounder.h"


sbit sounder=P2^0;
unsigned char KeyNum;



//-----------------
//中断初始化

//-----------------


void Timer0_Init(){
	//TMOD=TMOD&0XF0;//高四位保持不变,第四位清零
	//TMOD=TMOD|0X01;//设置定时器模式  M1=0 M0=1
	//TF0=0;//标志位
	//TR0=1;//是定时器T0的定时器启动位
	//TL0=0X18;//TX0的高8位 除以256相当于256进制 对65535-1000求商	 	 1000us = 1ms
	//TH0=0XFC;//TX0的低8位 对65535-1000取余
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0xF0;		//设置定时初值
	TH0 = 0xD8;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	//中断部分设置
	ET0=1;
	EA=1;
	PT0=0;

}




//修改时间
unsigned char State = 'm';//修改项  初始化为秒  m - 秒  f - 分 s - 时 t - 天 y - 月 n - 年 j - 计时功能



unsigned char Year=22,Mon=2,Day=6;
unsigned char Sec=30,Min=2,Hour=12;
unsigned char CouSec=0,CouMin=0,CouMs=0;
//时间判断函数
void Judge(){
	if(Sec>=60){
		Sec=0;
		Min++; 
		}
	if(Min>=60){
		Min=0;
		Hour++;
		}
	if(Hour>=24){
		Hour=0;
		Day++;
		}
	if(((Mon==1||Mon==3||Mon==5||Mon==7||Mon==8||Mon==10||Mon==12)&&Day>31)||(Mon==4||Mon==6||Mon==9||Mon==11)&&Day>30){
		Day=1;
		Mon++;
		}
	if(Mon>12){
		Mon=1;
		Year++;
		}
	}
//平润年判断
void JudgeYear(){

		//闰年
		if(Year%4==0&&Mon==2){
				if(Day>29){
					Day=0;
					Mon++;
					}
			
		}

		//平年
		else if(Year%4!=0&&Mon==2){
				if(Day>28){
					Day=1;
					Mon++;	
					}
		}	
			
}

void Motify(){
	if(Day==0)Day=1;
}

unsigned char CountFlag=0;//计时器标志符  1是启动 2是暂停
unsigned char FlagHour=0;
void JudgeHour(){
	if(Min==0&&Sec==0)
	  	Sounder();
}

void main(){
	Timer0_Init();
	LCD_Init();	
	LCD_Init();
	LCD_ShowString(1,1,"Clock:");
	LCD_ShowString(2,1,"CountT:");
	LCD_ShowString(3,1,"State:");
	LCD_ShowChar(1,10,':');
	LCD_ShowChar(1,13,':');
	LCD_ShowChar(2,10,':');
	LCD_ShowChar(2,13,':');
	LCD_ShowChar(4,6,'-');
	LCD_ShowChar(4,9,'-');
	sounder =~sounder;	
 	while(1){
		LCD_ShowNum(4,4,Year,2);
		LCD_ShowNum(4,7,Mon,2);
		LCD_ShowNum(4,10,Day,2);
		LCD_ShowNum(1,14,Sec,2);
		LCD_ShowNum(1,11,Min,2);	
		LCD_ShowNum(1,8,Hour,2);
		LCD_ShowNum(2,14,CouMs,2);
		LCD_ShowNum(2,11,CouSec,2);	
		LCD_ShowNum(2,8,CouMin,2);
		LCD_ShowChar(3,7,State);
		JudgeHour();
		JudgeYear();
		Motify();
		Judge();
		KeyNum=Key();
		if(KeyNum==3){
			if(State=='m')
				State='f';
			else if(State=='f')
				State='s';
			else if(State=='s')
				State='t';
			else if(State=='t')
				State='y';
			else if(State=='y')
				State='n';
			else if(State=='n')
				State='j';
			else if(State=='j')
				State='m';					
		}
		if(KeyNum==1){
			if(State=='m')
				Sec++;
			else if(State=='f')
				Min++;
			else if(State=='s')
				Hour++;
			else if(State=='t')
				Day++;
			else if(State=='y')
				Mon++;
			else if(State=='n')
				Year++;	
			else if(State=='j')
				CountFlag=~CountFlag;
									
		}
		if(KeyNum==2){
			if(State=='m'&&Sec!=0){
				Sec--;
			}
			else if(State=='m'&&Sec==0){
				Sec=59;
			}	
			else if(State=='f'&&Min!=0){
				Min--;
				}
			else if(State=='f'&&Min==0){
				Min=59;
				} 
			else if(State=='s'&&Hour!=1){
				Hour--;
				}
			else if(State=='s'&&Hour==1){
				Hour=12;
			}
			else if(State=='t'){
				Day--;
				if(Day<1&&Mon!=2&&(Mon==1||Mon==3||Mon==5||Mon==7||Mon==8||Mon==10||Mon==12))Day=31;
				else if(Day<1&&Mon!=2&&(Mon==4||Mon==6||Mon==9||Mon==11))Day=30;
				else if(Day<1&&Mon==2&&Year%4==0)Day=29;
				else if(Day<1&&Mon==2&&Year%4!=0)Day=28;
				}
			else if(State=='y')
				Mon--;
			else if(State=='n')
				Year--;	
			else if(State=='j'){
				CouMin=0;
				CouSec=0;
				CouMs=0;
				}				
		}
		
		//sounder=~sounder;
		//DelayXms(5);
		//Sounder();
						
	}
}

unsigned int T0Count;
void Timer0_Routine() interrupt 1{						//若是500ms   则可以用50ms*10  产生10次50ms的计时						
	TL0 = 0xF0;		//设置定时初值
	TH0 = 0xD8;		//设置定时初值				z		  55536  =0xD8F0
	T0Count++;											
	if(CountFlag!=0){										
		CouMs++;
		if(CouMs>=100){
			CouSec++;
			CouMs=0;
			if(CouSec>=60){
			CouMin++;
			CouSec=0;
			}
		}
	}
	if(T0Count>=100){	 //100 * 10ms = 1s	   如果发现比实际时间慢   可以特意调低累计次数T0Count
		T0Count=0;
		Sec++;
								
	}	
}




定时器计算部分在作业验收时已经修改,跟代码不相符,具体计算方法可以查找其他博主的文章。

LM041L显示部分

#include "REGX52.H"
#include "LCDLM041L.h"


sbit LCD_RS=P3^5	;
sbit LCD_RW=P3^6	;
sbit LCD_E=P3^7		;

#define LCD_DataPort P0
//-----------------
//写延迟函数
//-----------------
void LCD_Delay(){ //12MHz 1ms
	unsigned char i,j;
	i = 2;
	j = 239;
	do
	{
		while (--j);
	}while(--i);
}


//-----------------
//写命令
//-----------------
void LCD_WriteCommand(unsigned char Command){


	LCD_RS = 0;
	LCD_RW = 0;
	LCD_DataPort = Command;
				//因为传输时序    需要延时一段时间
	LCD_E = 1;
	LCD_Delay();
	LCD_E = 0;
	LCD_Delay();


}
//-----------------
//写数据?
//-----------------
void LCD_WriteData(unsigned char Data){

	LCD_RS = 1;
	LCD_RW = 0;
	LCD_DataPort = Data;

				//因为传输时序    需要延时一段时间
	LCD_E = 1;
	LCD_Delay();
	LCD_E = 0;
	LCD_Delay();


}

//-----------------
//LCD初始化
//-----------------

void LCD_Init(void){

	LCD_WriteCommand(0x38);	  //00111000
	LCD_WriteCommand(0x0c);
	LCD_WriteCommand(0x06);
	LCD_WriteCommand(0x01);
	LCD_WriteCommand(0x38);
	LCD_Delay();

}

//-----------------
//光标位置
//-----------------
void LCD_SetCursor(unsigned char Line ,unsigned char Column){
	if     (Line == 1){
		LCD_WriteCommand(0x80|(Column-1));//第一行
		}
	else if(Line == 2){
		LCD_WriteCommand(0x80|((Column-1)+0xc0));//第二行
		}
	else if(Line == 3){
		LCD_WriteCommand(0x80|((Column-1)+0x90));//第三行
		}
	else{
		LCD_WriteCommand(0x80|((Column-1)+0xd0));//第四行
		}
}

//-----------
//显示字符
//-----------
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char){
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

//-----------
//显示字符串
//-----------
void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String){
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++){
		LCD_WriteData(String[i]);
	}
}

//----------
//次方计算函数
//----------
int LCD_Pow(int x, int y){
	unsigned char i;
	int Result = 1;
	for(i=0;i<y;i++){
		Result *= x;
	}
	return Result;
}

//-----------
//显示数字
//-----------
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length){
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for (i=Length;i>0;i--){
		LCD_WriteData('0'+Number/LCD_Pow(10,i-1)%10);
	}
}

按键部分:

#include "REGX52.H"
#include "KEY.H"
#include "Delay.h"

unsigned char Key(){
	unsigned char KeyNumber = 0;
	if (P1_0==0){
		Delay20us();
		while(P1_0==0);
		Delay20us();
		KeyNumber = 1;
	}
	if (P1_1==0){
		Delay20us();
		while(P1_1==0);
		Delay20us();
		KeyNumber = 2;
	}
	if (P1_2==0){
		Delay20us();
		while(P1_2==0);
		Delay20us();
		KeyNumber = 3;
	}

	return KeyNumber;

}

如有建议或错误,欢迎各位大佬指正。

  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值