单片机课程论文Word格式.docx
《单片机课程论文Word格式.docx》由会员分享,可在线阅读,更多相关《单片机课程论文Word格式.docx(24页珍藏版)》请在冰豆网上搜索。
(4)比赛时间结束时,能发出报警指令。
硬件电路设计
电路主要包括CPU部分、电源部分、按键部分、LED显示部分。
1、CPU部分
51单片机为单芯片微控制器,常见封装形式为40脚双列直插式塑料封装DIP—40,其引脚识别为:
正面面向用户,缺口向上,左上面第一脚为1脚,然后按逆时针方向依次为2~40脚。
通常第一脚有标志符号。
51单片机管脚图如图2所示。
AT89C51是一种带4K字节闪烁可编程可擦除只读存储器(FPEROM—FalshProgrammableandErasableReadOnlyMemory)的低电压,高性能CMOS8位微处理器,俗称单片机。
AT89C单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案.
图2单片机引脚图
2.管脚说明:
VCC:
供电电压。
GND:
接地。
P0口:
P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。
当P1口的管脚第一次写1时,被定义为高阻输入。
P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位.在FIASH编程时,P0口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。
P1口:
P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。
P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。
在FLASH编程和校验时,P1口作为第八位地址接收。
P2口:
P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入.并因此作为输入时,P2口的管脚被外部拉低,将输出电流。
这是由于内部上拉的缘故。
P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。
在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容.P2口在FLASH编程和校验时接收高八位地址信号和控制信号.
P3口:
P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流.当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。
作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。
P3口也可作为AT89C51的一些特殊功能口,如下表所示:
口管脚备选功能
P3。
0RXD(串行输入口)
1TXD(串行输出口)
P3.2/INT0(外部中断0)
P3.3/INT1(外部中断1)
4T0(记时器0外部输入)
5T1(记时器1外部输入)
6/WR(外部数据存储器写选通)
7/RD(外部数据存储器读选通)
P3口同时为闪烁编程和编程校验接收一些控制信号。
RST:
复位输入。
当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间.
ALE/PROG:
当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。
在FLASH编程期间,此引脚用于输入编程脉冲。
在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。
因此它可用作对外部输出的脉冲或用于定时目的。
然而要注意的是:
每当用作外部数据存储器时,将跳过一个ALE脉冲。
如想禁止ALE的输出可在SFR8EH地址上置0。
此时,ALE只有在执行MOVX,MOVC指令是ALE才起作用。
另外,该引脚被略微拉高.如果微处理器在外部执行状态ALE禁止,置位无效。
/PSEN:
外部程序存储器的选通信号.在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。
但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
/EA/VPP:
当/EA保持低电平时,则在此期间外部程序存储器(0000H—FFFFH),不管是否有内部程序存储器。
注意加密方式1时,/EA将内部锁定为RESET;
当/EA端保持高电平时,此间内部程序存储器。
在FLASH编程期间,此引脚也用于施加12V编程电源(VPP).
XTAL1:
反向振荡放大器的输入及内部时钟工作电路的输入。
XTAL2:
来自反向振荡器的输出.
3。
振荡器特性:
XTAL1和XTAL2分别为反向放大器的输入和输出。
该反向放大器可以配置为片内振荡器。
石晶振荡和陶瓷振荡均可采用。
如采用外部时钟源驱动器件,XTAL2应不接。
有余输入至内部时钟信号要通过一个二分频触发器,因此对外部时钟信号的脉宽无任何要求,但必须保证脉冲的高低电平要求的宽度。
单片机是一种微控制器,任何为控制器正常工作最基本的条件是要有正确的电源、时钟电路好复位信号,三者缺一不可。
单片机正常工作最基本条件是:
正确的电源、时钟信号、复位信号。
51系列单片机第40引脚接电源+5V,第20引脚接地。
电压过高或者过低均会引起单片机CPU部工作.单片机指令执行时在时钟脉冲控制下进行的,时钟脉冲信号是由单片机内部时钟电路及18脚、19脚外接晶振和电容组成的时钟电路产生的.时钟电路异常,也会引起单片机CPU部工作,可通过测量30脚(ALE)是否有时钟脉冲六分频信号输出来判断振荡电路是否起振。
复位电路时在CPU通电后,给复位端9脚(RST)一个复位脉冲,使CPU内部处于初始工作状态。
51系列单片机是高电平复位,在正确的复位后(工作状态)9脚应保持低电平。
如果复位电路出现故障,CPU也将无法工作。
由于CPU的复位电路只有在开机瞬间产生复位脉冲,周期一般为几毫秒,用万用表无法鉴别正常与否。
对于只有上电复位的复位电路,快速判断CPU是否有故障可以采取强制复位的方法,将复位瞬时接电源正端,如果此时CPU恢复工作,说明CPU的复位电路出现故障。
对于有按键复位的复位电路,按下复位键,测量复位端是否有高电平产生来判断复位电路工作是否正常.
图3CPU控制电路
2、电源部分
图4电源部分
4.按键部分
ADD1,DEC1,EXCHANGE,ADD2,DEC2,RUN/STOP
其中:
ADD1甲队比分加1键,(暂停时为调整时间分钟加1)
DEC1甲队比分减1键,(暂停时为调整时间分钟减1)
EXCHANGE换场键,半场休息时换场。
ADD2乙队比分加1键,(暂停时为调整时间秒钟加1)
DEC2乙队比分减1键,(暂停时为调整时间秒钟减1)
RUN/STOP启动暂停键,比赛开始时按下启动计时,比赛开始。
比赛开始后,按下为暂停计时,比赛暂停。
甲乙队比分默认000,此时按下ADD1键,可以对比赛时间分钟加1,
按下DEC1键,可以对比赛时间的分钟减1,按下ADD2键,
可以对比赛时间秒加1,按下DEC2键,可以对比赛时间秒减1.
图6按键部分
系统的总电路图
图7系统总电路图
在proteus下的仿真。
图7AT89C51单片机部分
图8排阻部分
图9蜂鸣器部分
图10按键部分
图11时间显示部分
图12比分显示部分
图13仿真全图
软件设计
代码
程序就是从主程序开始执行的,在主程序里可以调用子程序,调用完成后还要返回主程序继续执行。
我们在主程序里对各个模块进行初始化,用一个while循环不断地循环执行各个子程序,例如按键扫描程序在这里可以一次一次地扫描按键,这样实现简单易行.
延时子程序
此次程序中单独设立了一个带有参数传输的延时子程序,以供其他程序块的调用,且延时可以通过参数方便的控制,使程序更加的简洁。
:
中断服务子程序
当T0中断发生时转入执行中断服务子程序,本程序主要用于提供一个精确的时钟实现定时。
另外还用对数码管的循环扫描显示,每中断一次就对数码管进行扫描一次,从而提供一个稳定的显示输出,不受其他程序的延时影响。
数码管显示子程序
数码管显示采用动态显示方式,这样占用I/O口资源比较少,且易于实现。
在运行中可以随时修改显示分数及时间.
按键处理模块
按键识别及处理程序主要由键盘识别和键值处理组成。
其中键盘识别子程序不断地对键盘进行判断是否有键按下。
当有键按下时则转到相应按键进行相应处理,即可实现对甲、乙两队总分的计算与处理和对比赛时间的相应操作。
源程序代码
#include<
reg51.h〉
#defineLEDDataP0//定时数码管的段值从P0口输出
unsignedcharcodeLEDCode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//数码管0-—9的编码
unsignedcharminit,second,count,count1;
//分,秒,计数器
unsignedcharset_minit=12,set_second=0;
sbitadd1=P1^0;
//甲队加分,每按一次加1分/比赛前为时间加1分
sbitdec1=P1^1;
//甲队减分,每按一次减1分/比赛前为时间减1分
sbitexchange=P1^2;
//交换场地
sbitadd2=P1^3;
//乙队加分,每按一次加1分/比赛前为时间加1秒
sbitdec2=P1^4;
//乙队减分,每按一次减1分/比赛前为时间减1秒
sbitsecondpoint=P0^7;
//秒闪动点
//----数码管的位选控制脚,共有10位数码管--—-——
sbitled1=P2^7;
sbitled2=P2^6;
sbitled3=P2^5;
sbitled4=P2^4;
sbitled5=P2^3;
sbitled6=P2^2;
sbitled7=P2^1;
sbitled8=P2^0;
sbitled9=P3^7;
sbitled10=P3^6;
sbitalam=P1^7;
//报警
bitplayon=0;
//比赛进行标志位,为1时表示比赛开始,计时开启
bittimeover=0;
//比赛结束标志位,为1时表示比赛结束
bitAorB=0;
//甲乙队交换位置标志位
bithalfsecond=0;
//半秒标志位
unsignedintscoreA;
//甲队得分
unsignedintscoreB;
//乙队得分
//====================延时==================
voidDelay5ms(void)
{
unsignedinti;
for(i=100;
i〉0;
i—-);
}
voiddisplay(void)
{
//—---———-———显示时间(分钟)---———————-———
LEDData=LEDCode[minit/10];
//显示分钟的十位
led1=0;
//开启位选
Delay5ms();
//延时,以便足以点亮数码管.
led1=1;
//关闭位选
LEDData=LEDCode[minit%10];
//显示分钟的个位
led2=0;
led2=1;
//————-——---———秒点闪动-———-——————-
if(halfsecond==1)
LEDData=0x80;
else
LEDData=0x00;
led2=0;
Delay5ms();
led2=1;
secondpoint=0;
//—-——-—-—--—显示时间(秒钟)-—————---—--
LEDData=LEDCode[second/10];
//显示秒钟的十位
led3=0;
led3=1;
LEDData=LEDCode[second%10];
//显示秒钟的个位
led4=0;
led4=1;
//---——-----—显示1组的分数百位-—————-
if(AorB==0)
LEDData=LEDCode[scoreA/100];
LEDData=LEDCode[scoreB/100];
led5=0;
led5=1;
//-—--—-——---——--显示1组分数的十位—--————————
LEDData=LEDCode[(scoreA%100)/10];
LEDData=LEDCode[(scoreB%100)/10];
led6=0;
led6=1;
//—-----——-—————-显示1组分数的个位—--——-——-—-
LEDData=LEDCode[scoreA%10];
LEDData=LEDCode[scoreB%10];
led7=0;
led7=1;
//---—-—--———显示2组分数的百位——-——--
if(AorB==1)
LEDData=LEDCode[scoreA/100];
LEDData=LEDCode[scoreB/100];
led8=0;
led8=1;
//—--—----—-—显示2组分数的十位——-——--———-
LEDData=LEDCode[(scoreA%100)/10];
LEDData=LEDCode[(scoreB%100)/10];
led9=0;
led9=1;
//——---——————显示2组分数的个位————--———--
LEDData=LEDCode[scoreA%10];
LEDData=LEDCode[scoreB%10];
led10=0;
led10=1;
//====================按键检测程序================================================
voidkeyscan(void)
if(playon==0)//在比赛未开始的状态下
{
if(add1==0)//当add1按键按下时
{
display();
//调用显示,同时作为延时消抖
if(add1==0);
//延时消抖后,依然检查到按键按下
{
if(minit<
99)//当分钟小于99时,分钟加1
minit++;
else
minit=99;
//否则,分钟仍然为99,调整为99分钟
}
do//当按键未松开时,一直调用显示,防止数码管闪动,
display();
while(add1==0);
}
if(dec1==0)//当dec1键按下时,dec1的原理与add一样,
if(dec1==0);
if(minit〉0)
minit-—;
minit=0;
}
do
while(dec1==0);
if(add2==0)//调整秒,原理同上
{
if(add2==0);
{
if(second〈59)
second++;
second=59;
while(add2==0);
if(dec2==0)
if(dec2==0);
if(second>
0)
second—-;
second=0;
display();
while(dec2==0);
}
if(exchange==0)//换场键
display();
if(exchange==0);
TR1=0;
//关闭T1计数器
alam=1;
//关报警
AorB=~AorB;
//开启交换
minit=set_minit;
//并将时间预设为12:
00
second=0;
while(exchange==0);
}
}
else//比赛开始。
if(add1==0)//add1键按下
//调用显示,同时延时消抖
if(AorB==0)//当场地标志位=0时,
{
if(scoreA〈999)//当A方的比分小于999时,比分加1
scoreA++;
else
scoreA=999;
//否则最大值为999分
}
else//当场地标志位=1时,
{
if(scoreB<
999)//当B方的比分小于999时,比分加1
scoreB++;
scoreB=999;
//否则最在值为999分
}
while(add1==0);
if(dec1==0)//当dec1键按下时,原理与add1一样,比分减1
if(dec1==0);
if(AorB==0)
if(scoreA〉0)
scoreA-—;
scoreA=0;
if(scoreB〉0)
scoreB——;
scoreB=0;
while(dec1==0);
if(add2==0)//原理同上
if(add2==0);
if(AorB==1)
if(scoreA<
999)
scoreA=999;
scoreB=999;
while(add2==0);
if(dec2==0)
scoreA--;
scoreA=0;
if(scoreB>
scoreB-—;
while(de