一、功能概述
概述:通過按下矩陣鍵盤輸入數字讓數位管顯示,然後按下獨立鍵盤通過定時器開始倒計時,倒計時結束蜂鳴器響。
二、所使用的功能子產品
矩陣鍵盤、獨立鍵盤、蜂鳴器、數位管
三、程式設計過程中所遇到的問題及改進措施
問題1: 如何通過矩陣鍵盤點亮數位管并将按鍵值傳遞給定時子產品?
措施:(代碼子產品如下)
(1)矩陣鍵盤掃描 0~15。
注意:<1>受單片機I/O口數量所限,注意到矩陣鍵盤第一排和獨立鍵盤共用一組I/O口,是以如果忽略,當按下矩陣鍵盤第一排後會自動進入倒計時子產品。
<2>掃描末尾要将P3口拉高,否則在程式執行過程中由于程式段開始時進行列掃描将P3口部分拉高,導緻矩陣鍵盤二、三、四排其中一個按鍵被按下時都有可能自動進入倒計時子產品。
uchar KeyScan(uint KeyValue)
{
P3 = 0XF0;//列掃描
if(P3 != 0XF0)//判斷按鍵是否被按下
{
delay(10);//軟體消抖10ms
if(P3 != 0XF0)//判斷按鍵是否被按下
{
switch(P3) //判斷那一列被按下
{
case 0xe0: KeyValue = 0; break;//第一列被按下
case 0xd0: KeyValue = 1; break;//第二列被按下
case 0xb0: KeyValue = 2; break;//第三列被按下
case 0x70: KeyValue = 3; break;//第四列被按下
}
P3 = 0X0F;//行掃描
switch(P3) //判斷那一行被按下
{
case 0x0e: KeyValue = KeyValue; break;//第一行被按下
case 0x0d: KeyValue = KeyValue + 4; break;//第二行被按下
case 0x0b: KeyValue = KeyValue + 8; break;//第三行被按下
case 0x07: KeyValue = KeyValue + 12; break;//第四行被按下
}
while(P3 != 0X0F);//松手檢測 /***重點***/
}
}
P3=0xff; /***重點***/
return KeyValue;
}
(2)按鍵數字顯示和值傳遞
uchar Key_input(uint z)
{
uint temp1=0;
uint temp2=0;
while(!temp1)
{
P0=0xfe;
WE=1;
WE=0;
temp1=KeyScan(temp1);
P0=tabel[temp1];
DU=1;
DU=0;
temp1=temp1 * 10;
}
while(!temp2)
{
P0=0xfd;
WE=1;
WE=0;
temp2=KeyScan(temp2);
P0=tabel[temp2];
DU=1;
DU=0;
}
z=temp1+temp2;
return z;
}
問題2: 如何精确控制倒計時的時間間隔(1s)?
措施:(代碼子產品如下)
(1) 使用定時器0,通過配置16位定時器的初始值,溢出一次為50ms,溢出二十次即為1s。
(2)具體轉換步驟:
<1> 50ms=50 000us
<2>一個機器周期為1.085us(晶振頻率為11.0592)
<3>50 000/1.085=46082 個機器周期
<4>16位定時器,1111 1111 1111 1111 轉換為十進制為65535,是以65535-46082=19453 轉換為二進制為4BFD, 故高八位為 0x4B, 低八位為0xFD.
void timer0() interrupt 1 //T0溢出中斷,中斷入口為1
{
TH0=(65535-46080)/256; //高四位
TL0=(65535-46080)%256; //低四位
m++;
}
//定時器開關
void timer_open()
{
TMOD=0x01; //定時器工作模式1,16位定時器計數模式
TR0=1; //啟動定時器0
TH0=(65536-46080)/256;//4bfd
TL0=(65536-46080)%256;//定時50ms
EA=1; //cpu的總中斷允許控制位,開放中斷
ET0=1; //T0的溢出中斷允許?
}
(4)主程式段
*注意标志位flag的使用
void main()
{
uchar a1,a0;
uchar flag=0;
while(1) /***重點***/
{
if(flag==0) /***重點***/
{
Sec=Key_input(Sec);
flag=1; /***重點***/
}
if(flag==1) /***重點***/
{
if(Key_s2==0)
{
delay(20);
if(Key_s2==0)
{
timer_open();
while(1)
{
if(m==20) //中斷20次,1秒
{
m=0;//m置零
Sec--;//秒減一
}
a0=Sec%10;//實時顯示十位數字
a1=Sec/10;//實時顯示個位數字
display(a1,a0);
if(Sec==0)//倒計時結束
{
TR0=0;//關閉定時器0
beep=0;
}
}
}
}
}
}
}
//完整代碼如下:
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit DU = P2^6;
sbit WE = P2^7;
sbit beep=P2^3;
sbit Key_s2=P3^0;
uint i,m,KeyValue;
uint Sec;
//共陰數位管段選表
uchar code tabel[]= {
//0 1 2 3
0x3F, 0x06, 0x5B, 0x4F,
//4 5 6 7
0x66, 0x6D, 0x7D, 0x07,
//8 9 A B
0x7F, 0x6F, 0x77, 0x7C,
//C D E F
0x39, 0x5E, 0x79, 0x71};
void delay(uint z)
{
uint x,y;
for(x = z; x > 0; x--)
for(y = 114; y > 0 ; y--);
}
//定時器0初始化
void timer0() interrupt 1 //T0溢出中斷,中斷入口為1
{
TH0=(65535-46080)/256; //高四位
TL0=(65535-46080)%256; //低四位
m++;
}
//定時器開關
void timer_open()
{
TMOD=0x01; //定時器工作模式1,16位定時器計數模式
TR0=1; //啟動定時器0
TH0=(65536-46080)/256;//4bfd
TL0=(65536-46080)%256;//定時50ms
EA=1; //cpu的總中斷允許控制位,開放中斷
ET0=1; //T0的溢出中斷允許位
}
//4*4矩陣鍵盤掃描
uchar KeyScan(uint KeyValue)
{
P3 = 0XF0;//列掃描
if(P3 != 0XF0)//判斷按鍵是否被按下
{
delay(10);//軟體消抖10ms
if(P3 != 0XF0)//判斷按鍵是否被按下
{
switch(P3) //判斷那一列被按下
{
case 0xe0: KeyValue = 0; break;//第一列被按下
case 0xd0: KeyValue = 1; break;//第二列被按下
case 0xb0: KeyValue = 2; break;//第三列被按下
case 0x70: KeyValue = 3; break;//第四列被按下
}
P3 = 0X0F;//行掃描
switch(P3) //判斷那一行被按下
{
case 0x0e: KeyValue = KeyValue; break;//第一行被按下
case 0x0d: KeyValue = KeyValue + 4; break;//第二行被按下
case 0x0b: KeyValue = KeyValue + 8; break;//第三行被按下
case 0x07: KeyValue = KeyValue + 12; break;//第四行被按下
}
while(P3 != 0X0F);//松手檢測
}
}
P3=0xff;
return KeyValue;
}
uchar Key_input(uint z)
{
uint temp1=0;
uint temp2=0;
while(!temp1)
{
P0=0xfe;
WE=1;
WE=0;
temp1=KeyScan(temp1);
P0=tabel[temp1];
DU=1;
DU=0;
temp1=temp1 * 10;
}
while(!temp2)
{
P0=0xfd;
WE=1;
WE=0;
temp2=KeyScan(temp2);
P0=tabel[temp2];
DU=1;
DU=0;
}
z=temp1+temp2;
return z;
}
void display(uchar sh,uchar g)
{
P0=tabel[sh];
DU=1;
DU=0;
P0=0xfe;
WE=1;
WE=0;
delay(5);
P0=tabel[g];
DU=1;
DU=0;
P0=0xfd;
WE=1;
WE=0;
delay(5);
}
void main()
{
uchar a1,a0;
uchar flag=0;
while(1)
{
if(flag==0)
{
Sec=Key_input(Sec);
flag=1;
}
if(flag==1)
{
if(Key_s2==0)
{
delay(20);
if(Key_s2==0)
{
timer_open();
while(1)
{
if(m==20)
{
m=0;
Sec--;
}
a0=Sec%10;
a1=Sec/10;
display(a1,a0);
if(Sec==0)//
{
TR0=0;
beep=0;
}
}
}
}
}
}
}