程序目的:制作一个抢答器,在前五秒倒计时,若有人按键(矩阵键盘),显示其编号并且蜂鸣器报警按下S3停止报警继续倒计时,五秒后进行秒表计时,若有人按下,显示其编号且秒表停止计数。
现在遇到的问题:无法实现蜂鸣器报警和显示编号,只有倒计时和秒表显示。或有时按下S2不开始倒计时。
#include<reg52.h>
#define uint unsigned int //宏定义 unsigned int
#define uchar unsigned char //宏定义 unsigned char
sbit we = P2^7; //定义位选
sbit du = P2^6; //定义段选
sbit S2 = P3^0; //定义独立键盘S2
sbit S3 = P3^1; //定义独立键盘S3
sbit S4 = P3^2; //定义独立键盘S4
sbit beep = P2^3; //定义蜂鸣器
uint i=1;
uint d=1;
uchar counter = 0;
uint b,e=1;
void delay(uint z) //定义delay延迟函数
{
uint x,y;
for(x = z; x > 0; x--)
for(y = 120; y > 0 ; y--);
}
void display1(uint a); //声明display1函数
unsigned char leddata[]={ //定义数码管显示的字符
0x3F, //"0"
0x06, //"1"
0x5B, //"2"
0x4F, //"3"
0x66, //"4"
0x6D, //"5"
0x7D, //"6"
0x07, //"7"
0x7F, //"8"
0x6F, //"9"
0x77, //"A"
0x7C, //"B"
0x39, //"C"
0x5E, //"D"
0x79, //"E"
0x71, //"F"
0x76, //"H"
0x38, //"L"
0x37, //"n"
0x3E, //"u"
0x73, //"P"
0x5C, //"o"
0x40, //"-"
0x00, //熄灭
0xBF, //0.
0x86, //1.
0xDB, //2.
0xCF, //3.
0xE6, //4.
0xED, //5.
0xFD, //6.
0x87, //7.
0xFF, //8.
0xEF, //9.
};
uchar KeyScan() //带返回值的子函数
{
uchar cord_l,cord_h;//声明列线和行线的值的储存变量
P3 = 0xf0;//1111 0000
if( (P3 & 0xf0) != 0xf0)//判断是否有按键按下
{
delay(5);//软件消抖
if( (P3 & 0xf0) != 0xf0)//判断是否有按键按下
{
cord_l = P3 & 0xf0;// 储存列线值
P3 = cord_l | 0x0f;
cord_h = P3 & 0x0f;// 储存行线值
while( (P3 & 0x0f) != 0x0f );//松手检测
return (cord_l + cord_h);//返回键值码
}
}
}
void keypro1() //定义按键作用函数1(倒计时时使用)
{
switch(keyscan())
{
case 0xee :P0=leddata[1];break;
case 0xde :P0=leddata[2];break;
case 0xbe :P0=leddata[3];break;
case 0x7e :P0=leddata[4];break;
case 0xed :P0=leddata[5];break;
case 0xdd :P0=leddata[6];break;
case 0xbd :P0=leddata[7];break;
case 0x7d :P0=leddata[8];break;
}
}
void keypro2() //定义按键作用函数2(秒表计时时使用)
{
switch(keyscan())
{
case 0xee :P0=leddata[5];break;
case 0xde :P0=leddata[5];break;
case 0xbe :P0=leddata[5];break;
case 0x7e :P0=leddata[5];break;
case 0xed :P0=leddata[5];break;
case 0xdd :P0=leddata[5];break;
case 0xbd :P0=leddata[5];break;
case 0x7d :P0=leddata[5];break;
}
}
void display1(uint a) //定义倒计时函数
{
uint b;
b = 5-a;
P0 = 0xff;
we = 1;
P0 = 0xef;
we = 0;
du = 1;
P0 = leddata[b];
du = 0;
delay(1);
}
void display(uint a) //定义秒表计时函数
{
uint shi,ge,fen ;
shi = a/100;
ge = a%100/10+24;
fen = a%10;
P0 = 0xff;
we = 1;
P0 = 0xdf;
we = 0;
du = 1;
P0 = leddata[shi];
du = 0;
delay(1);
we = 1;
P0 = 0xbf;
we = 0;
du = 1;
P0 = leddata[ge];
du = 0;
delay(1);
we = 1;
P0= 0x7f;
we = 0;
du = 1;
P0 = leddata[fen];
du = 0;
delay(1);
we = 1;
P0 = 0xef;
we = 0;
du = 1;
P0 = leddata[b];
delay(1);
}
void Init
timer() //定义定时器模式
{
TMOD = 0x01; //使用计时器0
TH0 = 0x4c; //计时50毫秒
TL0 = 0x00;
}
void main() //主函数体
{ uint d=1,e=1; //定义标识符d,e
uint time_counter = 0; //定义记录时间变量
InitTimer(); //打开计时器
while(1)
{
if(time_counter <= 5)
{
display1(time_counter); //开始倒计时
if(TF0 == 1) //溢出处理
{
TF0 = 0;
TH0 = 0x4c;
TL0 = 0x00;
counter++;
}
if(counter == 20) //满秒+1处理
{
counter = 0;
time_counter++;
}
if(keyscan()) //判断是否按下矩阵键盘
{
beep=0; //蜂鸣器响
we = 1; //位选打开
P0 = 0xfe; //第一位数码管
we = 0; //位选关闭
du = 1; //段选打开
P0 = 0x00; //消除虚影
while(d)
{
keypro1(); //抢答按键响应模式1{报警和显示编号}
if(S3 == 0) //按下按键S3,继续倒计时
{
delay(1); //消抖设置
if(S3 == 0)
{
d=0;
while(!S3);
}
}
}
}
if(S2 == 0) //按下按键S2开始倒计时
{
delay(1); //消抖设置
if(S2 == 0)
{
TR0 = 1;
while(!S2);
}
}
}
if(time_counter >= 5) //倒计时结束。秒表计时开始
{
time_counter = 0; //时间清0
InitTimer();
TR1=1;
while(1) //秒表计时设置
{
if(TF0 == 1)
{
TF0 = 0;
TH0 = 0x4c;
TL0 = 0x00;
counter++;
}
if(counter == 2)
{
counter = 0;
time_counter++;
}
if(time_counter == 600)
{
time_counter = 0;
b++;
}
display(time_counter);
if(keyscan())
{ TR0=0, //计时停止
we = 1; //位选打开
P0 = 0xfe; //第一位数码管亮
we = 0; //位选关闭
du = 1; //打开段选
P0 = 0x00; //消影处理
while(e)
{
keypro2(); //按键响应系统2{显示抢答者编号}
if(S4 == 0) //退出显示循环
{
delay(1); //消抖处理
if(S4 == 0)
{
e=0;
while(!S4);
}
}
}
}
}
}
}
}
哦,就是抢答器,前五秒倒计时,按下键盘时报警,显示号码。后五秒时正计时,按下键盘后停止计数,显示号码。
一周热门 更多>