一、实验目的
1、熟练单片机的结构组成及原理;
2、软硬兼施,采用硬件电路的焊接搭建和软件的设计调试、下载,亲自动手,对硬件系统加深了解的同时,软件编程也能得心应手;
3、了解如何从硬件和软件上分析问题,排除故障。
二、实验内容
MCS-51/MCS-52单片机的跑马灯硬软件设计、键盘控制及键号显示电路的软硬件设计、直流电机转速电路的软硬件设计、转速计数控制电路的软硬件设计、步进电机转速的硬软件设计
三、实验器材与工具
实验器材:
多功能电路板、AT89S52单片机、电解电容、瓷片电容、电阻、二极管、集成芯片、插槽、八段共阴数码管、发光二极管、三极管、12MHz晶振、小按钮开关、光电开关、直流电机、步进电机
主要工具
PC机、下载器、电烙铁、焊锡丝、导线、尖嘴钳、斜口钳、剥线钳、数字万用表、透明胶带等。
四、实验原理
1-1 MCS-51/MCS-52单片机的跑马灯的硬软件设计
1 MCS-51/MCS-52单片机跑马灯的硬件电路的设计。
图 1-1
如图1-1是一个利用51单片机设计的跑马灯电路,51单片机的第9引脚为复位电路,单片机上电之初,使用C-R充电过程使得第9脚保持10ms以上的高电位,使机器复位。复位开关K可使之做到随机复位。
51单片机的第18,19引脚为外接晶振,接一个12M的晶振,同51单片机内部电路配合,上电后产生12兆的晶振频率和1兆的机器周期频率。
因为89S52机片内含8K程序存储器,机器运行程序将下载其中,故89S51的引脚EA接电源VCC。
51单片机第32—39引脚为P0口,分别对应P0.7—P0.0,P0口外接10KΩ的上拉排阻。P0口的P0.0—P0.7与74HC573的D0—D7一一对应相连,74HC573的Q0—Q7为输出,分别经220Ω电阻后接于发光二极管(跑马灯)的D0—D7上。
74HC573为8位锁存器,其1脚为输出使能端,低电平有效。本电路将其接地,所以74HC573的8位Q端为直通输出。
74HC573的第11引脚LE为输入使能端,高电平有效。本电路中或非门的输出与其相连,而或非门的两个输入端分别连接于51机的和P2.7引脚上。将P0口的数据写入,74HC573的输入条件是在写入的瞬间必须使P2.7端为低电平,写入有效时,也同时为低电平。这就构成,74HC573(跑马灯)的写入地址为0X7FFF,此电路中的或非门在此时从低电平观点视为低与非门。
2 MCS-51/MCS-52单片机跑马灯的软件设计
/********************************************/
/* 51单片机学习板主程序,12MHz晶振 */
/********************************************/
#include <AT89X52.H>
#include <absacc.h>
#include "delay.h"
#include "scan_key.h"
#include "timer0srv.h"
#include "spd.h"
void Initial() //初始化函数
{
TMOD=0x11;
IT0 = 1; //键盘中断初始化
EX0 = 1;
PX0 = 0;
IT1 = 1; //直流电机转速计数初始化
EX1 = 1;
PX1 = 0;
ET1 = 1; //直流电机转速定时初始化
PT1 = 1;
TL1 = 0x00;
TH1 = 0x00;
TR1 = 1;
PT0 = 0; //步进电机调速和直流电机自动调速初始
ET0 = 1;
TL0 = 0x00;
TH0 = 0x00;
TR0 = 1;
EA = 1;
P1 = 0xf0;
DAC_ADDR = 0x7f;
}
void main()
{
unsigned char LEDval = 0x0f,i = 0,j=0;
unsigned int temp,step_delay=0;
Initial();
while(1)
{
P1 = 0xf0; //键盘初始化
/*/////// 跑马灯程序 ////////////////////////*/
for(i=1;i<10;i++)
{
for(temp=0;temp<256;temp+=i)
{
LED_ADDR = temp;
delay_nms(80);
}
}
for(i=0,j=0x01;i<10;)
{
LED_ADDR = j;
delay_nms(100);
j = j<<1;
if(j==0)
{
i++;
j++;
}
}
for(i=0,j=0x80;i<10;)
{
LED_ADDR = j;
delay_nms(60);
j = j>>1;
if(j==0)
{
i++;
j=0x80;
}
}
}
}
在以上的程序中:
#include <AT89X52.H>为51单片机中定义的特殊功能寄存器功能头文件。
#include <absacc.h>为C语言头文件。
#include "delay.h"为延时函数。
#include "scan_key.h"为键盘控制函数。
initial()函数为预置函数,为后续键盘控制程序,定时器中断程序,直流电机,步进电机驱动程序预置特殊功能寄存器。
在main()函数中先对变量temp进行加i计数,采用双重循环方式,第一遍i=1,temp计数,每次加1,计数范围从0——255,达到256归零。每计数一次,将结果送LED_ADDER。LED_ADDR地址定义为0X7FFF,即将temp结果经P0口送锁存器74HC573,然后经发光二极管显示。第二遍i=i+1=2,temp=temp+i,即temp每次加2,直到temp<256再对temp归零。这一循环过程直到i=9,在每次送LED_ADDER地址(P0口)显示后,调延时程序延时200ms左右,以便让学生看清楚显示过程。然后进入跑马灯左移位程序。先将j=1,LED_ADDR=j,delay_nms(100);j=j<<1,(左移一位)。再将LED_ADDR=j……直到j=0,再将j=1……这样循环左移10遍。再进入循环右移过程:先将j=0x80(即最左位置1), LED_ADDR=j;延时,j=j>>1(右移1位),LED_ADDR=j;直到j=0(右移8位后)再将经=0x80……如此循环10遍,再返回程序初始位置。
由于51机指令系统多数为单机器周期指令,运行速度是μs级,肉眼无法鉴别temp的计数过程,故在每次执行LED_ADDR=temp指令后,要调用延时函数delay_nms(80)使temp的值经P0口送74HC573锁存器后,保存显示在发光二极管400ms左右。
1-2 MCS-51/MCS-52单片机键盘控制及键号显示电路软硬件设计。
1 MCS-51/MCS-52单片机键盘控制及键号显示电路的硬件设计。
图 1-2
51单片机键盘控制及键号数码显示硬件电路如图1-2,51单片机的P1口控制键盘,其中P1.0,P1.1,P1.2,P1.3为列线,P1.4,P1.5,P1.6,P1.7为行线。四根行线各接1只5.1K电阻,再与电源VCC(+5V)相连。四根行线同时也与74HC21(四输入与门)的输入端口相连,其输出端与51单片机的外中断0输入端P3.2相连。因为P1口通过指令设置为0xF0,即“11110000”,四列线均为“0”,如果没有键按下,则四个行线均为高电平。74HC21输出为高电平。当有任意一个键被按下,则如图1-2所示,则74HC21的四个输入端总有一个输入为低电平。此时的74HC21的功能为:只要有一个输入端为低电平,则其输出端为低电平。此下降沿触发51单片机的外中断0而引发中断服务(搜索中断键号),所以对键盘控制方式采用的是中断搜索方式。
2 MCS-51/MCS-52单片机键盘控制及键号显示电路的软件设计。
/****************扫描矩阵键盘子程序scan_key.h******************/
#include <AT89X52.H>
#include <absacc.h>
#include "delay.h"
#ifndef _SCAN_KEY
#define _SCAN_KEY
#define SEG_ADDR XBYTE[0xbfff]
#define LED_ADDR XBYTE[0x7fff]
unsigned char nKeyNumber;
void int0() interrupt 0
{
int i,j;
int Pin1;
EX0 = 0;
delay_nms(20);
// if(P3_2==0)
// {
for(i=0;i<4;i++) //i代表行,j代表列,每列逐行扫描
{
P1=0xff&(~(0x01<<3-i));
Pin1=P1;
for(j=0;j<4;j++)
{
if(((Pin1>>(4+j))&0x01)==0)
{
nKeyNumber=i+j*4;
i = 4;
j = 4;
P1 = 0xf0;
SEG_ADDR = (nKeyNumber/10 <<4)+ nKeyNumber%10;
delay_nms(20);
EX0 = 1;
return;
}
}
}
// }
P1 = 0xf0;
EX0 = 1;
}
#endif
1-3 MCS-51/MCS-5单片机控制直流电机转速电路的软硬件设计。
1 MCS-51/MCS-52单片机控制直流电机转速电路的硬件设计。
如图1-3所示,将P0口的P0.0-P0.7与A/D转换器0832的D0-D7相连,单片机的待转换数据由P0口输出给8位D/A转换器0832的输入寄存器,写入地址为0xDFFF,即89S51的P2.5=0与同时为低,经74HC02反向后,则8位输入寄存器的输入使能端ILE为高,将D0—D7的8位转换数据送入0832寄存器,DAC0832内部两级寄存器接成直通状态,即0832的,,,XFER均接低电平,所以DAC0832的D/A转换器对输入的数据信号实时进行转换输出。输出端口为IOUT1和IOUT2。输出的模拟信号由两级运放LM324放大馈送至直流电机。LM324均由负极端口输入而正极端口接地,构成两极反向放大电路。故最终给电机的直流电流信号与DAC0832的输出端口的电流电压信号为同相信号,运算放大器的供电电压为±9V。
图 1-3
直流电机一端接LM324的输出,另一端接地。由于LM324用±9V供电,则LM324的输出电压则会以0V为中心点,对DAC0832的输出端的输出信号进行电流电压放大,使LM324的输出在+8V—-8V之间成比例地浮动,从而驱动直流电机以不同速度正转和反转。
2 MCS-51/MCS-52单片机控制直流电机转速电路的软件设计。
/***********************************/
/* 键盘中断及直流电机手动变速速控制*/
/**********************************/
#include <AT89X52.H>
#include <absacc.h>
#include "delay.h"
#ifndef _SCAN_KEY
#define _SCAN_KEY
#define SEG_ADDR XBYTE[0xbfff] //数码管地址
#define LED_ADDR XBYTE[0x7fff] //跑马灯地址
#define DAC_ADDR XBYTE[0xdfff] //直流电机地址
#define STEP_ADDR XBYTE[0xefff] //步进电机地址
unsigned char nKeyNumber;
void int0() interrupt 0
{
int i,j;
int Pin1;
EX0 = 0;
delay_nms(20);
for(i=0;i<4;i++) //i代表行,j代表列,每列逐行扫描
{
P1=0xff&(~(0x01<<3-i));
Pin1=P1;
for(j=0;j<4;j++)
{
if(((Pin1>>(4+j))&0x01)==0)
{
nKeyNumber=i+j*4;
i = 4;
j = 4;
P1 = 0xf0;
SEG_ADDR = nKeyNumber/10 + (nKeyNumber%10<<4);
switch(nKeyNumber)
{
case 0:
DAC_ADDR = 0x7f;
SEG_ADDR = 0x00;
break;
case 1:
DAC_ADDR = 0x00;
break;
case 2:
DAC_ADDR = 25;
break;
case 3:
DAC_ADDR = 50;
break;
case 4:
DAC_ADDR = 75;
break;
case 5:
DAC_ADDR = 100;
break;
case 6:
DAC_ADDR = 127;
break;
case 7:
DAC_ADDR = 150;
break;
case 8:
DAC_ADDR = 175;
break;
case 9:
DAC_ADDR = 200;
break;
case 10:
DAC_ADDR = 225;
break;
case 11:
DAC_ADDR = 240;
break;
case 12:
DAC_ADDR = 255;
break;
default:
break;
}
EX0 = 1;
return;
}
}
}
P1 = 0xf0;
EX0 = 1;
}
#endif
1-4 MCS-51/MCS-52单片机转速计数控制电路的软硬件设计
图 1-4
1 MCS-51/MCS-52单片机转速计数控制电路的硬件电路设计
如图1-4所示,由红外发射管D和红外接收管T组成的转速检测电路中,当D和T之间没有遮挡物时,红外光由D照向T,红外接收管T受光后饱和导通,A点电位为0.3V,经或非门输出高电平。P3.3端因高电平无中断触发;当转动轴上的叶片经过D-T之间划过瞬间,T管因叶片遮挡不受光而截止,A点呈高电平。在P3.3端口接收到一个由高电平至低电平的下降沿,导致外中断1被触发而引起中断请求。转动轴上的叶片每转动一周,划过D-T一次,红外光被遮一次而中断一次。如果在单位时间(秒)内D-T间被遮挡n次,则被中断n次,直流电机的转速便是n。
2 MCS-51/MCS-52单片机转速计数控制电路的软件设计
/******************************************/
/* 直流电机测速程序 */
/******************************************/
#include <AT89x52.h>
#include <absacc.h>
#include "delay.h"
#ifndef _SPD_H
#define _SPD_H
unsigned int pt=0;
unsigned char ft=0;
void int1( ) interrupt 2
{
ft = ft + 1;
}
void timer1_isr( ) interrupt 3
{
unsigned char pp;
if(pt>=15)
{
pt = 0;
if(ft!=0)
{
if(ft>45)
ft = ft - 4;
else if(ft>40)
ft = ft - 3;
else if(ft<35)
ft = ft - 3;
}
pp = ft/10 + (ft%10<<4);
SEG_ADDR = pp;
ft = 0;
}
else
pt=pt+1;
}
#endif
1-5 MCS-51/MCS-52单片机控制步进电机转速的硬软件设计
如图1-5所示,步进电机的驱动数码信号经P0.3,P0.2,P0.1,P0.0传送至HC573的D3,D2,D1,D0和D7,D6,D5,D4,传送到D7,D6,D5,D4的数码信号由HC573的Q7,Q6,Q5,Q4输出,再驱动四只发光二极管,显示驱动步进电机的数码及转速频率,而另外一路经过Q3,Q2,Q1,Q0传送至LM2003电流放大,LM2003的最大驱动电流可以达到0.5A。
图 1-5
1 MCS-51/MCS-52单片机控制步进电机转速的硬件电路设计
由LM2003去驱动步进电机正向或者反向转动。由于步进电机为感性负载,当驱动器LM2003输出端关断时,势必引起电机与LM2003D端口较大的反向电动势,危及LM2003输出端口的安全。因此电路中在LM2003与步进电机的输入端并接四只二极管D0,D1,D2,D3及四只4.7K的电阻,称之为续流二极管和续流电阻。当LM2003输出端口截止时,步进电机电感线圈产生的续流电动势大于+5.7V时,二极管导通,限制LM2003的输出端口电压不大于+5.7V,以确保LM2003输出端的安全。
2 MCS-51/MCS-52单片机控制步进电机转速和直流电机自动加速运转的软件设计
/*****************************************************/
/* 定时器0中断函数
/*****************************************************/
#include <AT89X52.H>
#ifndef _TIMER0_SRV
#define _TIMER0_SRV
static unsigned char loop_temp = 0,temp = 0;
unsigned char motor_val = 0x00;
void timer0_srv() interrupt 1
{
TL0 = 0x00;
TH0 = 0x00;
loop_temp=(loop_temp+1)%5; //定时器0扩展4倍
if(loop_temp==0)
{
temp = (temp+1)%4; //步进电机四相
if(nKeyNumber==13)
{
switch(temp)
{
case 0:
STEP_ADDR = 0x01;
break;
case 1:
STEP_ADDR = 0x02;
break;
case 2:
STEP_ADDR = 0x04;
break;
case 3:
STEP_ADDR = 0x08;
break;
}
}
else if(nKeyNumber==14)
{
switch(temp)
{
case 0:
STEP_ADDR = 0x03;
break;
case 1:
STEP_ADDR = 0x09;
break;
case 2:
STEP_ADDR = 0x0c;
break;
case 3:
STEP_ADDR = 0x06;
break;
}
}
else if(nKeyNumber == 15)
{
switch(temp)
{
case 0:
STEP_ADDR = 0x01;
break;
case 1:
STEP_ADDR = 0x02;
break;
case 2:
STEP_ADDR = 0x04;
break;
case 3:
STEP_ADDR = 0x08;
break;
}
motor_val = motor_val + 1;
DAC_ADDR = motor_val;
}
}
return;
}
#endif
五、实物图