sweetyy、

导航

单片机计时器(数码管显示)

单片机计时器(数码管显示)

一、开发板简介

1、数码管为阴极,位控码对应P2.4~P2.7端口,段码对应P0口,高电平有效

2、LED灯对应P1口,低电平有效

3、独立按键对应P3.4~P3.7端口,低电平有效

4、计算

转化为16进制,高位=x/256

​ 低位=x%256

二、Keil程序

#include <reg51.h>
#define uchar unsigned char
unsigned char j,k,num0,num1,num2,num3,sec,min,count=0;
unsigned char time_count;
//数码管位控码
unsigned char code weitable[]={0x8f,0x4f,0x2f,0x1f};
//数码管段码(不带小数点)
unsigned char code dis_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,                          0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//数码管段码(带小数点)
unsigned char code dis_code1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,                        0x87,0xff,0xef};
sbit k4 = P3^6;   //按键K4
sbit k5 = P3^7;   //按键K5
sbit beep = P2^3;   //蜂鸣器
 bit stop = 1;      //停止工作标记位
															//延时函数	
void delay(unsigned char i)
{
  for(j=i;j>0;j--)
    for(k=85;k>0;k--);
}

//在某一位数码管上显示的数字
void display1(uchar wei,uchar shu)
{
   //数码管位控码全置1,即全部选中
   P2=P2|0xf0;
   //如果是第二位,就用带小数点的段码,即3 2 . 1 0
   if(wei == 2)   
   	P0=dis_code1[shu];
   	//否则用不带小数点的段码
   else
    P0=dis_code[shu];
    
    //给P2需要显示的那一位置1,其他置0,即单独设置位控码,选择某位
    P2=P2&weitable[wei];
    delay(5);
}
 //一次显示4个数字,且每位显示数字可自定
void display(unsigned char a,unsigned char b,unsigned char c,unsigned char d)
{						 
   display1(3,a);
   display1(2,b);
   display1(1,c);
   display1(0,d);
}

void start_timer()
{
   	  ET0=1;   //开定时器0中断			 
	  EA=1;	   //开总中断,中断允许总开关控制位,1表示允许	
	  TR0=1;   //打开定时器	 
}

void stop_timer()
{
      ET0=0;	//关闭定时器0中断	 
	  EA=0;		//关总中断,中断允许总开关控制位,0表示不允许	
	  TR0=0;	//关闭定时器
}

void main()
{
    //模式设置,00000001,采用的是定时器0,工作模式1
	TMOD=0x01;	
    //晶振为11.0592,所以50000*11.0592/12=46080
	TH0=(65536-46080)/256;
	TL0=(65536-46080)%256;
	while(1)
	{
		if(k4 == 0)  //按下键
		{
			delay(10);  //去抖动
			if(k4 == 0)
			{
				while(k4 == 0); //直到按键判断松开
				{
					if(stop)  //标记位初值为1
//因为按下了键,所以如果停止工作标记位为1,表示没工作,那么要打开定时器						
						start_timer();                       
					else	
/*如果本来就是0,即本来就打开,那正在工作的时候按下键,说明是暂停,就关闭定时器 */					
						stop_timer();	
                        
                     //状态取反、关闭蜂鸣器、流水灯全灭
					  stop = ~stop;
				      beep = 1;
					  P1 = 0xff;
				}
			}
		}
		else if(k5 == 0)  //按下K5键,则清零
		{
			delay(10);  //去抖动
			if(k5 == 0)  //再次判断按键是否被按下
			{
				while(k5 == 0); //直到按键判断松开
				{	
					stop_timer();	//关闭定时器		 
					stop = 1;
					beep = 1;
					P1 = 0xff;
					count = 0;
					time_count = 0;
					sec = 0;	   //记时清零		 
					min = 0;
				}
			}
		}
		
//当暂停或停止时,led灯闪亮表明在等待
		if(stop)
		{
 /*每当count加一执行完,P1口对应的led灯状态就取反,即一亮一灭的闪亮效果,count终值越小,闪亮的越快。这里用count实现闪亮,不需要准确时间,不会影响数码管的刷屏,也不会造成延时而影响数码管。*/	
			count++;
			if(count == 60)
			{
				P1 = ~P1;
				count = 0;
			}
		}
		 //没停止,即在计时,在工作
		else if(time_count==20)  //计数20次,20*0.05秒=1秒
		{
			count = 0;
			time_count=0;
			sec++;
			if(sec==60)
			{
				sec=0;	 //如果到了60s,则归零   
				min++;
			}
			if(min==60)
			{
				min=0;	 //如果到了60min,则归零   
			}
			//计时达最大值,蜂鸣器响,提示
			beep = 0;
			delay(10);
			beep = 1;
		}
		num0=sec%10;	//取出秒数的个位	 
		num1=sec/10;    //取出秒数的十位	
		num2=min%10;	//取出分数的个位	
		num3=min/10;    //取出分数的十位	
		display(num3,num2,num1,num0);	  
	}
}

void timer0() interrupt 1
{
	TH0=(65536-46080)/256;
	TL0=(65536-46080)%256;
	time_count++;//每隔0.05s加一次
}

三、效果展示

posted on 2021-12-23 17:24  sweetyy、  阅读(220)  评论(0)    收藏  举报