电子技术应用综合课程设计
—51单片机八位抢答器
目录
第一章:内容提要„„„„„„„„„„„„„„„„„„„„„„„„„„4
1.1设计要求„„„„„„„„„„„„„„„„„„„„„„„„4
1.2总体设计方案„„„„„„„„„„„„„„„„„„„„„„5
第二章:硬件设计及分析„„„„„„„„„„„„„„„„„„„„„„„5
2.1单片机最小系统„„„„„„„„„„„„„„„„„„„„„5
2.2 LCD1602显示电路„„„„„„„„„„„„„„„„„„„„7
2.3独立式按键键盘设计„„„„„„„„„„„„„„„„„„„7
2.4蜂鸣器设计„„„„„„„„„„„„„„„„„„„„„„„8
2.5复位电路设计„„„„„„„„„„„„„„„„„„„„„„9
第三章:软件设计及分析„„„„„„„„„„„„„„„„„„„„„„„10
3.1系统程序„„„„„„„„„„„„„„„„„„„„„„„10
3.2程序流程图„„„„„„„„„„„„„„„„„„„„„„10
第四章:体会感想„„„„„„„„„„„„„„„„„„„„„„„„„„11
参考文献„„„„„„„„„„„„„„„„„„„„„„„„„„„„„12 附录„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„13
第一章:内容摘要
数字抢答器由主体电路与扩展电路组成。优先编码电路、锁存器、译码电路将参赛队的输入信号在显示器上输出;用控制电路和主持人开关启动报警电路,以上两部分组成主体电路。通过定时电路和译码电路将秒脉冲产生的信号在LCD602显示器上输出实现计时功能,构成扩展电路。经过布线、焊接、调试等工作后数字抢答器成形。单片机体积小价格低,应用方便,稳定可靠。单片机将很多任务交给了软件编程去实现,大大简化了外围硬件电路,使外围电路的实现简单方便。单片机系统的硬件结构给予了抢答系统“身躯”,而单片机的应用程序赋予了其新的“生命”,使其在传统的抢答器面前具有电路简单、成本低、运行可靠等特色。对于抢答器我们大家都知道那是用于选手做抢答题时用的,选手进行抢答,抢到题的选手来回答问题。抢答器不仅考验选手的反应速度同时也要求选手具备足够的知识面和一定的勇气。选手们都站在同一个起跑线上,体现了公平公正的原则。
关键字: 抢答电路 定时电路 报警电路
1 .1设计要求
以单片机为核心,设计一个8位竞赛抢答器:同时供8名选手或8个代表队比赛,分别用8个按钮S0~S7表示。
设置一个系统清除和抢答控制开关S,开关由主持人控制。
抢答器具有锁存与显示功能。即选手按按钮,锁存相应的编号,并在优先抢答选手的编号一直保持到主持人将系统清除为止。
抢答器具有定时抢答功能,且一次抢答的时间由主持人设定(如30秒)。 当主持人启动“开始”键后,定时器进行减计时,同时扬声器发出短暂的声响,声响持续的时间为0.5s左右。
参赛选手在设定的时间内进行抢答,抢答有效,定时器停止工作,显示器上显示选手的编号和抢答的时间,并保持到主持人将系统清除为止。
如果定时时间已到,无人抢答,本次抢答无效,系统报警并禁止抢答,定时显示器上显示00。
1 .2总体方案设计
图1.2 总体电路设计框图
独立式按键键盘:用于输入高低电平,连接到P1口,由P1口检测电平的变化。
抢答器倒计时显示电路:用LCD1602液晶显示,第一行显示成功抢答选手编号,第二行显示选手抢答用的时间和倒计时时间。
蜂鸣电路:有选手抢答成功,P2.0口发出脉冲,使蜂鸣器发出声音。
第二章:硬件设计及分析
2.1单片机最小系统
单片机选用的是Atmel公司推出的AT89S52,它是一种低功效、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。使用Atmel
公司高密度非易
失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。在单芯片上拥有灵巧的8位CPU和在线系统可编程Flash,使得AT89S52具有以下标准功能:8K字节Flash,256字节RAM,32位I/O口线,看门狗定时器,2个数据指针,三个16位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。空闲模式下,CPU停止工作,允许RAM、定时器/计数器串口、中断继续工作。掉电保护方式下RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。而且,它还具有一个看门狗(WDT)定时/计数器。如果程序没有正常工作,就会强制整个系统复位,还可以在程序陷入死循环的时候,让单片机复位而不用整个系统断电,从而保护你的硬件电路。T89S52有40个引脚,32个外部双向输入/输出(I/O)端口,同时内含2个外中端口,2个16位可编程定时计数器,2个全双工串行通信口,片上Flash允许程序存储器在系统可编程,亦适于常规编程器。其将通用的微处理器和Flash存储器结合在一起,特别是可反复擦写的Flash存储器可有效地降低开发成本。
图2.1 最小系统电路
2.2LCD显示电路
液晶显示器是一种功耗极低的被动式显示器件,1602广脚介绍:D0—D7数据传送引脚,VSS为接地线,VDD为电源线,VEE为 LCD驱动电压调节,由此可以调节显示亮度。RS为寄存器选择信号,高电平选择数据寄存器,低电平选择指令寄存器。RW为读写控制信号,高电平读,低电平写。EN使能信号,读状态下高电平有效,写状态下下降沿有效。
RS连接P2^0; 寄存器选择信号
RW连接P2^1; 读写控制信号线
EN连接P2^2; 使能信号线
图2.2 LCD1602电路
2.3独立式按键键盘设计
键盘接口中使用多少根I/O线,键盘中就有几个按键,键盘接口使用了8根I/O口线,该键盘就有8个按键,这种类型的键盘,其按键比较少,且键盘中各按键的工作互不干扰。因此可以根据实际需要对键盘中的按键灵活的编码。
最简单的编码方式就是根据I/O输入口所直接反映的相应按键,按下的状态进行编码,称按键直接状态码,对于这样编码的独立式键盘,CPU可以通过直接
读取I/O口的状态来获取按键的直接状态编码值,根据这个值直接进行按键识别,这样形式的键盘结构简单,按键识别容易。
独立式键盘的缺点是需要占用比较多的I/O口线,当单片机应用系统键盘中需要的按键比较少或I/O口线比较富余时,可以采用这样类型的键盘。
独立式按键键盘:用于输入高低电平,八位选手抢答时高低电平发生变化,如图所示。
图2.3 抢答按键电路
2.4蜂鸣器设计
我们知道,声音的频谱范围约在几十到几千赫兹,若能利用程序来控制单片机某个口线的“高”电平或低电平,则在该口线上就能产生一定频率的巨型波,接上喇叭就能发出一定频率的声音,若再利用延时程序控制“高”“低”电平的持续时间,就能改变输出频率,从而改变音调,使喇叭发出不同的声音。单片机通过内部定时器的操作实现交替变换的波形输出驱动扬声器发声,有选手抢答成功,使蜂鸣器发出声音,如图 所示。
图2.4 蜂鸣器电路
2.5复位电路设计
MCS-5l的复位输入引脚RST为MCS-51提供了初始化的手段,可以使程序从指定处开始执行,在MCS-5l的时钟电路工作后,只要RST引脚上出现超过两个机器周期以上的高电平时,即可产生复位的操作.只要RST保持高电平,则MCS-5l循环复位.只有当RST由高电平变低电平以后。MCS-51才从0000H地址开始执行程序。本系统采用按键复位方式的复位电路。
复位电路:当一轮进行完时,由主持人按下,下一轮倒计时开始,如图3.2所示。
图2.4 复位电路
第三章:软件设计及分析
3.1系统程序
分为主程序、lcd1602显示程序、按键扫描程序、初始化等程序。
当主持人启动“开始”键后,定时器进行减计时,同时扬声器发出短暂的声响,声响持续的时间为0.5s左右。
参赛选手在设定的时间内进行抢答,抢答有效,定时器停止工作,显示器上显示选手的编号和抢答的时间,并保持到主持人将系统清除为止。
如果定时时间已到,无人抢答,本次抢答无效,系统报警并禁止抢答,定时显示器上显示00。
按键复位再来一次执行下次程序
3.2程序流程图
第四章:体会感想
通过本次单片机课程设计,使我所学的知识能够得到实际的应用,过程中也发现自身所学的知识存在许多的不足和问题,当然同时也学到了不少宝贵的知识,提高了自己的动手实践能力。在整个设计过程中从设计方案确定,到具体的电路仿真,最后到总体电路的连接构建以及程序的编写烧制,特别是程序的编写要求对LCD1602的初始化操作,指令和数据的操作都非常熟悉。通过这次对数字钟的设计与制作 让我了解了设计电路的程序 也让我了解了关于数字钟的原理与设计理念 要设计一个电路总要先用仿真仿真成功之后才实际接线的。但是最后的成品却不一定与仿真时完全一样 因为 再实际接线中有着各种各样的条件制约着。而且 在仿真中无法成功的电路接法 在实际中因为芯片本身的特性而能够成功。所以 在设计时应考虑两者的差异 从中找出最适合的设计方法。在这次实习中遇到了许多问题,但通过向老师同学请教都得到了解决。通过这次课程设计,我知道了做任何事都要有一颗平常心,不要想着走捷径,要一步一个脚印才能取得最后成功,在此过程中更要注重自主学习,发挥自己的主管能动性。总之这次课程设计试一次很好的锻炼,让我有了全方位的提高,受益匪浅,为我以后的工作学习打下了很好的基础,而且积累了丰富的经验。
参考文献:
[1]张义和.例说51单片机[M].北京:人民邮电出版社,2010年
[2] 阎石编著 数字电子技术基础 (第五版) 北京高等教育出版社] 2006.1~550
[3] 蔡明文 冯先成主编 单片机课程设计 华中科技大学出版社 2007.3
[4]陈明萤 编著 8051单片机课程设计实训教材 清华大学出版社 2004
[5] 康华光 编著 模拟电子技术基础(第五版) 高等教育出版社 2006
[6 ]黄智伟 编著 全国大学生电子设计竞赛电路(第一版)航空航天大学出版社 2006.36
附录:
(1) 实物图:
(2) 元件清单
Lcd1602 一个
蜂鸣器 一个
三极管 一个
89c52单片机一个
Led 一个
按键 九个
10K电阻器 一个
最小系统板一个
(3)程序清单
#include
#include
sbit RS = P2^4; //定义端口
sbit RW = P2^5;
sbit EN = P2^6;
sbit s = P3^7;
sbit s0 = P1^0;
sbit s1 = P1^1;
sbit s2 = P1^2;
sbit s3 = P1^3;
sbit s4 = P1^4;
sbit s5 = P1^5;
sbit s6 = P1^6;
sbit s7 = P3^6;
sbit beep = P2^0;
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
unsigned char table[10] ={'0','1','2','3','4','5','6','7','8','9'};
unsigned char shu,key,count=0;
unsigned char flag=0;
unsigned char DATA,num;
/*------------------------------------------------
uS延时函数,含有输入参数 unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下 T=tx2+5 uS
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
mS延时函数,含有输入参数 unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned int t)
{
while(t--)
{
//大致延时1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{
while(LCD_Check_Busy()); //忙则等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;
}
/*------------------------------------------------
写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data)
{
while(LCD_Check_Busy()); //忙则等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
}
/*------------------------------------------------
清屏函数
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*------------------------------------------------
写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x); //表示第一行
}
else
{
LCD_Write_Com(0xC0 + x); //表示第二行
}
while (*s)
{
LCD_Write_Data( *s);
s ++;
}
}
/*------------------------------------------------
写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
/*------------------------------------------------
初始化函数
------------------------------------------------*/
void LCD_Init(void)
{
LCD_Write_Com(0x38); /*显示模式设置*/
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*显示关闭*/
LCD_Write_Com(0x01); /*显示清屏*/
LCD_Write_Com(0x06); /*显示光标移动设置*/
DelayMs(5);
LCD_Write_Com(0x0C); /*显示开及光标设置*/
}
/*------------------------------------------------
定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
unsigned char temp,temp1,i,j=2;
TH0=(65536-50000)/256;//重新赋值 50ms
TL0=(65536-50000)%256;
// beep=~beep;
// DelayMs(100);
i++;
if(i==20)
{ i=0;
DATA--;
if(DATA>0)
{ DelayMs(50);
temp=DATA/10;
temp1=DATA%10;
LCD_Write_Char(7,1,table[temp]);
LCD_Write_Char(8,1,table[temp1]);
}
else if(DATA==0)
{ P1=0xFF;
ET0=0;
DelayMs(50);
LCD_Write_Char(7,1,'0');
LCD_Write_Char(8,1,'0');
for(;j--;j>0)
{
beep=0;
DelayMs(500);
beep=1;
}
}
}
}
void beepon(void)
{
unsigned char i;
for(i=0;i
{
beep=0;
DelayMs(50);
beep=1;
}
}
unsigned char keyscan(void)
{
unsigned char scan1;
scan1=P1;
if(scan1!=0xff)
{
DelayMs(30);
if(scan1==P1)
{
switch(scan1)
{
case 0xff:
scan1 = 0;
break;
case 0xfe:
scan1 = 1;
break;
case 0xfd:
scan1 = 2;
break;
case 0xfb:
scan1 = 3;
break;
case 0xf7:
scan1 = 4;
break;
case 0xef:
scan1 = 5;
break;
case 0xdf:
scan1 = 6;
break;
case 0xbf:
scan1 = 7;
break;
case 0x7f:
break;
}
}
}
else
scan1=0;
return(scan1);
}
void display(void)
{ unsigned char a,b;
key=keyscan();
if(key!=0 & flag==0 )
{ET0=0; count++;
DelayMs(200);
LCD_Write_Char(10,0,table[key]);
flag=1;
a=(shu-DATA)/10;
b=(shu-DATA)%10;
LCD_Write_Char(7,1,table[a]);
LCD_Write_Char(8,1,table[b]);
}
}
void main(void)
{ unsigned char k;
unsigned a,b;
LCD_Init(); //初始化液晶
DelayMs(20); //延时有助于稳定
LCD_Clear(); //清屏
LCD_Write_String(0,1,"time");
LCD_Write_String(0,0,"xuanshou");
// Init_Timer0(); //定时器0初始化
while(count==0)
{
if(s0==0)
{ DelayMs(10);
if(s0==0)
{
while(count==1)
{
if(s==0)
{
DelayMs(10);
if(s==0)
{ while(!s);
count++;
}
}
if(s1==0)
{
DelayMs(10);
if(s1==0)
{
while(!s1);
{
DATA++;
shu=DATA;
if(DATA==31){DATA=0;count=0;}
a=DATA/10;
b=DATA%10;
LCD_Write_Char(7,1,table[a]);
LCD_Write_Char(8,1,table[b]);
}
}
}
}
while(count==2)
{
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TH0=(65536-50000)/256;//重新赋值 50ms
TL0=(65536-50000)%256;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关颡