51单片机秒表设计——利用定时器扫描独立按键和数码管

一、写在前面

        这次实验主要是用定时器来定时扫描独立按键和数码管,代替两个模块函数中的延时函数。用定时器定时扫描的好处就是,主函数中的延时并不会影响按键的检测和数码管的扫描,只会影响响应速度。因为定时器是溢出就会执行中断程序,是定时的扫描。

二、主要模块改进

改进的总体思路是:

  1. 只是用定时器替代延时函数,保证原有的功能不变。
  2. 定义一个被定时中断函数调用的Loop函数。
  3. 定义一个被主函数调用的新函数。该函数与原来函数的参数和返回值相同。

2.1 独立按键模块

        之前的独立按键模块功能就是:检测到松手信号,就把按键值返回,没有按键按下就返回0。中间有用延时函数消除按键抖动。

#include <REGX52.H>
unsigned char Keynum;
unsigned char key()
{
	unsigned char temp=0;
	temp=Keynum;
	Keynum=0;
	return temp;
}
unsigned char Independentkey()
{
	unsigned char keynum=0;
	if(P3_1==0){keynum=1;}
	if(P3_0==0){keynum=2;}
	if(P3_2==0){keynum=3;}
	if(P3_3==0){keynum=4;}

	return keynum;
}
void Key_Loop()
{
	static unsigned char Last_state,Now_state;
	Last_state=Now_state;
	Now_state=Independentkey();
	if(Last_state==1&&Now_state==0)//松手检测
	{
		Keynum=1;
	}
	if(Last_state==2&&Now_state==0)//松手检测
	{
		Keynum=2;
	}
	if(Last_state==3&&Now_state==0)//松手检测
	{
		Keynum=3;
	}
	if(Last_state==4&&Now_state==0)//松手检测
	{
		Keynum=4;
	}
}

2.2 数码管显示模块

        之前数码管功能是:指定哪一位,显示什么数字。数码管显示在进行段选清零或者位选清零之前,有短暂的延时是通过延时函数来完成的。

#include"Displaytube.h"
unsigned char Nixie_segs[9]={0,10,10,10,10,10,10,10,10};
void Set_Nixiesegs(unsigned char bits,number)//设置数组
{
	 Nixie_segs[bits]=number;
}
void Displaytube(unsigned char bits,segs)//bits:位选	segs:段选
{	
	static unsigned char tube[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40}; //0~9,不显示,-
	 //位选
	 P0=0x00;
	switch(bits)
	{
		case 1:P2_4=0;P2_3=0;P2_2=0;
			break;
		case 2:P2_4=0;P2_3=0;P2_2=1;
			break;
		case 3:P2_4=0;P2_3=1;P2_2=0;
			break;
		case 4:P2_4=0;P2_3=1;P2_2=1;
			break;
		case 5:P2_4=1;P2_3=0;P2_2=0;
			break;
		case 6:P2_4=1;P2_3=0;P2_2=1;
			break;
		case 7:P2_4=1;P2_3=1;P2_2=0;
			break;
		case 8:P2_4=1;P2_3=1;P2_2=1;
			break;
		default:
			break;
	}
	//段选
	P0=tube[segs];	
}
void Nixie_Loop()
{
	static unsigned char i=1;
	Displaytube(i,Nixie_segs[i]);
	i++;
	if(i>8)i=1;
}

三、测试文件test.c

#include <REGX52.H>
#include"IndependentKey.h"
#include"Displaytube.h"
#include"Timer0_Init.h"
#include"AT24C02.h"
#include"Delay.h"
unsigned char millsec,sec,min;
unsigned char Stopmode=1;
void watch_show()
{
		Set_Nixiesegs(8,min/10);
		Set_Nixiesegs(7,min%10);
		Set_Nixiesegs(6,11);
		Set_Nixiesegs(5,sec/10);
		Set_Nixiesegs(4,sec%10);
		Set_Nixiesegs(3,11);
		Set_Nixiesegs(2,millsec/10);
		Set_Nixiesegs(1,millsec%10);
		if(millsec>99)
		{
			sec++;
			if(sec>59)
			{
				min++;
				sec=0;
			}
			millsec=0;	
		}
}
int main()
{
	unsigned char keynum=0; 
	Timer0_Init();
	while(1)
	{
		keynum=key();
		if(keynum!=0)
		{
			if(keynum==1)  //暂停
			{
				Stopmode=!Stopmode;	
			}
			if(keynum==2)  //复位
			{
				millsec=0;
				min=0;
				sec=0;
			}
			if(keynum==3) //保存到AT24C02
			{
				AT24C02_Writebyte(0x01,min);
				Delay(5);//写周期
				AT24C02_Writebyte(0x02,sec);
				Delay(5);
				AT24C02_Writebyte(0x03,millsec);
				Delay(5);	
			}
			if(keynum==4) //读出数据
			{
				min=AT24C02_Readbyte(0x01);
				sec=AT24C02_Readbyte(0x02);
				millsec=AT24C02_Readbyte(0x03);
			}	
		}
		watch_show();
	}
}
void Timer0_ISR() interrupt 1
{	
	static int count1,count2,count3=0;
	count1++;
	count2++;
	count3++;
	TH0=0xfc;
	TL0=0x18;
	if(count1==20) //20ms
	{
		count1=0;
		Key_Loop();
	}
	if(count2==2) //2ms
	{
		count2=0;
		Nixie_Loop();
	}
	if(count3==10) //10ms
	{
		count3=0;
		if(Stopmode==0)
			millsec++;
	} 
}

四、效果简述

  • 启动的时候,数码管显示"00-00-00"。
  • 按下key1键,秒表开始计时。
  • 再按下key1键,秒表暂停。
  • 按下key2键,秒表清零。
  • 按下key3键,保存数据到AT24C02中。
  • 按下key4键,可以读取AT24C02中存储的数据(掉电不丢失)。
  •  

     

     

    物联沃分享整理
    物联沃-IOTWORD物联网 » 51单片机秒表设计——利用定时器扫描独立按键和数码管

    发表评论