目录
百度网盘下载链接:https://pan.baidu.com/s/1mojcSZMy_wdgINXWBWhudg?pwd=yjc3
提取码:yjc3
protues版本为8.15,可直接用普中开发板进行实物调试。
文件内容如下:
1 设计任务
1.1题目
基于51单片机的八位竞赛抢答器的系统设计
1.2功能要求:
以单片机为核心,设计一个8位竞赛抢答器:同时供8名选手或8个代表队比赛,分别用8个按钮K1~K8表示。
设置一个系统清除和抢答控制开关S,开关由主持人控制。
抢答器具有锁存与显示功能。即选手按按钮,锁存相应的编号,并将优先抢答选手的编号一直保持到主持人将系统清除为止。
抢答器具有定时抢答功能,且一次抢答的时间由主持人设定(如30秒)。当主持人启动“开始”键后,定时器进行减计时,同时扬声器发出短暂的声响,声响持续的时间为0.5s左右。
参赛选手在设定的时间内进行抢答,抢答有效,定时器停止工作,显示器上显示选手的编号和抢答的时间,并保持到主持人将系统清除为止。
如果定时时间已到,无人抢答,本次抢答无效,系统报警并禁止抢答,定时显示器上显示00。
2 系统硬件设计
本设计的硬件设计在实物设计之前先根据开发板原理图编写相应的程序并使用 Proteus软件进行仿真调试,在仿真成功运行后再在开发板上进行验证,可以有效保护开发板,减少实物调试时出现的问题。
2.1系统总体设计方案
本系统采用模块化设计原则,将软硬件相结合,硬件部分由单片机、数码管显示等电路组成,软件部分,把收集到的选手按键信息上传到数码管上并显示出来,从而实现抢答功能。
该设计采用STC89C52单片机作为控制系统核心,完成信号识别,运算控制以及显示功能。系统整体设计由STC89C52单片机、选手按键模块、主持人按键模块、数码管显示模块、蜂鸣器报警模块组成。该系统的整体设计如图2.1所示。
3 系统程序设计
在本设计中包括了以下主要的程序:主程序,键盘扫描程序,数码管显示程序,倒计时程序以及蜂鸣器报警程序。通过 STC89C52芯片的控制,实现各个系统模块的通信连接,获取各个部分的信息,并使相应的信息显示在数码管上。
3.1 主程序设计
主程序的功能设计目标主要是完成内部各寄存单元的初始化 , 对接口电路、内部定时器、中断的初始化,查询开始抢答按键是否按下;调用显示程序对初始状态的显示以及对外部信号的等待处理,总的来说就是完成前期准备工作并随时等待与外部信号对接。
附录:
仿真原理图:
程序代码:
#include<reg52.h>
typedef unsigned char u8;
typedef unsigned int u16;
//数码管接口定义
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
#define KEY_MATRIX_PORT P1 //矩阵按键
#define SMG_A_DP_PORT P0 //数码管
sbit key_clear=P3^0;//主持人时间清除
sbit key_begin=P3^1;//主持人开始按键
sbit BEEP=P2^5;
u8 second=30;//秒表计数值
u8 counter=0;//counter每100,minite加1
u8 people=0;//抢答结果
u8 gsmg_code[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//数码管显示0,1,2,3,4,5,6,7,8,9
//1ms延时函数
void delay_ms(u16 ms)
{
u16 i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
void beep_alarm(unsigned int ms) //蜂鸣器播放,时间单位:ms
{
unsigned int i;
for(i=0;i<ms*2;i++)
{
BEEP=!BEEP;
delay_ms(1);
}
}
u8 key_matrix_flip_scan(void) //线翻转方式扫描
{
static u8 key_value=0;
KEY_MATRIX_PORT=0x0f;
if(KEY_MATRIX_PORT!=0x0f)
{
delay_ms(10);
//测试列
if(KEY_MATRIX_PORT!=0x0f)
{
KEY_MATRIX_PORT=0x0f;
switch(KEY_MATRIX_PORT)
{
case 0x07:key_value=1;break;
case 0x0b:key_value=2;break;
case 0x0d:key_value=3;break;
case 0x0e:key_value=4;break;
}
//测试行
KEY_MATRIX_PORT=0xf0;
switch(KEY_MATRIX_PORT)
{
case 0x70:key_value=key_value;break;
case 0xb0:key_value=key_value+4;break;
case 0xd0:key_value=key_value+8;break;
case 0xe0:key_value=key_value+12;break;
}
while(KEY_MATRIX_PORT!=0xf0); //等待按键松开
}
}
else
key_value=0;
return key_value;
}
void smg_display(u8 dat[],u8 pos) //数码管显示函数
{
u8 i=0;
u8 pos_temp=pos-1;
for(i=pos_temp;i<2;i++)
{
switch(i)//位选
{
case 0: LSA=1;LSB=1;LSC=1;break;
case 1: LSA=0;LSB=1;LSC=1;break;
}
SMG_A_DP_PORT=dat[i-pos_temp];//传送段选数据
delay_ms(1);//延时一段时间,等待显示稳定
SMG_A_DP_PORT=0x00; //消影
}
}
void time_display(u8 x)//时间显示
{
u8 time_buf[2];
time_buf[0]=gsmg_code[x/10];
time_buf[1]=gsmg_code[x%10];//秒
smg_display(time_buf,1);//显示
}
void scare_display(u8 x)//抢答结果显示
{
u8 key=0;
u8 i=0;
key=x;
if(key!=0)
{
switch(i)
{
case 0: LSA=1;LSB=0;LSC=1;break;
}
SMG_A_DP_PORT=gsmg_code[0];
delay_ms(1); //延时1ms,肉眼看不到变化
SMG_A_DP_PORT=0x00; //消影
LSA=0;
LSB=0;
LSC=1;
SMG_A_DP_PORT=gsmg_code[key];//数码管显示选手号
delay_ms(1); //延时1ms,肉眼看不到变化
SMG_A_DP_PORT=0x00; //消影
}
}
void holderscan()//抢答时间设置,0-60s
{
time_display(second);
scare_display(people);
if(~key_clear)//如果有键按下,改变抢答时间
{
while(~key_clear);
if(people)//如果抢答结果没有清空,抢答器重置
{
second=30;
people=0;
}
else if(second<60)
{
second++;
}
else
{
second=0;
}
}
}
void timer_init()
{
EA=1;
ET0=1;
TMOD=0x01;
TH0=0xd8;//设定10ms中断一次
TL0=0xef;
}
void main()
{
BEEP=0;
while(1)
{
do
{
holderscan();
}
while(key_begin);//开始前进行设置,若未按下开始键
while(~key_begin);//防抖
timer_init(); //中断初始化
TR0=1; //开始中断
beep_alarm(50);
do{
time_display(second);
scare_display(people);
people=key_matrix_flip_scan();
}
while((!people)&&(second));//运行直到抢答结束或者时间结束
TR0=0;
}
}
void timer0() interrupt 1
{
if(counter<100)
{
counter++;
if(counter==50)
{
}
}
else
{
counter=0;
second=second-1;
if(second==0)
{
while(1)
{
beep_alarm(5);
time_display(0);
delay_ms(1);
SMG_A_DP_PORT=0x00;
}
}
}
TH0=0xd8;//重新装载
TL0=0xef;
TR0=1;
}