单片机实习报告.docx
《单片机实习报告.docx》由会员分享,可在线阅读,更多相关《单片机实习报告.docx(33页珍藏版)》请在冰点文库上搜索。
单片机实习报告
实习内容
本系统共采用两个模块。
两者主要采用单片机AT89C52作为本设计的核心元件。
24秒计时显示系统利用7段共阴LED作为显示器件。
在此设计中共接入了2个7段共阴LED显示器,其中1个用于显示十位时间数,另一个用来显示个位时间数。
同时通过按键控制计数器的直接清零、启动和暂停功能,同时发出光电报警信号。
另一个系统就是计分和每节计时。
该系统利用10个共阳极数码管。
其中四个用于每小节的时间,4个LED显示器则用来记录赛程时间,其中2个用于显示分钟,2个用于显示秒钟。
三个用于显示甲队的分数,另外三个用于显示乙队的分数。
每队3个LED显示器显示围可达到0~999分,足够满足赛程需要。
另外,赛程计时采用倒计时方式。
即比赛前将时间设置好,比赛开始时启动计时,直至计时到零为止。
计时范围可达到0~99分钟,也完全满足实际赛程的需要。
其次,为了配合计时器和计分器校正调整时间和比分,本设计中设立了6个按键,其中1个用于设置交换场地,启动和暂停、设时等。
设计可以满足以下要求。
1、能记录整个赛程的比赛时间,并能修改比赛时间。
2、能随时刷新甲、乙两队在整个过程中的比分。
3、中场交换比赛场地时,能交换甲、乙两队比分的位置。
4、比赛结束时,能发出报警声。
5、比赛开始,进行24秒计时。
实习系统总体方案
模块
(一)
1硬件设计
1.1设计原理
24秒计时器的总体参考方案框图如图2.1所示,它包括秒脉冲发生器、计数器、译码显示电路、报警电路和辅助时序控制电路等五个模块组成。
其中计数器和控制电路是系统的主要模块。
计数器完成24秒计时功能,而控制电路完成计数器的直接清零、启动技术、暂停/连续计数、译码显示电路的显示与灭灯、定时时间到报警等功能。
外部操
作开关
1.2硬件电路图设计:
根据设计要求,要求设置外部操作开关,控制计数器的直接清零、启动和暂停。
所以,硬件设计框图包括AT89C51芯片、显示器、报警和按键四大模块。
此计时器采用的设计采用模块化的结构,主要由以上几个部分组成,即计时模块、控制模块以及译码显示模块。
在设计此计时模块时,采用模块化的设计思想,使设计起来更加简单、方便、快捷。
一个完整的计算机应该由运算器、控制器、存储器和I/O接口组成。
运算器包括一个可进行8位算术运算和逻辑运算的单元ALU,8位的暂存器1、暂存器2,8位的累加器ACC,寄存器B和程序状态寄存器PSW等。
控制器包括程序计数器PC、指令寄存器IR、指令寄存器ID、振荡器及定时电路等。
存储器分为程序存储器(FlashROM)和数据存储器(RAM)。
另外,89C51有4个与外部交换信息的8位并行接口,即P0至P3。
它们都是准双向端口,每个端口各有8个I/O线,均可输入输出。
此外,AT89C51设有稳态逻辑,可以在低到零频率的条件下静态逻辑,支持两种软件可选的掉电模式。
在闲置模式下,CPU停止工作。
但RAM,定时器,计数器,串口和中断系统仍在工作。
在掉电模式下,保存RAM的内容并且冻结振荡器,禁止所用其他芯片功能,直到下一个硬件复位为止。
1.3功能单元模块
1.3.1光电报警器
报警探测器是由传感器和信号处理组成的,用来探测信号的,由电子和机械部件组成的装置,是报警系统的关键,而传感器又是报警探测器的核心元件。
采用不同原理的传感器件,可以构成不同种类、不同用途、达到不同探测目的的报警探测装置。
报警探测器的灵敏度和可靠性是相互影响的。
在设计中,用到的是实验室的光电报警器。
光电报警器的驱动器的输入端接AT89C51的P1.0,当P1.0输出高电平时,会产生光电,实现报警。
图2报警模块
1.3.2LED显示器
单片机中通常用7段LED构成字型“8”,另外,还有一个小数点发光二极管,以显示数字、符号及小数点。
这种显示器有共阴极和共阳极两种,此课程设计采用的是共阴极。
发光二极管的阳极连在一起的称为共阳极显示器,阴极连在一起的称为共阴极显示器。
一位显示器由8个发光二极管组成,其中,7个二极管构成字型“8”的各个笔画a~g,
图3数码管显示器
1.3.3控制模块
此模块控制显示管的显示,并通过控制按钮来操纵时间的启停、复位与开始。
图4按键控制模块
2软件设计
2.1程序流程图
根据设计要求,可分析并设计图3.2.1程序流程图,采用24秒倒计时,所以复位值为24秒,倒计时到0时,LED显示为00,开始判断,并报警。
开关A1控制复位,A2控制暂停,A3控制启动。
篮球计时器24秒倒计时的程序流图如下
图5主程序流程图
2.2程序设计
根据以上流程图,可以用汇编语言编写出篮球计时器24秒倒计时程序,该程序包括主程序,中断程序,延时程序以及显示程序。
ORG0000H
SJMPMAIN
ORG000BH
LJMPT0_ISR
ORG0030H
MAIN:
MOVP0,#3FH;初始化赋值
MOVP1,#0FFH
MOVP2,#3FH
MOVR0,#00H
MOVR1,#24
MOVDPTR,#TAB
KEY:
JBP3.0,$;判断启动键是否按下
ACALLDELAY30MS
JNBP3.0,$
ACALLSTART
SJMPKEY;
START:
MOVTMOD,#01H;启动程序
MOVTH0,#0D8H
MOVTL0,#0EFH
SETBET0
SETBEA
SETBTR0
STOP:
JBP3.2,ZTJX;判断复位键是否程序
ACALLDELAY30MS
JNBP3.2,$
SJMPMAIN;复位程序
ZTJX:
JBP3.1,XS;判断暂停键是否按下
ACALLDELAY30MS
JNBP3.1,$
ZT:
CLRTR0;K2按下后暂停计数,并关中断
CLRET0
CLREA
JBP3.1,$;K2再次按下继续计数
ACALLDELAY30MS
JNBP3.1,$
JX:
SETBET0;第二次按下暂停键后继续倒计时(继续启动)
SETBEA
SETBTR0
XS:
MOVA,R1;显示子程序
MOVB,#10
DIVAB
MOVCA,@A+DPTR
MOVP0,A;显示秒十位
MOVA,B
MOVCA,@A+DPTR
MOVP2,A;显示秒个位
CJNER0,#100,STOP;1S时间到否,未到直接转数码管显示
MOVR0,#00H;1S时间到,R0重赋初值
MOVA,R1;R1减1,不为0转数码管显示,为0则重新开始
CLRC
SUBBA,#1
MOVR1,A
JNCSTOP;计数未到0继续判断暂停键和停止键
MOVR1,#24;计数到0停止计数并关中断,
CLRET0
CLREA
CLRTR0
SJMPSND;跳到报警程序
SJMPKEY;跳回开始检测启动键
RET
DELAY30MS:
MOVR6,#150;延时程序子程序
AAA:
MOVR7,#100
DJNZR7,$
DJNZR6,AAA
RET
T0_ISR:
CLRTR0;中断程序子程序
MOVTH0,#0D8H
MOVTL0,#0EFH
INCR0
SETBTR0
RETI
SND:
CLRP1.0;报警程序子程序(红色发光二极管亮一下就灭)
MOVR7,#0FFH
DL:
MOVR6,#0FFH
DL1:
DJNZR6,DL1
DJNZR7,DL
SETBP1.0
RET
TAB:
DB3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
END
2.3仿真及仿真结果
通过在Protues中仿真,按下复位键(开启键),显示器显示24,然后自动显示23、22…,当计时到21秒时,按下暂停,显示器锁定在21,当再按启动键时,又开始倒计时,直到显示00,开始报警,按下复位键,又回到了24。
图为
图6仿真图
模块
(二)
3硬件设计
3.1设计原理
此记分器的设计采用模块化结构,主要由以下2个组成,即键盘模块、以及译码显示模块。
以单片机为核心,配以一定的外围电路和软件,以实现比赛计分器的功能。
它由硬件部分和软件部分组成。
矩
形
键
盘
89C51
甲显示器
乙显示器
图7硬件电路设计方框图
3.2功能单元模块
3.2.1键盘控制电路
在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式。
在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。
这样,一个端口(如P1口)就可以构成4*4=16个按键,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。
图8矩阵键盘与80C52的接口电路
3.2.2显示电路
显示器采用三个四位共阳极LED显示器,来实现显示器的动态扫描,八个二极管连接一个阴极的结构,只要另一段为高电平,二极管就会发光,从而形成一段。
将八段顺序排列后就成为具有一定编码的共阴显示器了。
动态扫描的频率有一定的要求,频率太低,LED将出现闪烁现象。
如频率太高,由于每个LED点亮的时间太短,LED的亮度太低,肉眼无法看清,所以一般均取几个ms左右为宜,这就要求在编写程序时,选通某一位LED使其点亮并保持一定的时间,程序上常采用的是调用延时子程序。
显示电路如图3-3所示。
图9显示电路图
4软件设计
4.1主程序设计
主程序主要由系统初始化段、开中断、键盘识别、键值处理、两个4位共阴极LED显示器扫描显示子程序和中断处理子程序等组成。
通过对以上各段和子程序的结合,以实现系统功能。
该系统主程序流程图如下图所示。
开始
始初化
图10主程序流程图
4.2键盘识别及处理程序设计
按键识别及处理程序主要由键盘识别和键值处理组成。
其中键盘识别子程序不断地对键盘进行判断是否有键按下。
当有键按下时则转到键码处理即甲、乙总分处理子程序对相应按键进行相应处理,即可实现对甲、乙两队总分的计算与处理。
键盘识别即依次判断第一列、第二列、第三列、第四列是否有键按下。
如果有键按下,先得出列,再反向赋值得出行,最后得出所在行和列的位置。
键值处理即先定义0~9这九个按键,再对三次按键值进行保存,再来判断是甲队还是乙队加减分,再判断是加还是减,最后判断加或减多少分,实现分别给甲、乙总分进行加分和减分。
键值处理即甲、乙总分处理子程序流程图如11
图11键值处理子程序流程图
4.3显示子程序设计
由于该系统使用的是8位LED显示器显示计分器比分,因此显示采用动态扫描显示方法,即由显示器扫描显示子程序控制显示器逐个循环从左至右依次点亮各个显示器。
这样虽然在任一时刻只要一个显示器点亮,但是由于人眼具有视觉残留效应,看起来与全部显示器持续点亮效果一样。
如下图12
图12显示子程序流程图
4.4复位程序设计
按钮与单片机P0.6/AD6引脚相连,当每次按下该按钮后,系统将通过软件实现对计分复位功能。
在主程序运行过程中,只要系统识别到与单片机P0.6/AD6引脚相连的按键按下,程序则会转去执行复位程序,完成对甲、乙总分寄存单元的清零,显示器各位的显示数寄存单元的复位,执行完毕后,返回主程序。
流程图如4-4所示。
图13复位程序流程图
程序如下:
#include
#defineLEDDataP0
unsignedcharcodeLEDCode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
unsignedcharminit,second,count,count1;//分,秒,计数器
sbitadd1=P1^0;//甲对加分,每按一次加1分/在未开始比赛时为加时间分
sbitdec1=P1^1;//甲对减分,每按一次减1分/在未开始比赛时为减时间分
sbitadd2=P1^3;//乙对加分,每按一次加1分/在未开始比赛时为加时间秒
sbitdec2=P1^4;//乙对减分,每按一次减1分/在未开始比赛时为减时间秒
sbitsecondpoint=P0^7;//秒闪动点
//----依次点亮数码管的位------
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;//乙队得分
voidDelay10ms(void)
{
unsignedinti;
for(i=500;i>0;i--);
}
voiddisplay(void)
{
//-----------显示时间分--------------
LEDData=~LEDCode[minit/10];
led1=1;
Delay10ms();
led1=0;
LEDData=~LEDCode[minit%10];
led2=1;
Delay10ms();
led2=0;
//-------------秒点闪动------------
if(halfsecond==1)
LEDData=0x7f;
else
LEDData=0xff;
led2=1;
Delay10ms();
led2=0;
secondpoint=0;
//-----------显示时间秒------------
LEDData=~LEDCode[second/10];
led3=1;
Delay10ms();
led3=0;
LEDData=~LEDCode[second%10];
led4=1;
Delay10ms();
led4=0;
//-----------显示1组的分数百位-------
if(AorB==0)
LEDData=~LEDCode[scoreA/100];
else
LEDData=~LEDCode[scoreB/100];
led5=1;
Delay10ms();
led5=0;
//---------------显示1组分数的十位-----------
if(AorB==0)
LEDData=~LEDCode[(scoreA%100)/10];
else
LEDData=~LEDCode[(scoreB%100)/10];
led6=1;
Delay10ms();
led6=0;
//---------------显示1组分数的个位-----------
if(AorB==0)
LEDData=~LEDCode[scoreA%10];
else
LEDData=~LEDCode[scoreB%10];
led7=1;
Delay10ms();
led7=0;
//-----------显示2组分数的百位-------
if(AorB==1)
LEDData=~LEDCode[scoreA/100];
else
LEDData=~LEDCode[scoreB/100];
led8=1;
Delay10ms();
led8=0;
//-----------显示2组分数的十位-----------
if(AorB==1)
LEDData=~LEDCode[(scoreA%100)/10];
else
LEDData=~LEDCode[(scoreB%100)/10];
led9=1;
Delay10ms();
led9=0;
//-----------显示2组分数的个位-----------
if(AorB==1)
LEDData=~LEDCode[scoreA%10];
else
LEDData=~LEDCode[scoreB%10];
led10=1;
Delay10ms();
led10=0;
}
//=========================按键检测程序================================================
voidkeyscan(void)
{
if(playon==0)
{
if(add1==0)
{
display();
if(add1==0);
{
if(minit<99)
minit++;
else
minit=99;
}
do
display();
while(add1==0);
}
if(dec1==0)
{
display();
if(dec1==0);
{
if(minit>0)
minit--;
else
minit=0;
}
do
display();
while(dec1==0);
}
if(add2==0)
{
display();
if(add2==0);
{
if(second<59)
second++;
else
second=59;
}
do
display();
while(add2==0);
}
if(dec2==0)
{
display();
if(dec2==0);
{
if(second>0)
second--;
else
second=0;
}
do
display();
while(dec2==0);
}
}
else
{
if(add1==0)
{
display();
if(add1==0);
{
if(AorB==0)
{
if(scoreA<999)
scoreA++;
else
scoreA=999;
}
else
{
if(scoreB<999)
scoreB++;
else
scoreB=999;
}
}
do
display();
while(add1==0);
}
if(dec1==0)
{
display();
if(dec1==0);
{
if(AorB==0)
{
if(scoreA>0)
scoreA--;
else
scoreA=0;
}
else
{
if(scoreB>0)
scoreB--;
else
scoreB=0;
}
}
do
display();
while(dec1==0);
}
if(add2==0)
{
display();
if(add2==0);
{
if(AorB==1)
{
if(scoreA<999)
scoreA++;
else
scoreA=999;
}
else
{
if(scoreB<999)
scoreB++;
else
scoreB=999;
}
}
do
display();
while(add2==0);
}
if(dec2==0)
{
display();
if(dec2==0);
{
if(AorB==1)
{
if(scoreA>0)
scoreA--;
else
scoreA=0;
}
else
{
if(scoreB>0)
scoreB--;
else
scoreB=0;
}
}
do
display();
while(dec2==0);
}
}
}
voidmain()
{
TMOD=0x11;
TL0=0xb0;
TH0=0x3c;
TL1=0xb0;
TH1=0x3c;
minit=12;//初始值为12:
00
second=0;
EA=1;
ET0=1;
ET1=1;
TR0=0;
TR1=0;
EX0=1;
IT0=1;
IT1=1;
EX1=1;
PX0=1;
PX1=1;
PT0=0;
P1=0xFF;
P3=0xFF;
while
(1)
{
keyscan();
display();
}
}
voidPxInt0(void)interrupt0
{
Delay10ms();
EX0=0;
alam=0;
TR1=0;
if(timeover==1)//比赛结束标志位,为1时表示时间已经完
{
timeover=0;
}
if(playon==0)//比赛进行标志位,为1时表示比赛开始,计时开启
{
playon=1;