时钟及规定时间闹钟

本文介绍了一种用四个按键操作的时钟设计,包括选择、加减和确认功能。通过定时器中断控制数码管闪烁,特别关注了八位数码管小数点的点亮和秒闪。同时,详细展示了如何设置闹钟,当指定时间到达时蜂鸣器会报警。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

时钟及规定时间闹钟

题目要求:用按键设定时钟的时、分、秒。要求用4键方式,即选择、加、减、确认键,选择键用于选择修改起始时、分、秒值,每按一次,被修改数码管顺序移动并闪烁。用+,- 键修改数值,确认键确定修改结束。用扫描方式动态显示时、分、秒,第2,4 数码管加小数点,并且要求第4数码管小数点每秒闪烁一次。可以设置闹钟,到时间蜂鸣器报警

难点及技巧:

1、通过在定时器中断来设置标志位来控制数码管的闪烁
2、八位数码管小数点的点亮,0x80,通过或与句(|0x80)
3、数码管的闪烁,通过if语句,对标志位进行求余(闪烁,对2求余即可)

话不多说,直接看代码

代码讲解:

源代码:

#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
#include<intrins.h> 

typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;

sbit LSA=P2^2;			  //38译码器
sbit LSB=P2^3;
sbit LSC=P2^4;

sbit buzz=P2^5;	 //蜂鸣器

sbit k1=P3^1;  //选择键
sbit k2=P3^0;  //加一				
sbit k3=P3^2;  //减一 
sbit k4=P3^3;  //确认健

//数码表
u8 code lzl[17]={    0x3f,0x06,0x5b,
	                 0x4f,0x66,0x6d,
	                 0x7d,0x07,0x7f,
                     0x6f,0x77,0x7c,
                     0x39,0x5e,0x79, 
                     0x71};

u8 ssec,sec,min,hour; //毫秒,秒,分,时
u8 model,sign;    //标志位
u8 wei[8];

u8 uhour=0,umin=0,usec=5;	   //闹钟时间设定

void delay(u16 i);	  //延时函数
void Timer0Init();	  //中断函数初始化
void display();	      //动态显示
void show();	      //显示数码管
void key_scan();      //按键功能    k1:选择健   k2:加一   k3:减一   k4:确认健
void start();         //函数总和

										 
void delay(u16 i)	 //延时函数
{
	while(i--);	
}


void Timer0Init()
{
	TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
	TH0=0Xd8;	//给定时器赋初值,定时10ms
	TL0=0Xf0;	
	ET0=1;//打开定时器0中断允许               //注:稍后用K2控制总中断,实现暂停功能
	EA=1;//打开总中断	
	TR0=1;//打开定时器				 防止未按就计时
}




//动态显示函数
void display()
   {
   u8 i;
   for(i=0;i<8;i++)
   {
   	switch(i)	 //位选,选择点亮的数码管,
   	{
   		case(0):
   			LSA=1;LSB=1;LSC=1; break;
   		case(1):
   			LSA=0;LSB=1;LSC=1; break;
   		case(2):
   			LSA=1;LSB=0;LSC=1; break;
   		case(3):
   			LSA=0;LSB=0;LSC=1; break;
   		case(4):
   			LSA=1;LSB=1;LSC=0; break; 
   		case(5):
   			LSA=0;LSB=1;LSC=0; break;
   		case(6):
   			LSA=1;LSB=0;LSC=0; break;
   		case(7):
   			LSA=0;LSB=0;LSC=0; break;	
   	}
   	P0=wei[i];			//发送段码
   	delay(100); 		//间隔一段时间扫描	
   	P0=0x00;
   }
 }


//记录数码管显示

void show()		
   {
	 wei[2]=0;
	 wei[5]=0;
   switch(model)
   {
   	case 0:
   	{
   		wei[0]=lzl[hour/10];		
   		if(sign%2==0)						
   			wei[1]=lzl[hour%10]|0x80;
   		else
   			wei[1]=lzl[hour%10];

   			wei[3]=lzl[min/10];
   			wei[4]=lzl[min%10]|0x80;
   			wei[6]=lzl[sec/10];
   			wei[7]=lzl[sec%10];
   		break;
   	}
   	case 1:
   	{
   		if(sign%2==0)
   		{								
   			wei[0]=lzl[hour/10];		
   			if(sign%2==0)
   				wei[1]=lzl[hour%10]|0x80;
   			else
   				wei[1]=lzl[hour%10];

   			wei[3]=lzl[min/10];
   			wei[4]=lzl[min%10]|0x80;
   			wei[6]=0x00;
   			wei[7]=0x00;
   		}
   		else
   		{							 
   			wei[0]=lzl[hour/10];		
   			if(sign%2==0)
   				wei[1]=lzl[hour%10]|0x80;
   			else
   				wei[1]=lzl[hour%10];

   			wei[3]=lzl[min/10];
   			wei[4]=lzl[min%10]|0x80;
   			wei[6]=lzl[sec/10];
   			wei[7]=lzl[sec%10];
   		}
   		break;
   	}
   	case 2:					  
   	{
   		if(sign%2==0)
   		{
   			wei[0]=lzl[hour/10];						
   			if(sign%2==0)
   				wei[1]=lzl[hour%10]|0x80;
   			else
   				wei[1]=lzl[hour%10];

   			wei[3]=0x00;
   			wei[4]=0x00|0x80;
   			wei[6]=lzl[sec/10];
   			wei[7]=lzl[sec%10];
   		}
   		else
   		{
   			wei[0]=lzl[hour/10];		
   			if(sign%2==0)
   				wei[1]=lzl[hour%10]|0x80;
   			else
   				wei[1]=lzl[hour%10];

   			wei[3]=lzl[min/10];
   			wei[4]=lzl[min%10]|0x80;
   			wei[6]=lzl[sec/10];
   			wei[7]=lzl[sec%10];
   		}
   	}
   		break;
   	case 3:
   	{
   		if(sign%2==0)										   
   		{
   			wei[0]=0x00;		
   			if(sign%2==0)
   				wei[1]=0x00|0x80;
   			else
   				wei[1]=0x00;

   			wei[3]=lzl[min/10];
   			wei[4]=lzl[min%10]|0x80;
   			wei[6]=lzl[sec/10];
   			wei[7]=lzl[sec%10];
   		}
   		else
   		{
   			wei[0]=lzl[hour/10];		
   			if(sign%2==0)
   				wei[1]=lzl[hour%10]|0x80;
   			else
   				wei[1]=lzl[hour%10];

   			wei[3]=lzl[min/10];
   			wei[4]=lzl[min%10]|0x80;
   			wei[6]=lzl[sec/10];
   			wei[7]=lzl[sec%10];
   		}
   		break;
   	}
   }
   }

//按键扫描及处理

  void key_scan()
  {
  if(k1==0)
  {
  	delay(1000);
  	if(k1==0)
  	{
  	model++;
  	while(!k1);
  	if(model==4)
  		model=0;
  	}
  }

  if(k2==0)
  {
  	delay(1000);
  	if(k2==0)
  	{
  		if(model==1)		//修改秒
  		{
  			sec++;	if(sec>=60)sec=0;
  		}
  		else if(model==2)	//修改分钟
  		{
  			min++;	if(min>=60)min=0;
  		}
  		else if(model==3)	//修改小时
  		{
  			hour++;	if(hour>=24)hour=0;
  		}
  		while(!k2);
  	}
  }

  if(k3==0)
  {
  	delay(1000);
  	if(k3==0)
  	{
  		if(model==1)		//修改秒
  		{
  			sec--;	if(sec==255)sec=59;
  		}
  		else if(model==2)	//修改分钟
  		{
  			min--;	if(min==255)min=59;
  		}
  		else if(model==3)	//修改小时
  		{
  			hour--;	if(hour==255)hour=23;
  		}
  		while(!k3);
  	}
  }
  if(k4==0)				  //恢复初态
  {
  	delay(1000);
  	if(k4==0)
  		model=0;
  	while(!k4);
  }

  if(min==umin)				//闹钟,自己定义时间
  {
  	if(hour==uhour)
	{
		if(sec==usec)
		{
		   buzz=~buzz;
    	}
	}
  }

}

void start()
{
      display();
      show();
	  key_scan();	
}


//主函数
void main()
{
	Timer0Init(); //设置外部中断	
	while(1)
	{
  	start();
     }

}



void Timer0() interrupt 1
{
	TH0=0Xd8;	//给定时器赋初值,定时10ms
	TL0=0Xf0;
	ssec++;
					
	 if(ssec>=100)  //1s
	{
		ssec=0;
		sec++;
		sign++;
		if(sec>=60)
		{

			sec=0;
			min++;
			if(min>=60)
			{	  
				min=0;
				hour++;
				if(hour>=24)
				{
					hour=0;
				}
			}
		}	
	}
			
}

	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AT89C52时钟程序 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;*********************************************************************************************; ;以下程序能用于24,能作为表使用,能定闹铃1钟(也可关). ;使用方法:开机后在00:00:00起开始计,(1)长按P1.0进入调状态:单元闪烁 ;按P1.01,按P1.11.再长按P1.0进入调整状态,单元闪烁,调整同调. ;按长按退出调整状态. (2)按下P1.1进入表状态:按P1.2暂停,再按P1.2表清零,再按 ;P1.2表又启动,按P1.1退出表回到时钟状态. (3)按P1.3进入设定状态: 00:00: -,可进 ;行设定,按P1.21,再按P1.3为调整,00:00:- ,按P1.21,按P1.1闹铃有效,显示为00:00:-0,再按 ;P1.1闹铃无效(显示00:00:- ,),按P1.3调闹钟结束.在闹铃可按P1.3停闹,不按闹铃1钟. ;定器T0、T1溢出周期为50MS,T0为计数用, T1为调整闪烁及表定用, ;P1.0、P1.1、P1.2、P1.3为调整按钮,P0口为字符输出口,P2为扫描口,P1.7为蜂呜器口,采用共阳显示管。 ;50H-55H为闹钟单元,60H-65H为表计单元,70H-75H为显示时间单元,76H-79H为单元。 ;03H标志=0时钟闪烁,=1表, 05H=0,不闹铃,=1要闹铃. 07H每改变一次,用作间隔呜叫. ;***********************************************************************************************; DISPFIRST EQU 30H ;显示首址存放单元 BELL EQU P1.7 ;小喇叭 CONBS EQU 2FH ;存放报次数 ; ;**************************************** ;; 中断入口程序 ;; ;****************************************
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值