?? 200548602.txt
字號:
基于單片機的8路搶答器程序
2008年01月05日 星期六 16:25
#include <stdio.h>//調(diào)用庫函數(shù)
#include <reg51.h>
#include <intrins.h>
unsigned char key, leda[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0xf3};//共陰位段碼
unsigned char sec, sec_=65; //定時65秒
unsigned char key,key_0,key_flag,key_count;
unsigned char mask=0xee,t0_count,set_no=0,led_no=0;
unsigned char set_flag=0,disp[4];
#define hi 0x3c //定時初值1(50ms)
#define lo 0xb0
#define hi1 0xff //定時初值2
#define lo1 0x00
sbit P37=P3^7;sbit P36=P3^6;sbit clk=P0^7;sbit sda=P0^6; sbit P30=P3^0;//單片機端口位矢量定義
////////////////////////////////////////////
void delay(unsigned int n) //延時函數(shù)
{unsigned int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++);
}
////////////////////////////////////////////
void shift(unsigned char dx) //74LS164移位函數(shù)
{static unsigned char d;
unsigned char j=0;
d=dx;
while(j<8) //循環(huán)8次完成8位段碼的串行移入
{ if((d&0x80)!=0) sda=1; //如果d最高位是高電平,就輸出高電平
else sda=0; //否則為0電平,就輸出0電平
clk=0;clk=1; //產(chǎn)生脈沖信號
d<<=1; //左移循環(huán)
j++;
}
}
////////////////////////////////////////////
void clktodisp(unsigned char j,xx) //數(shù)制轉(zhuǎn)換
{disp[j]=xx/10; j--; xx=xx%10; disp[j]=xx;}
////////////////////////////////////////////
void t0() interrupt 1 //0#外中斷
{ TH0=hi;TL0=lo; //重裝初值
t0_count++;key_count++;
if(t0_count==20) //如果半秒時間到
{ if (key_flag==1&&sec>0)sec--; //如果有鍵按下開始倒計時
if (key_flag==1&&sec_>0)sec_--; t0_count=0;
}
}
////////////////////////////////////////////////////////
void t1() interrupt 3 //1#外中斷
{P30=!P30;TH1=hi1;TL1=lo1;}
////////////////////////////////////////////
unsigned char get_char() //取鍵值
{ unsigned char key_code;
static unsigned char column=0,column1=4;
if(P37==0 && key_flag==0)key_code=column; //如果有鍵按下,顯示鍵號并鎖定
else
{
if(P36==0 && key_flag==0)key_code=column1; //如果有鍵按下,顯示鍵號并鎖定
else key_code=0xff;
}
column++; column1++;led_no++;
if(column>3)column=0; //如果檢測到P37為低電平,使鍵值(1)從0變化到3
if(column1>7)column1=4; //如果檢測到P36為低電平,使鍵值(2)從4變化到7
if(led_no>3)led_no=0;
mask=_crol_(mask,1); //左移循環(huán)
return key_code; //返回鍵值
}
///////////////////////////////////////////////////
void out() //輸出8位段碼
{ unsigned char dd;
dd=leda[disp[led_no]];
if((key_flag==0&&led_no!=0)||(key_flag==1&&led_no==2))shift(0x00); //使百位不顯示
else
{ if(key_flag==0)shift(leda[10]); //如果沒有鍵按下顯示“P”字碼
else shift(dd);
}
P2=mask;
}
////////////////////////////////////////////
void key_func(key) //讀鍵,并鎖定
{ switch (key)
{ case 0: disp[3]=1;key_flag=1;break;
case 1: disp[3]=2;key_flag=1;break;
case 2: disp[3]=3;key_flag=1;break;
case 3: disp[3]=4;key_flag=1;break;
case 4: disp[3]=5;key_flag=1;break;
case 5: disp[3]=6;key_flag=1;break;
case 6: disp[3]=7;key_flag=1;break;
case 7: disp[3]=8;key_flag=1;break;
default: break;
}
}
////////////////////////////////////////////
void main(void) //主函數(shù)
{ unsigned char i=1;
TMOD=0x11; //0#,1#定時器模式,方式1
TH0=hi;TL0=lo; //賦初值
TH1=hi1;TL0=lo1;
EA=1; //開中斷
ET0=1;ET1=1; //開定時
TR0=1; //允許計數(shù)
sec=60; //定時60s
P30=0;
while(1) //不斷循環(huán)
{
clktodisp( 1,sec); //使數(shù)碼管顯示倒計時時間
key=get_char( ); //取鍵值函數(shù)
key_func(key); //鍵功能函數(shù)
out();
delay(20); //延時函數(shù)
if(key_flag==1&&sec==60)
{TR1=1;key_count=0;} //如果有鍵按下則響一次鈴
else
{TR1=0; //停止計數(shù)
P30=0; //關閉響鈴
}
if(sec_<=5&&sec_>0)
{ if(t0_count<10 ) //延時半秒
TR1=1; //倒計時時間到蜂鳴器響5s
else
{TR1=0;P30=0;} //蜂鳴器響5s后停止響鈴
}
if(sec_==0)break;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -