一、写在前面
这次实验主要是用定时器来定时扫描独立按键和数码管,代替两个模块函数中的延时函数。用定时器定时扫描的好处就是,主函数中的延时并不会影响按键的检测和数码管的扫描,只会影响响应速度。因为定时器是溢出就会执行中断程序,是定时的扫描。
二、主要模块改进
改进的总体思路是:
- 只是用定时器替代延时函数,保证原有的功能不变。
- 定义一个被定时中断函数调用的Loop函数。
- 定义一个被主函数调用的新函数。该函数与原来函数的参数和返回值相同。
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中存储的数据(掉电不丢失)。
文章来源地址https://www.toymoban.com/news/detail-497168.html
文章来源:https://www.toymoban.com/news/detail-497168.html
到了这里,关于51单片机——秒表(定时器扫描独立按键和数码管)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!