资源描述
中国地质大学江城学院
《单片机原理及应用》
课程设计
学 部
班 级
学 号
姓 名
指导教师
年 月 日
目录
第1章 系统开发的基本原理 3
1.1 复位电路及时钟电路 3
1.2 跑马灯的基本原理 4
1.3 数码管的基本原理 5
1.4 键盘的基本原理 5
第2章 系统硬件设计 6
2.1 MCS-51单片机介绍 6
2.2 74HC573锁存器介绍 7
2.3 74HC02或非门介绍 7
2.4 4511译码器介绍 8
2.5 数码管介绍 9
2.6 系统硬件电路设计 10
第3章 系统软件设计 12
3.1 软件设计架构 12
3.2 主程序模块 13
3.3 跑马灯程序模块 18
3.4 键盘程序模块 18
3.5 数码管程序模块 19
第4章 系统测试 19
4.1 测试方法 19
4.2 测试考虑的因素 20
4.3 测试结论 20
第5章 课程设计小结 20
摘要:单片机最小系统,无论对单片机初学人员还是开发人员都具有十分重要的意义,可以利用最小系统进行编程实现工业控制。单片机最小系统电路板在单片机开发市场和大学生电子设计方面十分流行。本次课程设计包括AT89S52单片机最小系统(包括复位和时钟电路)及供电系统、4×4矩阵键盘、独立4个8段LED数码管显示电路。利用Protel电路设计软件进行原理图设计,PCB布线,借此巩固单片机应用、模拟电路、数字电路课程及学会工程软件protel的使用。
第1章 系统开发的基本原理
对51 系列单片机来说, 最小系统一般应该包括: 单片机、时钟电路、复位电路、输入/ 输出设备等。本次课程设计的系统还包括流水灯、4*4矩阵键盘和二位数码管显示。
1.1 复位电路及时钟电路
复位电路和时钟电路是维持单片机最小系统运行的基本模块。复位电路通常分为两种:上电复位和手动复位。[2]
上电复位 手动复位
有时系统在运行过程中出现程序跑飞的情况,在程序开发过程中,经常需要手动复位。所以本次设计选用手动复位。
高频率的时钟有利于程序更快的运行,也有可以实现更高的信号采样率,从而实现更多的功能。但是告诉对系统要求较高,而且功耗大,运行环境苛刻。考虑到单片机本身用在控制,并非高速信号采样处理,所以选取合适的频率即可。合适频率的晶振对于选频信号强度准确度都有好处,本次设计选取12.000M无源晶振接入XTAL1和XTAL2引脚。并联2个30pF陶瓷电容帮助起振。
1.2 跑马灯的基本原理
220Ω×8
10
2
10 5.1K
5.1K
P2.7
D0
D1
D2
D3
D4
D5
D6
D7
Q0
Q1
Q2
Q3
Q4
Q5
Q6
Q7
39
38
37
36
35
34
33
32
31
+
WR
28
16
VCC
74HC573
89S51
89S52
+5V
9
RST
K
μ
18
19
33P
33P
20
74HC02
1
3
4
5
6
7
8
9
VCC
11
20
10K×8
跑马灯的就是讲发光二极管分时点亮,产生流水的效果。
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,此电路中的或非门在此时从低电平观点视为低与非门。
P0.0
P0.1
P0.2
P0.3
P0.4
P0.5
P0.6
P0.7
+
WR
74HC02
P2.6
+
P1.0
P1.1
P1.2
P1.3
P1.4
P1.5
P1.6
P1.7
P3.2
5.1K
VCC
13 a
12 b
11 c
10 d
9 e
15 f
14 g
7
1
2
6
5
4511-2
3 4
13 a
12 b
11 c
10 d
9 e
15 f
14 g
7
1
2
6
5
4511-1
3 4
89S51
VCC
VCC
Ⅰ
Ⅱ
1.3 数码管的基本原理
单片机键盘控制及键号显示电路的硬件设计
键号的数码显示方式仍采用P0口输出给两片4511译码器。DC4511为四位BCD码输入,译码后产生7段数码管显示信号驱动数码管进行键号显示。
当控制地址为0xBFFF时,(即P2状态为10111111),与配合,驱动74HC02至4511的第5脚LE端,打开4511的锁存器,键号的显示由P0口输出。见图1-2。P0口的P0.3,P0.2,P0.1,P0.0与4511-1的D、C、B、A相连,再经译码后驱动数码管Ⅰ,显示键号的个位。而P0的P0.7,P0.6,P0.5,P0.4与4511-2的D、C、B、A相连,经译码后驱动数码管Ⅱ,显示键盘号的十位数。
1.4 键盘的基本原理
矩阵键盘是在要求按键不多是的一种简易键盘设计。与编码键盘相比,矩阵键盘不需要专门的编码芯片,从而成本低,设计简单,用简单的面包板即可搭成。缺点是占用单片机端口较多,而且编程实现行扫描列扫描比较占用资源。
键盘的原理是在一端接入高电平,用单片机一个端口去检测按键另一端的电平,另一端也是高电平时,说明按键被按下。4×4矩阵键盘,分为4行4列,在每列加上拉电阻(加高电平),然后用程序控制行扫描和列扫描,判断具体哪个按键被按下。由于本身键盘的特点,再设计程序是需要加入消除抖动处理。
51单片机的P1口控制键盘,其中P1.0,P1.1,P1.2,P1.3为列线,P1.4,P1.5,P1.6,P1.7为行线。四根行线各接1只5.1K电阻,再与电源VCC(+5V)相连。本次课程设计没有加中断,因而用扫描的方法写程序。
第2章 系统硬件设计
2.1 MCS-51单片机介绍
AT89S52 8位单片机是MSC-51®系列产品的升级版,有世界著名半导体公司ATMEL在购买MSC-51®设计结构后,利用自身优势技术——(掉电不丢数据)闪存生产技术对旧技术进行改进和扩展,同时使用新的半导体生产工艺,最终得到成型产品。与此同时,世界上其他的著名公司也通过基本的51内核,结合公司自身技术进行改进生产,推广一批如51F020等高性能单片机。
AT89S52片内集成256字节程序运行空间、8K字节Flash存储空间,支持最大64K外部存储扩展。根据不同的运行速度和功耗的要求,时钟频率可以设置在0-33M之间。片内资源有4组I/O控制端口、3个定时器、8个中断、软件设置低能耗模式、看门狗和断电保护。可以在4V到5.5V宽电压范围内正常工作。不断发展的半导体工艺也让该单片机的功耗不断降低。同时,该单片机支持计算机并口下载,简单的数字芯片就可以制成下载线,仅仅几块钱的价格让该型号单片机畅销10年不衰。根据不同场合的要求,这款单片机提供了多种封装,本次设计根据最小系统有时需要更换单片机的具体情况,使用双列直插DIP-40的封装。
DIP-40封装89S52引脚图
2.2 74HC573锁存器介绍
74HC573是八进制3 态非反转透明锁存器,器件的输入是和标准CMOS 输出兼容的;加上拉电阻,他们能和LS/ALSTTL 输出兼容。当锁存使能端为高时,这些器件的锁存对于数据是透明的(也就是说输出同步)。当锁存使能变低时,符合建立时间和保持时间的数据会被锁存。
74HC573引脚图 74HC573内部结构
2.3 74HC02或非门介绍
74HC02是四2输入或非门。1A-4A 输入端,1B-4B 输入端,1Y-4Y 输出端。
2.4 4511译码器介绍
CD4511是一个用于驱动共阴极 LED (数码管)显示器的 BCD 码—七段码译码器,特点:具有BCD转换、消隐和锁存控制、七段译码及驱动功能的CMOS电路能提供较大的拉电流。可直接驱动LED显示器。
CD4511 是一片 CMOS BCD—锁存/7 段译码/驱动器,引脚排列如图 2 所示。其中a b c d 为 BCD 码输入,a为最低位。LT为灯测试端,加高电平时,显示器正常显示,加低电平时,显示器一直显示数码“8”,各笔段都被点亮,以检查显示器是否有故障。BI为消隐功能端,低电平时使所有笔段均消隐,正常显示时, B1端应加高电平。另外 CD4511有拒绝伪码的特点,当输入数据越过十进制数9(1001)时,显示字形也自行消隐。LE是锁存控制端,高电平时锁存,低电平时传输数据。a~g是 7 段输出,可驱动共阴LED数码管。另外,CD4511显示数“6”时,a段消隐;显示数“9”时,d段消隐,所以显示6、9这两个数时,字形不太美观 图3是 CD4511和CD4518配合而成一位计数显示电路,若要多位计数,只需将计数器级联,每级输出接一只 CD4511 和 LED 数码管即可。所谓共阴 LED 数码管是指 7 段 LED 的阴极是连在一起的,在应用中应接地。
CD4511 引 脚 图
其功能介绍如下:
BI:4脚是消隐输入控制端,当BI=0 时,不管其它输入端状态
如何,七段数码管均处于熄灭(消隐)状态,不显示数字。
LT:3脚是测试输入端,当BI=1,LT=0 时,译码输出全为1,不管输入 DCBA 状态如何,七段均发亮,显示“8”。它主要用来检测数码管是否损坏。
LE:锁定控制端,当LE=0时,允许译码输出。 LE=1时译码器是锁定保持状态,译码器输出被保持在LE=0时的数值。
A1、A2、A3、A4、为8421BCD码输入端。
a、b、c、d、e、f、g:为译码输出端,输出为高电平1有效。
CD4511的工作真值表
2.5 数码管介绍
LED数码管显示是利用半导体发光制成条形的发光二极管,封装在一起组成数字或其他符号形状。数码管根据公共端不同,分为共阴极和共阳极两种形式。
共阴极数码管 共阳极数码管
根据设计需要,本次选用共阴极数码管。键号的数码显示方式仍采用P1口输出给两片4511译码器,如图1-4。DC4511为四位BCD码输入,译码后产生7段数码管显示信号驱动数码管进行键号显示。
数码管引脚图
2.6 系统硬件电路设计
第3章 系统软件设计
3.1 软件设计架构
本次系统的主要是用扫描的方法检测按键值,不同按键值设置不同的功能。1号键——流水灯;2-13号键——直流电机手动调速;14号键——步进电机正转;15号键——步进电机反转;16号键——直流电机自动调速。
开始
初始化
逐次给矩阵键盘四行低电平
逐次判断列=0?
否
按键去抖
是
判断列=0?
对应键值的键值数码管显示和功能
返回
3.2 主程序模块
#include <reg52.h>
#include<intrins.h>
#include <absacc.h>
#define SEG_ADDR XBYTE[0xbfff] //数码管地址
#define LED_ADDR XBYTE[0x7fff] //跑马灯地址
#define DAC_ADDR XBYTE[0xdfff] //直流电机地址
#define STEP_ADDR XBYTE[0xefff] //步进电机地址
#define uchar unsigned char
typedef unsigned int uint16;
typedef unsigned long uint32;
typedef char int8;
typedef int int16;
typedef long int32;
sbit KeyIn1 = P1^0; //矩阵键盘地址定义
sbit KeyIn2 = P1^1;
sbit KeyIn3 = P1^2;
sbit KeyIn4 = P1^3;
sbit KeyOut1 = P1^4;
sbit KeyOut2 = P1^5;
sbit KeyOut3 = P1^6;
sbit KeyOut4 = P1^7;
uchar code Pattern_P0[]=
{
0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xe7,0xdb,0xbd,0x7e,0xbd,0xdb,0xe7,0xff,0xe7,0xc3,0x81,0x00,0x81,0xc3,0xe7,0xff,
0xaa,0x55,0x18,0xff,0xf0,0x0f,0x00,0xff,0xf8,0xf1,0xe3,0xc7,0x8f,0x1f,0x3f,0x7f,
0x7f,0x3f,0x1f,0x8f,0xc7,0xe3,0xf1,0xf8,0xff,0x00,0x00,0xff,0xff,0x0f,0xf0,0xff,
0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
}; //流水灯函数定义
uchar code bujingZ[]={0x01,0x02,0x04,0x08}; //步进电机正转函数
uchar code bujingF[]={0x03,0x09,0x0c,0x06}; //步进电机反转函数
void delay(uint16 t)
{
uint16 k;
while(t--)
{
for(k=0; k<123; k++)
{ }
}
}
/********************************************************/
/*
/*步进电机正转
/*
/********************************************************/
void motor_ffw(uint16 n)
{
uchar i;
uint16 j;
for (j=0; j<5*n; j++) //转n圈
{
for (i=0; i<4; i++) //一个周期转72度
{
STEP_ADDR = bujingZ[i]; //取数据
delay(100); //调节转速
}
}
}
/********************************************************/
/*
/*步进电机反转
/*
/********************************************************/
void motor_rev(uint16 n)
{
uchar i;
uint16 j;
for (j=0; j<5*n; j++) //转n圈
{
for (i=0; i<4; i++) //一个周期转72度
{
STEP_ADDR = bujingF[i]; //取数据
delay(100); //调节转速
}
}
}
void delay0(void)
{
uint16 i=1000;
while (i--);
}
void DelayMS(uint16 x)
{
uchar i;
while(x--)
{
for(i=0;i<120;i++);
}
}
main()
{
uint16 i;
DAC_ADDR = 0x7f; //直流电机初始化定义
while (1)
{
KeyOut1 = 0; //扫描第一行
KeyOut2 = 1;
KeyOut3 = 1;
KeyOut4 = 1;
if(KeyIn1 == 0) //按键1按下
{
delay0(); //按键消抖
if(KeyIn1 == 0)
SEG_ADDR = 0x00; //数码管显示00
DAC_ADDR = 0x7f; //直流电机停止转动
for(i=0;i<80;i++) //流水灯开始运行
{
LED_ADDR =~Pattern_P0[i];
DelayMS(150);
}
}
if(KeyIn2 == 0) //按键2按下
{
delay0(); //按键消抖
if(KeyIn2 == 0)
SEG_ADDR = 0x10; //数码管显示01
DAC_ADDR = 0x00; //直流电机转动
}
if(KeyIn3 == 0) //按键3按下
{
delay0(); //按键消抖
if(KeyIn3 == 0)
SEG_ADDR = 0x20; //数码管显示02
DAC_ADDR =25; //直流电机转动
}
if(KeyIn4 == 0) //按键4按下
{
delay0(); //按键消抖
if(KeyIn4 == 0)
SEG_ADDR = 0x30; //数码管显示03
DAC_ADDR = 50; //直流电机转动
}
while((KeyIn1 == 0)||(KeyIn2 == 0)||
(KeyIn3 == 0)||(KeyIn4 == 0));
KeyOut1 = 1;
KeyOut2 = 0; //扫描第二行
KeyOut3 = 1;
KeyOut4 = 1;
if(KeyIn1 == 0) //按键5按下
{
delay0(); //按键消抖
if(KeyIn1 == 0)
SEG_ADDR = 0x40; //数码管显示04
DAC_ADDR = 75; //直流电机转动
}
if(KeyIn2 == 0) //按键6按下
{
delay0(); //按键消抖
if(KeyIn2 == 0)
SEG_ADDR = 0x50; //数码管显示05
DAC_ADDR = 100; //直流电机转动
}
if(KeyIn3 == 0) //按键7按下
{
delay0(); //按键消抖
if(KeyIn3 == 0)
SEG_ADDR = 0x60; //数码管显示06
DAC_ADDR = 125; //直流电机转动
}
if(KeyIn4 == 0) //按键8按下
{
delay0(); //按键消抖
if(KeyIn4 == 0)
SEG_ADDR = 0x70; //数码管显示07
DAC_ADDR = 150; //直流电机转动
}
while((KeyIn1 == 0)||(KeyIn2 == 0)||
(KeyIn3 == 0)||(KeyIn4 == 0));
KeyOut1 = 1;
KeyOut2 = 1;
KeyOut3 = 0; //扫描第三行
KeyOut4 = 1;
if(KeyIn1 == 0) //按键9按下
{
delay0(); //按键消抖
if(KeyIn1 == 0)
SEG_ADDR = 0x80; //数码管显示08
DAC_ADDR = 175; //直流电机转动
}
if(KeyIn2 == 0) //按键10按下
{
delay0(); //按键消抖
if(KeyIn2 == 0)
SEG_ADDR = 0x90; //数码管显示09
DAC_ADDR = 200; //直流电机转动
}
if(KeyIn3 == 0) //按键11按下
{
delay0(); //按键消抖
if(KeyIn3 == 0)
SEG_ADDR = 0x01; //数码管显示10
DAC_ADDR = 225; //直流电机转动
}
if(KeyIn4 == 0) //按键12按下
{
delay0(); //按键消抖
if(KeyIn4 == 0)
SEG_ADDR = 0x11; //数码管显示11
DAC_ADDR = 240; //直流电机转动
}
while((KeyIn1 == 0)||(KeyIn2 == 0)||
(KeyIn3 == 0)||(KeyIn4 == 0));
KeyOut1 = 1;
KeyOut2 = 1;
KeyOut3 = 1;
KeyOut4 = 0; //扫描第四行
if(KeyIn1 == 0) //按键13按下
{
delay0(); //按键消抖
if(KeyIn1 == 0)
SEG_ADDR = 0x21; //数码管显示12
DAC_ADDR = 255; //直流电机转动
}
if(KeyIn2 == 0) //按键14按下
{
delay0(); //按键消抖
if(KeyIn2 == 0)
SEG_ADDR = 0x31; //数码管显示13
motor_ffw(5); //步进电机正转
}
if(KeyIn3 == 0) //按键15按下
{
delay0(); //按键消抖
if(KeyIn3 == 0)
SEG_ADDR = 0x41; //数码管显示14
motor_rev(5); //步进电机反转
}
if(KeyIn4 == 0) //按键16按下
{
delay0(); //按键消抖
if(KeyIn4 == 0)
SEG_ADDR = 0x51; //数码管显示15
for(i=0;i<255;i++) //直流电机自动调速
{
DAC_ADDR = i;
DelayMS(150);
}
}
while((KeyIn1 == 0)||(KeyIn2 == 0)||
(KeyIn3 == 0)||(KeyIn4 == 0));
}
}
3.3 跑马灯程序模块
见3.2主程序模块。
3.4 键盘程序模块
见3.2主程序模块。
3.5 数码管程序模块
见3.2主程序模块。
第4章 系统测试
4.1 测试方法
软件仿真:将程序写入keil软件,编译无错误。
点击Peripherals->I/O-Ports->Port 1,选择 P1 口。下图表示按键3时的仿真结果.手动设计P1口的值,观察程序运行的过程。
硬件测试:将程序在keil软件中编译,生成HEX文件,用下载工具将HEX文件下载到单片机里面。按不同键,检测不同按键下的结果。观察实验板产生的结果,比较结果与设计目标是否相同。
4.2 测试考虑的因素
1.供电瞬停,电源突然断开,系统重启。工作正常。
2.电磁干扰和辐射,将手机放在单片机旁,手机有辐射和电磁干扰,工作正常。
3.振动,将实验板在桌上敲击,通电,无接触不良,工作正常。
4.高温,将实验板放置于室外,温度为33º,系统工作正常。
5.连续工作,我将实验板通电3个小时,系统稳定运行,只要7805温度过高。
4.3 测试结论
该课程设计的硬件电路焊接良好,程序工作正常,系统工作正常。
第5章 课程设计小结
通过这次单片机课程设计,使我们对单片机的结构、基本工作原理、单片机应用系统开发有了进一步的了解,特别是在硬件设计和软件编程方面有了很大提高。单片机课程设计的硬件设计电路简单,但对各芯片的性能及工作原理不是很熟悉;软件设计并不太复杂,但需要搞清其工作原理,时序。
在设计的过程中,通过请教老师和同学,上网或上图书馆查资料将这些问题解决。这样不仅巩固了以前所学过的知识,加深了我对所学知识的理解,而且学到了很多在书本上未涉及的知识, 锻炼了搜集有用信息的能力。
在硬件设计过程中,需要考虑很多问题,例如元器件参数的选取,单片机的实际驱动能力。在实际电路的设计时,必须软硬件相结合,使布局合理且软件设计的简单。
软件编程过程中,由于采用 C 语言编程,以前虽然有过接触,但并不是很熟练,所以参考了别人的设计思路,琢磨研究弄懂后,又试着修改程序。由于实验指导书的程序大部分是用中断的方法编写,由于今天我们电路设计中的键盘电路省略了74HC21,我们只能用扫描的方法写程序。之前由于对地址的用法不是很了解,但是参考知道书之后,明白了单片机系统设计的原理。而且能够较熟练的在用C语言写的程序中给地址送数据。程序写好之后最麻烦的是程序的调试,一个括号的位置区别,就会是程序运行的结果大不相同。在不满足要求时反复思考,研究错误出在哪里,经过不懈努力,最终找出错误所在,满足了基本的设计要求。在 编译仿真时对软件 Keil uVision3.0 和 Protel 认识更多,发现了 Protel 的很多优点,同时也发现它的不足之处,过于理想化,如果完全依赖,则硬件有可能无法工作。
总的来说,本次单片机的课程设计使我认识到课程的重要性,同时也感受到理论与实践之间的差距,让我对C51系列的单片机的系统设计有了一个整体的掌握。
21
展开阅读全文