|
書寫的51程序我之前發(fā)過一版但是這版更加的精細(xì) 我增加了按鍵和定時(shí)器自動(dòng)走
#include <reg52.h>
//------------------------- 引腳定義 --------------------------//
sbit BEEP = P2^0; //蜂鳴器控制引腳,高電平有效
sbit LED1 = P2^3; //LED1,控制引腳,低電平有效
sbit LED2 = P2^2; //LED2,控制引腳,低電平有效
sbit LED3 = P2^1; //LED3,控制引腳,低電平有效
//數(shù)碼管引腳定義
#define duanPore P0 //數(shù)碼管段控制端口,高電平有效
sbit DIG1 = P2^4; //數(shù)碼管第1位位選控制端口,低電平有效
sbit DIG2 = P2^5; //數(shù)碼管第2位位選控制端口,低電平有效
sbit DIG3 = P2^6; //數(shù)碼管第3位位選控制端口,低電平有效
sbit DIG4 = P2^7; //數(shù)碼管第4位位選控制端口,低電平有效
//按鍵引腳定義
sbit KEY1 = P1^0; //1號(hào)選手
sbit KEY2 = P1^1; //2號(hào)選手
sbit KEY3 = P1^2; //3號(hào)選手
sbit KEY4 = P1^3; //4號(hào)選手
sbit KEY5 = P1^4; //5號(hào)選手
sbit KEY6 = P1^5; //6號(hào)選手
sbit KEY7 = P3^2; //主持人鍵
sbit KEY8 = P3^3; //設(shè)置鍵
sbit KEY9 = P1^6; //增加鍵
sbit KEY10 =P1^7; //減少鍵
#define uchar unsigned char
#define uint unsigned int
//---------------------- 全局變量定義 --------------------//
//數(shù)碼管段碼表,適用于共陰數(shù)碼管
unsigned char code tab_duan[18] =
{
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, //0~9
0x77,0x7c,0x39,0x5e,0x79,0x71, //A~F
0x40,0x00 //'-',關(guān)閉顯示
};
unsigned char dat_buf[4] = {0,0,0,0}; //顯示數(shù)據(jù)緩存區(qū),默認(rèn)上電顯示" 05"
int time = 10; //倒計(jì)時(shí)時(shí)間
unsigned char i = 0;
unsigned int count = 0; //計(jì)數(shù)緩存變量
bit flag_lock = 1; //鍵盤鎖定標(biāo)志,1:不鎖定,0:鎖定
uint flag=0;
//------------------------------- 函數(shù)聲明 ------------------------------------//
void DelayMs(unsigned int ms); //延時(shí)函數(shù),單位:ms
void dig_scan(unsigned char *dat);
unsigned char KeyScan(void); //獨(dú)立按鍵掃描
void InitTimer0(void); //定時(shí)器0初始化
void alarm(void); //報(bào)警函數(shù)
void AnswerTask(void); //搶答任務(wù)
/* 主函數(shù) */
void main(void)
{
BEEP = 0; //上電默認(rèn)關(guān)閉蜂鳴器
LED1 = 1;
InitTimer0(); //定時(shí)器0初始化
while(1)
{
if(KeyScan() == 7) //如果主持人鍵按下,則進(jìn)行搶答
{
alarm(); //蜂鳴器響一聲
AnswerTask(); //進(jìn)行搶答任務(wù)
}
if(KEY9 == 0) //如果按鍵8按下
{
DelayMs(50); //延時(shí)10ms去除按鍵抖動(dòng)
if(KEY9 == 0) //再確認(rèn)一次按鍵按下,表示到這按鍵已經(jīng)穩(wěn)定了
time++;
if(time > 260)//只顯示0~9,故到9 就歸零
{
time =0;
}
while(KEY9 == 0);//保持對(duì)K1的判斷,松開才執(zhí)行下一句
dat_buf[1] = time/ 100 % 10;
dat_buf[2] = time / 10; //取出倒計(jì)時(shí)的十位數(shù)
dig_scan(dat_buf); //測(cè)試數(shù)碼管顯示
}
if(KEY10 == 0) //如果按鍵8按下
{
DelayMs(50); //延時(shí)10ms去除按鍵抖動(dòng)
if(KEY10 == 0) //再確認(rèn)一次按鍵按下,表示到這按鍵已經(jīng)穩(wěn)定了
while(KEY10 == 0);
time--;
if(time <0)//讓0~9不論是加還是減都能循環(huán)
{
time =99;
}
}
dat_buf[1] = time/ 100 % 10;; //取出倒計(jì)時(shí)的十位數(shù)
dat_buf[2] = time / 10; //取出倒計(jì)時(shí)的十位數(shù)
dig_scan(dat_buf); //測(cè)試數(shù)碼管顯示
}
}
/* 延時(shí)函數(shù),單位:ms */
void DelayMs(unsigned int ms)
{
unsigned char a,b,c;
while(--ms)
{
for(c=1;c>0;c--)
for(b=142;b>0;b--)
for(a=2;a>0;a--);
}
}
/* 數(shù)碼管顯示掃描 */
void dig_scan(unsigned char *dat)
{
/* 動(dòng)態(tài)掃描處理 */
switch(i)
{
case 0:
{
duanPore = tab_duan[dat[0]]; //顯示第1位數(shù)碼管內(nèi)容
DIG1 = 0;
break;
}
case 1:
{
duanPore = tab_duan[dat[1]]; //顯示第2位數(shù)碼管內(nèi)容
DIG2 = 0; //選通第2位數(shù)碼管
break;
}
case 2:
{
duanPore = tab_duan[dat[2]]; //顯示第3位數(shù)碼管內(nèi)容
DIG3 = 0; //選通第3位數(shù)碼管
break;
}
case 3:
{
duanPore = tab_duan[dat[3]]; //顯示第4位數(shù)碼管內(nèi)容
DIG4 = 0; //選通第4位數(shù)碼管
break;
}
default: break;
}
DelayMs(5); //掃描延時(shí)10ms,根據(jù)實(shí)際情況適當(dāng)修改改延時(shí)時(shí)間
DIG1 = 1; //消隱
DIG2 = 1;
DIG3 = 1;
DIG4 = 1;
++i; //掃描變量循環(huán)
if(i > 3)
i = 0;
}
/* 獨(dú)立按鍵掃描 */
unsigned char KeyScan(void)
{
if(KEY1 == 0) //如果按鍵1按下
{
DelayMs(10); //延時(shí)10ms去除按鍵抖動(dòng)
if(KEY1 == 0) //再確認(rèn)一次按鍵按下,表示到這按鍵已經(jīng)穩(wěn)定了
return 1; //輸出按鍵值1
}
if(KEY2 == 0) //如果按鍵2按下
{
DelayMs(10); //延時(shí)10ms去除按鍵抖動(dòng)
if(KEY2 == 0) //再確認(rèn)一次按鍵按下,表示到這按鍵已經(jīng)穩(wěn)定了
return 2; //輸出按鍵值2
}
if(KEY3 == 0) //如果按鍵3按下
{
DelayMs(10); //延時(shí)10ms去除按鍵抖動(dòng)
if(KEY3 == 0) //再確認(rèn)一次按鍵按下,表示到這按鍵已經(jīng)穩(wěn)定了
return 3; //輸出按鍵值3
}
if(KEY4 == 0) //如果按鍵4按下
{
DelayMs(10); //延時(shí)10ms去除按鍵抖動(dòng)
if(KEY4 == 0) //再確認(rèn)一次按鍵按下,表示到這按鍵已經(jīng)穩(wěn)定了
return 4; //輸出按鍵值4
}
if(KEY5 == 0) //如果按鍵5按下
{
DelayMs(10); //延時(shí)10ms去除按鍵抖動(dòng)
if(KEY5 == 0) //再確認(rèn)一次按鍵按下,表示到這按鍵已經(jīng)穩(wěn)定了
return 5; //輸出按鍵值5
}
if(KEY6 == 0) //如果按鍵6按下
{
DelayMs(10); //延時(shí)10ms去除按鍵抖動(dòng)
if(KEY6 == 0) //再確認(rèn)一次按鍵按下,表示到這按鍵已經(jīng)穩(wěn)定了
return 6; //輸出按鍵值6
}
if(KEY7 == 0) //如果按鍵7按下
{
DelayMs(10); //延時(shí)10ms去除按鍵抖動(dòng)
if(KEY7 == 0) //再確認(rèn)一次按鍵按下,表示到這按鍵已經(jīng)穩(wěn)定了
return 7; //輸出按鍵值7
}
if(KEY8 == 0) //如果按鍵8按下
{
DelayMs(10); //延時(shí)10ms去除按鍵抖動(dòng)
if(KEY8 == 0) //再確認(rèn)一次按鍵按下,表示到這按鍵已經(jīng)穩(wěn)定了
return 8; //輸出按鍵值8
}
//輸出按鍵值8
return 0; //無按鍵按下輸出0
}
/* 定時(shí)器0初始化 */
void InitTimer0(void)
{
TMOD = 0x01; //配置定時(shí)器0為工作模式1,16位定時(shí)器
TH0 = (65536 - 10000) / 256; //定時(shí)10ms
TL0 = (65536 - 10000) % 256;
EA = 1; //打開總中斷
ET0 = 1; //打開定時(shí)器0中斷
TR0 = 0; //上電默認(rèn)關(guān)閉定時(shí)器0
}
/* 定時(shí)器0中斷服務(wù)函數(shù),10ms進(jìn)一次中斷 */
void Timer0Interrupt(void) interrupt 1
{
TH0 = (65536 - 10000) / 256; //定時(shí)10ms,重新裝載計(jì)數(shù)值
TL0 = (65536 - 10000) % 256;
++count;
if(count > 100) //1s時(shí)間計(jì)算:10ms * 100 = 1s
{
count = 0; //計(jì)數(shù)值清零
--time; //倒計(jì)時(shí)時(shí)間減一次
if(time <= 0) //如果倒計(jì)時(shí)結(jié)束,則關(guān)閉定時(shí)器0,停止倒計(jì)時(shí),并聲光報(bào)警和鎖定鍵盤
{
TR0 = 0; //關(guān)閉定時(shí)器0
BEEP = 1; //聲光報(bào)警
LED1 = 0;
flag_lock = 0; //鎖定鍵盤
}
}
}
/* 報(bào)警函數(shù) */
void alarm(void)
{
BEEP = 1; //蜂鳴器響一下
DelayMs(300); //延時(shí)300ms
BEEP = 0;
}
/* 實(shí)現(xiàn)搶答任務(wù) */
void AnswerTask(void)
{
unsigned char key_val; //按鍵值緩存
TR0 = 1; //啟動(dòng)定時(shí)器0,開始倒計(jì)時(shí)
while(1)
{
if(flag_lock == 1)
{
key_val = KeyScan(); //獲取按鍵值
switch(key_val)
{
case 1:
{
dat_buf[0] = key_val; //第1位數(shù)碼管顯示1號(hào)
//顯示'-'
time = 200; //倒計(jì)時(shí)20s,選手回答時(shí)間
alarm(); //蜂鳴器響一下
flag_lock = 0; //鎖定鍵盤
break;
}
case 2:
{
dat_buf[0] = key_val; //第2位數(shù)碼管顯示2號(hào)
//顯示'-'
time = 20; //倒計(jì)時(shí)20s,選手回答時(shí)間
alarm(); //蜂鳴器響一下
flag_lock = 0;
break;
}
case 3:
{
dat_buf[0] = key_val; //第3位數(shù)碼管顯示3號(hào)
//顯示'-'
time = 20;
alarm(); //蜂鳴器響一下
flag_lock = 0;
break;
}
case 4:
{
dat_buf[0] = key_val; //第4位數(shù)碼管顯示4號(hào)
//顯示'-'
time = 20;
alarm(); //蜂鳴器響一下
flag_lock = 0;
break;
}
case 5:
{
dat_buf[0] = key_val; //第5位數(shù)碼管顯示5號(hào)
//顯示'-'
time = 20;
alarm(); //蜂鳴器響一下
flag_lock = 0;
break;
}
case 6:
{
dat_buf[0] = key_val; //第6位數(shù)碼管顯示6號(hào)
time = 20;
alarm(); //蜂鳴器響一下
flag_lock = 0;
break;
}
default: break;
}
}
dat_buf[1] = time / 100 % 10; //取出倒計(jì)時(shí)的十位數(shù)
dat_buf[2] = time / 10; //取出倒計(jì)時(shí)的十位數(shù)
dig_scan(dat_buf); //數(shù)碼管顯示內(nèi)容
}
}
|
|