C51闹钟程序

C51闹钟程序

应朋友要求帮忙修改一下某宝上的程序,作为应付期末作业

作业要求

在这里插入图片描述

某宝原理图

在这里插入图片描述

修改后的原理图

在这里插入图片描述
这里我们删除了时钟模块和DS12B20温度模块,在作业中没有要求到,增加一个DI发光二极管作为秒表指示 。

程序

#include<reg52.h>
  
#define uint unsigned int
#define uchar unsigned char	  
#define u8 unsigned char
#define yh 0x80 //LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)
#define er 0x80+0x40 //LCD第二行初始位置(因为第二行第一个字符位置地址是0x40)

//液晶屏的与C51之间的引脚连接定义(显示数据线接C51的P0口)
sbit en=P2^7;
sbit rw=P2^6;   //如果硬件上rw接地,就不用写这句和后面的rw=0了
sbit rs=P2^5;


//校时按键与C51的引脚连接定义

sbit KEY1=P3^0;  	//KEY1
sbit KEY2=P3^1;  	//KEY2
sbit KEY3=P3^2;  	//KEY3
sbit KEY4=P3^3;		//KEY4

sbit DQ=P3^7;		//
sbit buzzer=P2^0;	//蜂鸣器,通过三极管8550驱动,端口低电平响

//sbit LCD_Back=P2^4; 		//LCD背光开关
sbit LED = P2^1;
uchar a;
uint Timer=0; 
uchar Timer_ss=0;  
uchar Timer_mm=0;
uchar Timer_hh=0; 
uchar A_Timer_mm=1;
uchar A_Timer_hh=0;	  
bit A_T_Flag=1;   //闹钟开关标志位
bit A_S_Flag=1;   //闹钟设置标志位
uchar Set_Timer=0;  //设置标志位 

uchar *tab2="Timer:00:00:00";
uchar *tab1="Alarm Clock!";	
	变量初始化以及硬件外设初始化
//定时器0初始化
void Timer0_Inir(void)	 
{
	TMOD |= 0x01;   //定时器0   模式1 	 
	TL0 = (65536-500)%256;
	TH0 = (65536-500)/256;  //进中断时间为500uS
	TCON |= 0x10;   //开启定时器0中断
	ET0 = 1;//定时器0  允许中断
	EA = 1;			//开启总中断
}
		定时器初始化函数
工作方式M1M0说明
方式000定时器/计数器T0工作在方式0时,16位计数器只用了13位,即TH0的高8位和TL0的低5位,组成一个13位定时器/计数器(最大计数值8192)。
方式101定时器T0工作方式1与工作方式0类同,差别在于其中的计数器的位数。工作方式0以13位计数器参与计数,工作方式1则以16位计数器参与计数(最大计数值65536)。
方式210自动重装THx存放初值(预置数) ,TLx用于计数,计数完毕则自动将THx的值赋给TLx。(除了重装初值和最大计数值以外,其他同方式0)
方式311这种式作方式之下,定时/计数器0被拆成2个独立的定时/计数器来用。其中,TL0可以构成8位的定时器或计数器的工作方式,而TH0则只能作为定时器来用。我们知道作定时、计数器来用,需要控制,计满后溢出需要有溢出标记,T0被分成两个来用,那就要两套控制及、溢出标记了,从何而来呢?TL0还是用原来的T0的标记,而TH0则借用T1的标记。
//延时函数,后面经常调用
void delay(uint xms)//延时函数,有参函数
{
	uint x,y;
	for(x=xms;x>0;x--)
	 for(y=110;y>0;y--);
}
	延时函数
void write_1602com(uchar com)//****液晶写入指令函数****
{
	rs=0;//数据/指令选择置为指令
	rw=0; //读写选择置为写
	P0=com;//送入数据
	delay(1);
	en=1;//拉高使能端,为制造有效的下降沿做准备
	delay(1);
	en=0;//en由高变低,产生下降沿,液晶执行命令
}
	LCD1602的指令写入函数,控制1602的工作模式,显示位置、光标等
void write_1602dat(uchar dat)//***液晶写入数据函数****
{
	rs=1;//数据/指令选择置为数据
	rw=0; //读写选择置为写
	P0=dat;//送入数据
	delay(1);
	en=1; //en置高电平,为制造下降沿做准备
	delay(1);
	en=0; //en由高变低,产生下降沿,液晶执行命令
}
	LCD1602的数据写入函数,控制1602显示的内容
void lcd_init()//***液晶初始化函数****
{
	write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据
	write_1602com(0x0c);//开显示不显示光标
	write_1602com(0x06);//整屏不移动,光标自动右移
	write_1602com(0x01);//清显示

	write_1602com(yh);//日历显示固定符号从第一行第1个位置之后开始显示
	for(a=0;a<12;a++)
	{
		write_1602dat(tab1[a]);//向液晶屏写名称显示的固定符号部分
	//delay(3);
	}
	write_1602com(er);//时间显示固定符号写入位置,从第2个位置后开始显示
	for(a=0;a<14;a++)
	{
		write_1602dat(tab2[a]);//写显示时间固定符号,两个冒号
	//delay(3);
	}

}
	已知1206自带ASCII编码,所以直接输入字符编码即可显示,无需取模
void Beep_d(void)
{
	buzzer=0;
	delay(100);	  
	buzzer=1;
}
	蜂鸣器短响函数
void LCD_TimeDispay(u8 hh,u8 mm,u8 ss)
{
	write_1602com(er+6);//时间显示固定符号写入位置,从第2个位置后开始显示	  
	write_1602dat((hh/10)+0x30);//显示时十位  
	write_1602dat((hh%10)+0x30);//显示时个位		  	   
	write_1602com(er+9);//时间显示固定符号写入位置,从第2个位置后开始显示
	write_1602dat((mm/10)+0x30);//显示时十位  
	write_1602dat((mm%10)+0x30);//显示时个位
	write_1602com(er+12);//时间显示固定符号写入位置,从第2个位置后开始显示	 
	write_1602dat((ss/10)+0x30);//显示时十位  
	write_1602dat((ss%10)+0x30);//显示时个位
}
	LCD时间显示刷新函数,CPU空余时间(按键未按下、蜂鸣器未响是)都在运行,保证时间的实时显示
void Alarm_Clock(void)
{	
  if(A_T_Flag)
  {					   
	write_1602com(yh+13);//闹钟开关显示	
	write_1602dat('A');				
	write_1602dat('O');	      
	write_1602dat('N');	 
	if(Timer_mm == A_Timer_mm)
	{
		if(Timer_hh == A_Timer_hh)
		{
			  Beep_d();
		}
	}	
  }
  else
  {
	write_1602com(yh+13);//闹钟开关显示	
	write_1602dat('A');	 		   
	write_1602dat('O');		   
	write_1602dat('F');	 	 
  }
} 
	闹钟功能开关判断函数
void Key_Scan(void)
{
	if(!KEY1)
	{			 
		Beep_d();	   //蜂鸣器短响,提示按键按下
		write_1602com(yh+13);//闹钟开关显示	
		write_1602dat('T');				
		write_1602dat('S');
		Set_Timer++;
		if(Set_Timer==1)
		{ 			
			write_1602dat('M');		//设置分
		} 
		else if(Set_Timer==2)
		{ 			
			write_1602dat('H');		//设置时
		}
		if(Set_Timer>2)
			Set_Timer = 0;
		while(!KEY1);		//等待按键松开
	}  
	else if(!KEY2)
	{				  
		Beep_d();	//蜂鸣器短响,提示按键按下
		if(Set_Timer==1)  //Set_Timer==1 表示设置时钟分
		{
			Timer_mm++;
			if(Timer_mm>=60)
			{
				Timer_mm=0;
			}
			LCD_TimeDispay(Timer_hh,Timer_mm,0);  //显示当前设置时间
		}
		else if(Set_Timer==2)  //Set_Timer==2 表示设置时钟时
		{
			Timer_hh++;
			if(Timer_hh>=24)
			{
				Timer_hh=0;
			}
			LCD_TimeDispay(Timer_hh,Timer_mm,0);  //显示当前设置时间
		}
		else if(Set_Timer==3)  //Set_Timer==3 表示设置闹钟分
		{
			A_Timer_mm++;
			if(A_Timer_mm>=24)
			{
				A_Timer_mm=0;
			}
			LCD_TimeDispay(A_Timer_hh,A_Timer_mm,0);  //显示当前设置闹钟时间	
		}	
		else if(Set_Timer==6)  //Set_Timer==6 表示设置闹钟时
		{
			A_Timer_hh++;
			if(A_Timer_hh>=24)
			{
				A_Timer_hh=0;
			}
			LCD_TimeDispay(A_Timer_hh,A_Timer_mm,0);  //显示当前设置闹钟时间	
		}
		else
		{		  
			write_1602com(yh+13);		
			write_1602dat('A');					
			write_1602dat('C');	  			
			write_1602dat('D');
			LCD_TimeDispay(A_Timer_hh,A_Timer_mm,0);		//显示当前设置闹钟时间	
			delay(2000);	  
		}	 
		while(!KEY2);	//等待按键松开
	}  
	else if(!KEY3)
	{			 	  
		Beep_d();
		write_1602com(yh+13);//闹钟设置显示	
		write_1602dat('A');				
		write_1602dat('S');	
		Set_Timer += 3;	 
		if(Set_Timer==3)
		{ 			
			write_1602dat('M');		//闹钟设置分
		} 
		else if(Set_Timer==6)
		{ 			
			write_1602dat('H');		//闹钟设置时
		}
		if(Set_Timer>6)
			  Set_Timer = 0;   		//标志位清零,正常显示
		LCD_TimeDispay(A_Timer_hh,A_Timer_mm,0);	//显示当前设置闹钟时间
		while(!KEY3);
	}  
	else if(!KEY4)
	{		 
		A_T_Flag = !A_T_Flag;	 //闹钟功能标志位取反
		if(A_T_Flag) 	//A_T_Flag == 1 闹钟功能开
		{
			Beep_d();  
			delay(500);
			Beep_d();  
			delay(500);	 
			Beep_d();  
		}
		else    		//A_T_Flag == 0 闹钟功能关
		{	   
		 	Beep_d();  
		}
		while(!KEY4);	//等待按键松开
	}
}
	按键扫描函数
void main(void)
{
	lcd_init();	  //初始化LCD1206
	Beep_d();		//开机提示音
	Timer0_Inir();  //初始化定时器0
	while(1)
	{
		if(Set_Timer==0)   //判断标志位,为零为正常显示
		{
		  LCD_TimeDispay(Timer_hh,Timer_mm,Timer_ss);
		  Alarm_Clock();
		}	
		Key_Scan();
	}	

}

	主函数
void Timer0_Hard(void) interrupt 1//定时器0 中断函数
{	  
	Timer++;
	if(Timer==1000)		  //	500us*1000=500ms,500ms进一次if
	{
		LED = !LED;		//LED取反
		write_1602com(er+11);//秒:写入位置,从第11个位置后开始显示     
		write_1602dat(' ');//清除秒:显示	  
	}
	else if(Timer>=2000)	  //	500us*2000=1s,1s进一次if
	{	   
		Timer = 0;		//计数值清零
		Timer_ss++;	 	//时钟秒自增
		LED = !LED;		//LED取反
		write_1602com(er+11);//秒:写入位置,从第11个位置后开始显示	  
		write_1602dat(':');//显示秒:	       
	}				    
	if(Timer_ss>=60)
	{
	 	 Timer_ss = 0;		//60秒到,秒清零,分加1
		 Timer_mm++;
	}	
	else if(Timer_mm>=60)
	{				   
	 	 Timer_mm = 0;		//60分到,分清零,时加1
		 Timer_hh++;
	}  	
	else if(Timer_hh>=24)
	 	 Timer_hh = 0;		//24时到,时清零
	TL0 = (65536-500)%256;		//定时器0计数器值重装
	TH0 = (65536-500)/256;
}

下载程序验证

在这里插入图片描述
显示正常,功能OK

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值