昨天同學問我能不能幫他做道題,有關單片機定時器的,我大概寫了一個小時把這道題完成了,寫這篇部落格記錄練習和學習的曆程。
使用的是普中科技的A2開發闆。
題目
數位管秒表設計
任務1,能夠操作數位管顯示任意數字
任務2,在數位管的第1、2位顯示秒數,第3位顯示“-”,第4位顯示1/10秒,第5位顯示1/100秒。
任務3,按下獨立按鍵K1後,秒表開始計時,再次按下獨立按鍵K1後,秒表停止,按下獨立按鍵K2後,秒表計數清零。
分析: 完成這個題目需要運用中斷、獨立鍵盤和數位管的相關知識。
我的代碼
#include"reg52.h"
typedef unsigned int u16; //偷懶
typedef unsigned char u8;
u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//數位管顯示0-9的段選的數值
int sec; //定義秒變量
int msec; //定義毫秒變量
int count;//定義計時器溢出變量
sbit LSA=P2^2; //定義數位管位選的引腳
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit k1=P3^1; //定義獨立鍵盤的引腳
sbit k2=P3^0;
/*
名稱:delay
作用:延時
*/
void delay(u16 z)
{
u16 x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*
名稱:sec_display
作用:數位管上秒的十位和個位數的顯示
*/
void sec_display(int second)
{
LSA=1;//數位管位選,下皆同
LSB=1;
LSC=1;
P0=smgduan[second/10];//顯示秒的十位
delay(10);
//短暫延時,下同,在這裡延時的時間越短,重新整理的頻率越高,看起來數位管閃爍的程度就越弱
P0=0x00;//消隐,下同
LSA=0;
LSB=1;
LSC=1;
P0=smgduan[second%10];
delay(10);
P0=0x00;
}
/*
名稱:mirco_display
作用:數位管上1/10秒和1/100秒的顯示
*/
void mirco_display(int x)
{
msec=x*50;//count加1,大約是50ms,這裡x是後面輸入的count
LSA=0;
LSB=0;
LSC=1;
P0=smgduan[msec/100];
delay(10);
P0=0x00;
LSA=1;
LSB=1;
LSC=0;
P0=smgduan[msec%100/10];
delay(10);
P0=0x00;
}
/*
名稱:sta_display
作用:數位管上分隔符"-"的顯示
*/
void sta_display()
{
LSA=1;
LSB=0;
LSC=1;
P0=0x40;
delay(10);
P0=0x00;
}
/*
名稱:init
作用:定時器初始化,包括:确定定時器工作方式,打開總中斷,裝入初始值等,但是在這裡定時器0一開始是關閉的,對應題目要求的按下鍵盤才開始計時
*/
void init()
{
TMOD=0x01; //确定定時器工作方式
EA=1; //打開總中斷
ET0=1;
TR0=0; //關閉定時中斷0
TH0=(65536-50000)/256; //裝入初始值
TL0=(65536-50000)%256;
}
/*
名稱:keyscan
作用:鍵盤檢測,使用循環掃描的方式來檢測是否有按鍵輸入
*/
void keyscan()
{
if(k1==0) //檢測到按鍵1按下
{
delay(50); //短暫延時,消除抖動
if(k1==0)
{
TR0=~TR0; //定時器狀态取反,按下一次是打開,再按一次是關閉
while(!k1);//檢測到松手
}
}
if(k2==0) //檢測到按鍵2按下
{
delay(50); //短暫延時,消除抖動
if(k2==0)
{
count=0;//數值歸零,以達到顯示歸零的效果
sec=0;
while(!k2);//檢測到松手
}
}
}
/*
名稱:主函數
作用:程式的主體
*/
void main()
{
init();//初始化
while(1)//進入死循環
{
keyscan();
sta_display();
sec_display(sec);
mirco_display(count);
}
}
/*
名稱:timer0
作用:定時器中斷
*/
void timer0() interrupt 1
{
TH0=(65536-50000)/256;//裝入初始值
TL0=(65536-50000)%256;
count++; //約50ms,count加1
if(count==20) //count加20次,即1000ms=1s,秒加一
{
count=0; //count歸零
sec++;
if(sec==60) //當s到達60,s歸零
sec=0;
}
}