资源描述
单片机课程设计8位抢答器
Civil Aviation University of China
单片机课程设计报告
单片机课程设计报告
课 题: 8位抢答器系统的设计
姓 名:
学 号:
专 业:
学 院:
基于STC89C52单片机的抢答器系统的设计
摘要:
随着科学技术的发展和普及,各种各样的竞赛越来越多,其中抢答器的作用也越来越重要。本文设计为以AT89C52单片机为核心的八路抢答器,采用了数字显示器直接指示,自动锁存显示结果,并自动复位的设计思想,它能根据不同的抢答输入信号,经过单片机的控制处理并产生与输入信号相对应的输出信号,最后通过LED数码管显示相应的路数。
本设计是以抢答为出发点。考虑到根据需要设定限时回答的功能,利用89C52单片机及外围接口实现的抢答系统,利用单片机的定时器/计数器定时和记数的原理,将软、硬件有机地结合起来,使得系统能够正确地进行计时,同时使数码管能够正确地显示时间。用开关做键盘输入,蜂鸣器发声提示。
关键词:抢答器 单片机 LED 数码显示管 定时器/计数器
目 录
1. 概述…………………………………………………………………………1
1.1 课程设计的任务………………………………………………………1
1.2 课程设计的要求……………………………………………………………1
1.3 课程设计的意义……………………………………………………………1
2. 系统总体方案及硬件设计………………………………………………………2
2.1 设计任务分析………………………………………………………………2
2.2 设计方案……………………………………………………………………2
2.2.1 原理框图………………………………………………………………2
2.2.2 各功能模块介绍…………………………………………………………2
2.3 电路设计……………………………………………………………………7
2.3.1 硬件选型…………………………………………………………………7
2.3.2 功能模块电路设计………………………………………………………7
3. 软件设计………………………………………………………………………10
3.1系统分析……………………………………………………………………10
3.2参数计算……………………………………………………………………11
3.3程序设计……………………………………………………………………11
4.实验仿真………………………………………………………………12
5.课程设计体会………………………………………………………………14
6.参考文献…………………………………………………………………14
附件一………………………………………………………………………………15
附件二………………………………………………………………………………25
1.概述
1.1 课程设计的任务
结合所学单片机原理及接口技术,利用STC89C52单片机设计一个8位选手参加竞赛的抢答器。
1.2 课程设计的要求
基本要求:
(1)设置一个由主持人控制的系统清除和抢答控制开关。
(2)具有锁存和显示优先抢答选手的编号功能,并一直保持到主持人将系统清除为止。
扩展要求:
(1)抢答器具有定时抢答功能.当主持人启动“开始”键后,定时器进行减计时,参赛选手在设定的时间内进行抢答,抢答有效,定时器停止工作,显示抢答的时间,并保持到主持人将系统清除为止。如果定时时间已到,无人抢答,本次抢答无效,系统报警并禁止抢答,显示器上显示00。
(2)主持人可以设定抢答时间(如30秒)。
(3)参赛选手抢到答题权时,扬声器发出短暂的声响,声响持续的时间为10秒左右。
1.3课程设计的意义
为期两周的课程设计,首先,让同学们对本学期的《单片机原理及接口技术》课本知识记忆更牢固,也便于理解课上未能懂得的知识;其次,此次课程设计能够锻炼同学们的动手能力,从任务分析到设计电路,都是自我锻炼的机会;然后,同学间相互讨论能够锻炼合作能力最后能让同学熟悉单片机仿真软件Proteus,单片机开发环境Keil的应用;增进对单片机的感性认识,加深对单片机理论方面的理解;使学生了解和掌握单片机应用系统的软硬件设计过程、方法及实现,为后设计和实现单片机应用系统打下良好基础。
2. 系统总体方案及硬件设计
2.1 设计任务分析
设计要求利用单片机完成一个8位抢答器。需要用到4位共阳极数码管显示倒计时秒数和抢答成功的选手编号。所以。单片机程序中首先要有8位按键输入模块,还要有数字显示模块,利用外部中断进行调整强大时间,利用定时器模块进行倒计时和蜂鸣器响应时间的设置。同时要设置开始抢答和抢答重置的按键输入。电路中需要用到外部晶振,利用锁存器达到任务中显示锁存的要求。
2.2 设计方案
2.2.1原理框图
图1 设计原理框图
2.2.2 各功能模块介绍
(1)定时器中断0\1服务处理
定时器1用于响铃程序,定时器0用于计时程序。倒计时期间当有选手第一个按下抢答器按扭时数码管显示选手号码,开始倒计时,并锁定抢答。抢答完成后,蜂鸣器响十秒。无人抢答,倒计时结束后,蜂鸣器响十秒。
(2)外部中断0\1服务处理
外部中断0用于对抢答时间进行加处理,外部中断1用于对抢答时间进行减处理。
(3)外部晶振
外部晶振为单片机提供时钟信号,还作为定时器的计数信号,使用单片机的定时器要考虑晶振的数值。此次课程设计中,使用的是11.059MHz的外部晶振。
(4)单片机复位
当单片机系统在运行中,受到环境干扰出现程序跑飞的时候,按下复位按钮内部的程序自动从头开始执行。
(5)8位抢答按键
1-8号按键,都能进行抢答,抢答后相连接的管脚输入低电平,单片机结束倒计时,同时其他按键不能再抢答,数码管显示选手号,并保留剩余抢答时间。
(6)抢答开始、复位按键
两个按键分别完成抢答开始、抢答复位功能,抢答开始后选手方能进行抢答,若无选手抢答,倒计时继续进行。抢答复位功能只能在倒计时结束时进行,复位后,抢答时间恢复设定值。
(7)LED数码管显示模块
图2 4位LED数码管
led数码管常用段数一般为7段有的另加一个小数点,还有一种是类似于3位“+1”型。位数有半位,1,2,3,4,5,6,8,10位等等....,led数码管根据LED的接法不同分为共阴和共阳两类,了解LED的这些特性,对编程是很重要的,因为不同类型的数码管,除了它们的硬件电路有差异外,编程方法也是不同的。图2是共阴和共阳极数码管的内部电路,它们的发光原理是一样的,只是它们的电源极性不同而已。颜色有红,绿,蓝,黄等几种。led数码管广泛用于仪表,时钟,车站,家电等场合。选用时要注意产品尺寸颜色,功耗,亮度,波长等。
透过分时轮流控制各个LED数码管的COM端,就使各个数码管轮流受控显示,这就是动态驱动。每位元数码管的点亮时间为1~2ms,由于人的视觉暂留现象及发光二极体的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示资料,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的I/O口,而且功耗更低。
4位LED动态显示电路只需一个8位I/O口及一个4位I/O口,其中8个I/O控制段选码,4位I/O控制位选。进行4位字符显示时,采用扫描显示方式,即在每一瞬间只使某一位显示相应字符,在此瞬间,段选控制I/O口输出相应字符段选码,位选控制I/O口在该显示位送入选通电平(共阴极送低电平,共阳极送高电平),以保证该位显示相应字符。如此轮流,使每位显示该位应显示字符,并保持延迟一段时间(1~5ms),以造成视觉暂留效果。不断循环送出相应的段选码、位选码,就可以获得视觉稳定的显示状态。
图3 74HC373锁存器
74HC373为三态输出的八D锁存器,当三态允许控制端 OE 为低电平时,Q0~Q7为正常逻辑状态,可用来驱动负载或总线。当 OE 为高电平时,Q0~Q7 呈高阻态,即不驱动总线,也不为总线的负载,但锁存器内部的逻辑操作不受影响。
(8)抢答时间调整按键
利用两个外部中断管脚,连接两个按键,分别实现对抢答时间进行加处理,对抢答时间进行减处理。
(9) STC89C52RC单片机
图4 STC89C52RC单片机引脚图
STC89C52RC的特点
STC89C52RC有很宽的工作电源电压,可为2.7~6V,当工作在3V时,电流相当于6V工作时的1/4。STC89C52RC工作于12Hz时,动态电流为5.5mA,空闲态为1mA,掉电状态仅为20nA。这样小的功耗很适合于电池供电的小型控制系统。
STC89C52RC具有以下几个特点:
STC89C52RC与MCS-51系列的单片机在指令系统和引脚上完全兼容;
片内有4k字节在线可重复编程快擦写程序存储器;
全静态工作,工作范围:0Hz~24MHz;
三级程序存储器加密;
128×8位内部RAM;
32位双向输入输出线;
两个十六位定时器/计数器
五个中断源,两级中断优先级;
一个全双工的异步串行口;
间歇和掉电两种工作方式
超强抗干扰: 高抗静电(ESD保护) ,轻松过 2KV/4KV快速脉冲干扰;
宽电压,不怕电源抖动 ;
宽温度范围,-40℃~85℃ ;
禁止ALE输出;;
超低功耗:
1.掉电模式:典型功耗<0.1 μ A ;
2.空闲模式:典型功耗2mA ;
3.正常工作模式:典型功耗4mA-7mA ;
4.掉电模式可由外部中断唤醒,适用于电池供电系统,如水表、气表、便携设备等.;
STC89C52RC引脚功能
1电源:
①VCC - 芯片电源,接+5V;
②VSS - 接地端;
2.时钟:
XTAL1、XTAL2 - 晶体振荡电路反相输入端和输出端。
3.控制线:
控制线共有4根:
ALE/PROG:地址锁存允许/片内EPROM编程脉冲
① ALE功能:用来锁存P0口送出的低8位地址
② PROG功能:片内有EPROM的芯片,在EPROM编程期间,此引脚输入编程脉冲。
PSEN:外ROM读选通信号。
RST/VPD:复位/备用电源。
① RST(Reset)功能:复位信号输入端。
② VPD功能:在Vcc掉电情况下,接备用电源。
EA/Vpp:内外ROM选择/片内EPROM编程电源。
① EA功能:内外ROM选择端。
② Vpp功能:片内有EPROM的芯片,在EPROM编程期间,施加编程电源Vpp。
4. I/O口线:P0、P1、P2、P3共四个八位口。
P0口是三态双向口,通称数据总线口,因为只有该口能直接用于对外部存储器的读/写操作。P0口也用以输出外部存储器的低8位地图1址。由于是分时输出,故应在外部加锁存器将此地址数据锁存,地址锁存,信号用ALE。
P1口是专门供用户使用的I/O口,是准双向口。
P2口是从系统扩展时作高8位地址线用。不扩展外部存储器时,P2口也可以作为用户I/O口线使用,P2口也是准双向口。
P3口是双功能口,该口的每一位均可独立地定义为第一I/O功能或第二I/O功能。作为第一功能使用时操作同P1口。
2.3 电路设计
2.3.1 硬件选型
单片机:STC89C52RC
锁存器:74HC373
数码管:4位LED数码管
2.3.2 功能模块电路设计
(1)外部晶振电路
图5 外部晶振
(2)LED数码管显示电路
图6 LED数码管显示电路
(3)8位抢答按键电路
图7 8位抢答按键电路
(4)主持人控制部分(蜂鸣器、抢答开始、抢答复位、抢答时间调整按键)电路
图8 主持人控制部分
3. 软件设计
3.1系统分析
本次课程设计,主要由Keil和Proteus两个软件来完成程序编写和电路仿真。其中Keil用于程序的编写,而后生成可供单片机使用的.hex文件。Proteus用于搭建仿真电路,然后再单片机中下载Keil生成的.hex文件,进行仿真。
程序一共分为宏定义、定时器中断函数、外部中断函数、按键扫描函数、LED显示函数、延时函数、抢答开始函数、抢答复位函数和主函数9个部分。
系统流程图如下:
图9 系统流程图
3.2 参数计算
蜂鸣器10秒定时器初值计算
晶振12Mhz,则定时50000微妙,循环200次
T1=2^16-50000
3.3程序设计
(1)主程序
在该程序中首先完成定时器,中断,LCD的初始化,然后进入无限循环中,调用所有子函数,不断输出数据。
(2)蜂鸣器报警子程序
该程序包含了蜂鸣器开启子程序,以及用于控制蜂鸣器30秒鸣叫的定时器中断子程序。在开启子程序中判断温度数据的大小,控制定时器和蜂鸣器开关变量的赋值。定时器中断子程序中,定时器进入一次中断设置为0.05秒。则设置变量,计数600次,满30秒后关断蜂鸣器。
(3) 定时器中断子程序
该程序定时器用来控制抢答时间的按秒减少和蜂鸣器10秒报警。先设置初值,利用循环控制时间的减少。
(4) 外部中断子程序
该程序控制抢答时间初值的改变,每次中断将抢答时间初值加一或者减一。
(5) 按键扫描子程序
该程序利用P1口为抢答按键输入口,每次抢答开始,第一个按下按键的人能够实现抢答,其他按键失效无法抢答。
(6) 抢答开始子程序
该程序控制抢答开始。
(7) 抢答复位子程序
该程序控制抢答复位,只有完成抢答或者抢答时间为零后才能实现抢答复位。
(8) LED显示子程序
该程序用P0口为LED数码管的段码输入端,P2^0、P2^1、P2^2、P2^3为LED数码管位码输入端,持续扫描端口输入,形成视觉暂留,则可看做持续显示。
4.实验仿真
本次仿真用了Proteus软件,Proteus的ISIS是一款Labcenter出品的电路分析实物仿真系统,可仿真各种电路和IC,并支持单片机,元件库齐全,使用方便,是不可多得的专业的单片机软件仿真系统。
程序编译用Keil软件, Keil C51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。在开发大型软件时更能体现高级语言的优势。
运用keil软件编译C语言程序,其结果如下图所示,在结果栏显示—0 Error(s),0 warning(s).说明此程序在软件编译上无语法等错误。将此程序生成.hex文件调入硬件中用Proteus进行调试仿真。
图10 keil程序仿真结果
将生成的.hex文件调入Proteus电路图的单片机中,点击图左下角的开始键运行,程序的开始界面如图所示。
图11 Proteus程序仿真结果
图12 Proteus程序仿真结果
5. 课程设计体会
通过本次的课程设计,我学到了很多东西,同时在做的过程中也发现很多的问题。在这一过程中,我对我们所学习的相关单片机的知识又有了更深一层的学习和理解,让我对自己所学的又有了更深的掌握。虽然以前还做过这样的设计但这次设计真的让我长进了很多,单片机课程设计重点就在于软件算法的设计,需要有很巧妙的程序算法,虽然以前写过几次程序,但我觉的写好一个程序并不是一件简单的事。有好多的东西,只有我们去试着做了,才能真正的掌握,只学习理论有些东西而不结合实践是很难理解的,更谈不上掌握。
我相信,这些经验将会给我以后的工作和学习带来很大的帮助。
6. 参考文献
李朝青 刘艳玲.单片机原理及接口技术.北京航空航天大学出版社2013年7月第4版.
附件一:
(源程序代码)
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
#define KEY P1
/*-----------------
共阳极数码管编码表0-f
------------------*/
uchar code table[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,
0X80,0X90,0X88,0X83,0XC6,0XA1,0X86,0X8E,};
/*-------------
变量定义
-------------*/
sbit start_stop=P3^6;
sbit reset=P3^7;
sbit key1=P1^0;
sbit key2=P1^1;
sbit key3=P1^2;
sbit key4=P1^3;
sbit key5=P1^4;
sbit key6=P1^5;
sbit key7=P1^6;
sbit key8=P1^7;
sbit state=P3^4;
sbit kaishi=P3^1;
sbit speaker=P2^7;
bit start_stop_flag=0;
bit key1_flag=0;
bit key2_flag=0;
bit key3_flag=0;
bit key4_flag=0;
bit key5_flag=0;
bit key6_flag=0;
bit key7_flag=0;
bit key8_flag=0;
bit reset_flag=0;
bit action=0;
bit kaishi_flag=0;
bit speaker_flag=0;
bit tf=0;
uchar timer1_count=0;
uchar second=30;
uchar timer0_count=0;
uchar number=0;
uchar number_display=0;
uchar second1=30;
uchar b=10;
/*-----------------------------
延时函数
------------------------------*/
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*-------------------------------
数码管显示驱动函数
-------------------------------*/
void display(uchar number,uchar second)
{
uchar second_first,second_second;
second_first=second/10;
second_second=second%10;
P2=0x01;
P0=table[number];
delay(2);
P2=0x02;
P0=0xBF;
delay(2);
P2=0x04;
P0=table[second_first];
delay(2);
P2=0x08;
P0=table[second_second];
delay(2);
}
/*-------------------------------------
开始键扫描函数
-------------------------------------*/
void start_stop_keyscan()
{
if(start_stop==0)
{
delay(8);
if((start_stop==0)&&(!start_stop_flag))
{
start_stop_flag=1;
action=1;
TR0=1;
TR1=1;
state=0;
}
}
else
{
start_stop_flag=0;
}
}
/*--------------------------------------
八位抢答键扫描函数
--------------------------------------*/
uchar key_scan8()
{
if(key1==0)
{
delay(8);
if((key1==0)&&(!key1_flag))
{
key1_flag=1;
number=1;
number_display=number;
}
}
else
{
key1_flag=0;
number=0;
}
//////////////////////////////////////////
if(key2==0)
{
delay(8);
if((key2==0)&&(!key2_flag))
{
key2_flag=1;
number=2;
number_display=number;
}
}
else
{
key2_flag=0;
number=0;
}
//////////////////////////////////////////////
if(key3==0)
{
delay(8);
if((key3==0)&&(!key3_flag))
{
key3_flag=1;
number=3;
number_display=number;
}
}
else
{
key3_flag=0;
number=0;
}
///////////////////////////////////////////////
if(key4==0)
{
delay(8);
if((key4==0)&&(!key4_flag))
{
key4_flag=1;
number=4;
number_display=number;
}
}
else
{
key4_flag=0;
number=0;
}
////////////////////////////////////////////////
if(key5==0)
{
delay(8);
if((key5==0)&&(!key5_flag))
{
key5_flag=1;
number=5;
number_display=number;
}
}
else
{
key5_flag=0;
number=0;
}
/////////////////////////////////////////////////
if(key6==0)
{
delay(8);
if((key6==0)&&(!key6_flag))
{
key6_flag=1;
number=6;
number_display=number;
}
}
else
{
key6_flag=0;
number=0;
}
/////////////////////////////////////////////////////
if(key7==0)
{
delay(8);
if((key7==0)&&(!key7_flag))
{
key7_flag=1;
number=7;
number_display=number;
}
}
else
{
key7_flag=0;
number=0;
}
////////////////////////////////////////////////////////
if(key8==0)
{
delay(8);
if((key8==0)&&(!key8_flag))
{
key8_flag=1;
number=8;
number_display=number;
}
}
else
{
key8_flag=0;
number=0;
}
if(number_display!=0)
{
return 1;
}
else
{
return 0;
}
}
/*---------------------------------
抢答时间调整函数
--------------------------------*/
void INT0_SVR() interrupt 0
{
delay(8);
second1++;
second=second1;
display(number_display,second);
}
void INT1_SVR1() interrupt 2
{delay(8);
second1--;
second=second1;
display(number_display,second);
}
/*-----------------------------------
复位键扫描函数
-----------------------------------*/
void reset_keyscan()
{
if(reset==0)
{
delay(8);
if((reset==0)&&(!reset_flag))
{ b=10;
second=second1;
reset_flag=1;
number_display=0;
state=1;
}
}
else
{
reset_flag=0;
}
}
/*----------------------------------------
主函数
----------------------------------------*/
void main()
{
TMOD=0X11;
TH0=0X3C;
TL0=0XB0;
EA=1;
ET0=1;
TR0=0;
ET1=1;
TR1=1;
EX0=1;
IT0=1;
EX1=1;
IT1=1;
speaker=0;
while(1)
{
while((kaishi==0)&&(!kaishi_flag))
{
start_stop_keyscan();
reset_keyscan();
while(action)
{
while(!key_scan8())
{
display(number_display,second);
if(second==0)
{
second=0;
break;
}
}
TR0=0;
display(number_display,second);
action=0;
break;
}
display(number_display,second);
}
}
}
/*-------------------------------
中断服务函数
------------------------------*/
void timer0() interrupt 1
{
TH0=0x3c;
TL0=0xb0;
timer0_count ++;
if(timer0_count ==20)
{
timer0_count =0;
second --;
if(second==0)
{
TR0=0;
number_display=0;
state=1;
action =0;
}
}
}
void xtime(uchar timer)
{
uint i=0;
uchar j=0;
for(i=60;i>0;i--)
{
speaker=~speaker;
for(j=timer;j>0;j--);
display(number_display,second);
}
speaker=0;
}
void timer1() interrupt 3
{
TH1=0x3c;
TL1=0xb0;
timer1_count++ ;
if(timer1_count==20)
{
timer1_count=0;
if(KEY!=0xff)
{;
tf = 1; }
if(tf){
delay(8);
if(b--){
xtime(200);
}
}
if(second==0){
if(b--){
xtime(200);
}
}
if(b==0){
TR1=0;
tf = 0;
state=1;
action =0;
}
}
}
附录二:
(系统原理图)
展开阅读全文