数字抢答器课程设计C语言
设计要求:
(1)抢答器同时供10名选手或10个代表队比赛。
(2)设置一个系统清除和抢答控制开关S,该开关由主持人控制。
(3)抢答器具有锁存与显示功能。即选手按动按钮,锁存相应的编号,并在LED数码管上显示,同时扬声器发出报警声响提示。选手抢答实行优先锁存,优先抢答选手的编号一直保持到主持人将系统清除为止。
(4)抢答器具有定时抢答功能,且一次抢答的时间由主持人设定(如20s)。当主持人启动“开始”键后,定时器进行减计时,同时扬声器发出短暂的声响,声响持续的时间0.5s左右。
(5)参赛选手在设定的时间内进行抢答,抢答有效,定时器停止工作,显示器上显示选手的编号和抢答的时间,并保持到主持人将系统清除为止。
(6)如果定时时间已到,无人抢答,本次抢答无效,系统报警并禁止抢答,定时显示器上显示00。
单片机型号:STC15F2K60S2单片机
程序重要包含四个部分:主程序,延时子程序,主持人按键子程序,选手按键子程序,数码管显示子程序
#include <stc15f2k60s2.h>
sbit KEY0 = P3 ^4;//设置抢答时间
sbit KEY1 = P3 ^ 5;//开始
sbit KEY2 = P3 ^ 6;//清除
sbit fqm = P5 ^ 4;//蜂鸣器
sbit K9 = P4 ^ 4;//选手
sbit K10 = P4 ^ 2;
unsigned char sbufNum[8] = {0};
//共阴
//unsigned char code Semg[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};
unsigned char code Semg[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
unsigned char key_new = 0;
unsigned char key_can;
unsigned int Mil=0;
unsigned char second, setSecond = 00;//倒计时时间
unsigned char SegCnt = 0;
unsigned char state = 0, flagrun = 0;
#define DELAY 200
void DelaymsKey(int x)//按键毫秒延时函数
{
int i, j;
for (j = 0; j < x; j++)
{
for (i = 0; i < 122; i++)
}
}
//选手按键显示部分
void KeyScan(void)
{
unsigned char temp = 0;
if ((P2 != 0XFF) || (K9 == 0) || (K10 == 0) || (KEY0 == 0) || (KEY1 == 0) || (KEY2 == 0)) //
{
DelaymsKey(10);//按键延时去抖
if (((P2 != 0XFF) || (K9 == 0) || (K10 == 0) || (KEY0 == 0) || (KEY1 == 0) || (KEY2 == 0)) && (key_new == 1))
{
key_new = 0;
temp = P2;//选手接口
switch (temp)
{
case 0x7f:
key_can = 1;//赋值选手号码
break;
case 0xbf:
key_can = 2;
break;
case 0xdf:
key_can = 3;
break;
case 0xef:
key_can = 4;
break;
case 0xf7:
key_can = 5;
break;
case 0xfb:
key_can = 6;
break;
case 0xfd:
key_can = 7;
break;
case 0xfe:
key_can = 8;
break;
}
if (K9 == 0)//4.4接口单独赋值
key_can = 9;
if (K10 == 0)//4.2接口单独赋值
key_can = 10;
if (KEY0 == 0)//设置抢答时间
key_can = 11;
if (KEY1 == 0)//开始
key_can = 12;
if (KEY2 == 0)//清除
key_can = 13;
}
}
else
{
key_new = 1;
}
}
void Timer0Interrupt() interrupt 1 using 0
{//定时器中断
TH0 = (65536 - 5000) / 256;
TL0 = (65536 - 5000) % 256;
if (Mil < DELAY)
Mil++;
else
{
Mil = 0;
if (flagrun)
{
if (second > 0)
{
second--;
}
}
}
SegCnt++;
P2 = SegCnt % 8;
P0 = Semg[sbufNum[SegCnt % 8]];
}
//蜂鸣器持续时间
void beepOut(int beeptime)
{
int i = 0, j;
for (i = 0; i < beeptime; i++)
{
for (j = 0; j < 100; j++)
fqm = ~fqm;
}
}
void main(void)
{
unsigned char state = 0;
P1M1=0x00;
P1M0=0xFF;
TMOD = 0x01; //定时器0方式1
TH0 = (65536 - 5000) / 256;
TL0 = (65536 - 5000) % 256;
TR0 = 1;
ET0 = 1;
IE0 = 1;
IT0 = 1;
EA = 1;
beepOut(80);//蜂鸣器响
while (1)
{
key_can = 0xff;
KeyScan();//调用选手按键函数
switch (state)
{
case 0:
//设置抢答时间
if (key_can == 11)
{
if (setSecond < 30)
setSecond++;
else
setSecond = 0;
}
//开始
if (key_can == 12)
{
flagrun = 1;
second = setSecond;
beepOut(250);
state = 1;
}
sbufNum[0] = setSecond / 10 % 10;//十位
sbufNum[1] = setSecond % 10;//个位
sbufNum[2] = 0;
sbufNum[3] = 0;
break;
case 1:
sbufNum[0] = second / 10 % 10;
sbufNum[1] = second % 10;
//选手号码显示
if (key_can < 11)
{
if ((flagrun) && (second > 0)) //抢答过程倒计时显示
{
sbufNum[2] = key_can / 10 % 10;//十位
sbufNum[3] = key_can % 10;//个位
flagrun = 0;//标志位清0
}
}
if ((flagrun == 0)&&(second==0)) //倒计时结束
{
sbufNum[2] = 0;
sbufNum[3] = 0;
}
//清除
if (key_can == 13)
{
flagrun = 0;
second = setSecond;
state = 0;
}
break;
}
}
}
原理图采用AD绘制:
仿真图: