基于Proteus的单片机项目实践教程
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

项目2 制作流水灯

【项目引入】

在现代城市的夜晚,到处可以见到各种各样的流水灯、霓虹灯、广告灯箱,这些灯变换着各种动感的图案和色彩,如图2-1所示。这些流水灯实际上都是简单的单片机控制电路,它可以根据客户的需要来变换各种不同的图案。在项目1中学会了点亮一个LED,本项目要实现的是按照一定的规律点亮多个LED。

图2-1 霓虹灯

【知识目标】

● 掌握单片机I/O口的应用;

● 掌握单片机最小系统的组成;

● 掌握流水灯的三种程序设计方法。

【技能目标】

● 熟悉单片机开发工具;

● 熟悉Keil、Proteus的安装和使用;

● 能制作流水灯硬件电路。

2.1 任务描述

用电子元器件和单片机制作一个流水灯,含有8个发光二极管,可以实现8个LED灯各种显示方式的点亮(例如从上到下逐个点亮)。

2.2 准备知识

在实施项目之前先来认识单片机I/O口。

单片机经常要和外设之间传输数据(输入,输出),P0,P1,P2,P3就是可以和外设完成并行数据传输的接口。

1.P1口

(1)结构

P1口是8位双向I/O口,1位的结构原理如图2-2所示。P1口由8个这样的电路组成,它由如下几个部分组成:数据输出锁存器(D触发器),起输出锁存作用;场效应管(FET)V、上拉电阻组成输出驱动器,以增大带负载能力;上下两个三态门分别是读锁存器端口和读引脚。

图2-2 P0口内部结构图

(2)功能

P1口通常作为通用的I/O口使用,每一位可单独定义为输入/输出口。

① 输出。若P1口外接发光二极管,则应定义为输出口,可以用语句P1=0Xdata输出数值。假设某一位需要输出0,则内部总线输出“0”,则D=0,,V导通,则输出0。

② 输入。若P1口外接按键,则应定义为输入口。

假设读引脚脉冲有效为高电平,把该三态缓冲器打开,这样P1端口引脚上的数据经过三态门缓冲器读入到内部总线。如果输入数据走该通道,那么场效管V对该引脚有影响的。

如果锁存器原来寄存的数据Q=0,那么场效应管V导通,引脚始终被嵌位在低电平,不可能输入外接电路的高电平。所以在输入前,必须用输出指令向锁存器写入“1”,使场效应管V截止(断开),保证单片机输入的电平与外接电路电平相同。所以P0口被称为一个准双向口。

2.P0口

(1)结构

P0口1位的结构原理如图2-3所示。在电路结构上,比P1口增加了:多路选择开关(MUX),配合非门、与门用来实现两种功能的切换;输出驱动电路由两个场效应管(FET)V1、V2组成的漏极开路电路组成。

图2-3 P0口内部结构图

(2)功能

P0口有两种功能:通用I/O口和地址/数据分时复用总线。

① 通用I/O口。

● 输出。P0口作为通用输出口使用时,内部控制信号为低电平,开关连接B点,同时与门输出0,V1截止。此时,此电路就与P1口的内部结构相似,唯一不同的是输出电路为漏极开路电路,因此使用时必须外接上拉电阻才有高电平输出。

● 输入。P0口作为通用输入口使用时,和输出口相似,必须外接上拉电阻。另外因为P0口也是准双向口,所以要先向电路中写入“1”。

② 地址/数据线。当作为地址/数据线时,内部发出控制信号,打开与门,使多路选择开关接通A,V2导通,V1、V2形成推拉式电路结构,使负载能力大为提高。可以输出低8位地址信号或输出/输入8位数据信号。

3.P2口

(1)结构

P2口的1位内部结构图如图2-4所示。此电路结构比P1口增加了:多路转换电路MUX,反相器。

图2-4 P2口内部结构图

(2)功能

P2口有两种功能:通用I/O口和地址总线

① 通用I/O口。在无外部扩展存储器系统中,多路转换开关打向B,P2口作为通用I/O口使用,此时和P1口功能一样。

② 地址总线(高8位)。在有外部扩展存储器系统中,多路转换开关打向A,P2口通常作为高8位地址线使用,P0口分时送出低8位地址线和8位数据线。由于有了16位地址,单片机最大可外接60KB的程序存储器和64KB数据存储器。

4.P3口

(1)结构

P3口的1位内部结构图如图2-5所示。此电路结构比P1口增加了:与非门第二功能输出控制电路,第二功能输入缓冲器。

图2-5 P3口内部结构图

(2)功能

P3口有两种功能:通用I/O口和第二功能。

① 通用I/O口。P3口作为通用I/O口使用,此时和P1口功能一样。

② 第二功能。在真正的单片机应用电路中,第二功能显得更为重要。因为第二功能信号有输入、输出两种情况,所以下面分两种情况说明。

● 第二功能输入。作为第二功能信号输入引脚时,在输入通路上增加了一个缓冲器,输入的第二功能信号就是从这个缓冲器的输出端取得的。

● 第二功能输出。作为第二功能信号输出引脚时,该位的锁存器应置1,Q端输出高电平,与非门对第二功能信号的输出是通畅的,从而实现了第二功能信号输出。P3第二功能各引脚功能定义如表1-1所示。

5.带负载能力

带负载能力是指在一定的电压(0~5V)下能够灌入或拉出的最大电流,也称为驱动能力。

拉电流和灌电流是衡量电路输出驱动能力的参数,这种说法一般常用在数字电路中。

(1)灌电流(输出低电平)

当负载的另一端接VCC,输出端口输出低电平时,就会产生灌电流。它是从负载流向输出端口,“灌进去”的电流,一般是要吸收负载的电流,其吸收电流的数值叫“灌电流”。

(2)拉电流(输出高电平)

当负载的另一端接地,输出端口输出高电平时,就会产生拉电流。它是从输出端口流向负载,“拉出来”的电流,一般是对负载提供电流,其提供电流的数值叫“拉电流”。

一般地,1个LSTTL(低功耗肖特基晶体管)其拉电流(高电平)0.20μA,灌电流(低电平)0.35mA。所以灌电流一般比拉电流要大得多。因此用单片机I/O驱动LED一般采用低电平输出方式(灌电流)。

(3)I/O口驱动能力

P0的负载能力为驱动8个TTL门电路,P1、P2、P3口的负载能力为驱动4个TTL门电路。

4个端口的引脚,每个引脚灌电流≤10mA,每个端口8个引脚灌电流之和:

P0≤26mA

P1、P2、P3≤15mA

2.3 项目实现

2.3.1 设计思路

本项目要求制作含有8个发光二极管,可以实现各种显示方式(例如从上到下)逐个点亮的流水灯。

2.3.2 硬件电路设计

根据前面讲解的I/O口的内容,流水灯需要8个LED作输出,所以可以选择单片机的4个I/O口中的任一个连接8个LED。考虑到方便连接,选用P1口输出驱动8个LED,电路图如图2-6所示。从图上可以看出,P1口引脚输出低电平时,对应的LED灯亮,输出高电平时,对应LED灯熄灭。

图2-6 流水灯硬件电路图

在图2-6中,考虑到单片机P1口的带负载能力,我们选择了发光二极管共阳极接法。另外在设计中用到了排阻RP1。8个电阻的大小、功能完全一样,加工到一个器件中,这种器件叫排阻。此处排阻起到限流的作用,阻值选择300Ω。LED的工作电流大概10mA左右,正向导通压降大概为1.7V左右,则限流电阻计算如下:

2.3.3 程序流程设计

LED流水灯电路设计完成后,还看不到LED流水的现象,因此还需要编写程序控制单片机引脚电平的高低变化,来控制LED的亮灭,实现LED流水的现象。要求8只发光二极管按一定的规律循环点亮,假设设计8个LED从上到下逐个点亮。

第一次:D1亮,D2~D7灭,则P1.7输出低电平,其他都输出高电平,P1=FEH;

第二次:D2亮,D1、D3~D7灭,P1.6输出低电平,其他都输出高电平,P1=FDH;

第三次:D3亮,D1、D2、D4~D7灭,P1.6输出低电平,其他都输出高电平,P1=FBH;

………

第八次:D8亮,P1.0输出低电平,其他都输出高电平,P1=7FH

8次P1口输出的值分别为FE,FD,FB,F7,EF,DF,BF,7F。

下面介绍三种编程方法。

1.方法一

此方法为最简单和直观的方法,只适用于灯个数较少的情况。

            /*****************************************************************************/
            #include<reg51.h>               //包含头文件,文件内包含了51单片机的功能定义
            void  Delay(unsigned int t)
            {
              unsigned int i, j;
             for(i=0;i<t;i++)
              {
                for(j=0;j<255;j++);}
              }
            }
             void main (void)
            {
              P1=0XFF;
              while(1)
              {
                P1=0XFE; Delay(1000);
                P1=0XFD; Delay(1000);
                P1=0XFB; Delay(1000);
                P1=0XF7; Delay(1000);
                P1=0XEF; Delay(1000);
                P1=0XDF; Delay(1000);
                P1=0XBF; Delay(1000);
                P1=0X7F; Delay(1000);
              }
            }
            /*****************************************************************************/

程序说明:

● 程序中加入了延时程序,主要是考虑到人眼有视觉暂留效应,而单片机的执行速度又很快,所以加入了延时程序。此延时程序含有参数,可以通过改变参数的大小来改变延时程序时间的长短。

● 程序中经常反复执行的部分可以写成一个子函数,然后就可以在程序中反复地调用。例如Delay()函数。

● 函数调用。可以把一些具有一定功能的程序打包为一个个独立的函数,用到此功能时直接调用即可。如在本节的几个程序中,主函数都调用了延时函数。函数的调用是单片机程序模块化设计的一个方法。函数的调用让C语言的单片机程序具有很强的可移植性,同时也大大简化了程序的结构。

函数调用比较简单,如本例和上一节的程序中,主函数中出现的Delay()语句就是一种函数调用,当单片机运行主函数的Delay(1000)语句时,调用延时函数Delay(unsigned int t),其中1000为延时函数的实参,t为函数的形参。在形参函数中,实参必须与形参类型统一,本例中如果t为char变量,则程序运行中会出错。

2.方法二

仔细观察8次赋给P1口的值,不难发现,这8个值是有规律的。每一个值可以由前一个循环左移一位得到。程序设计如下。

            /*****************************************************************************/
            #include<REG51.H>       //包含头文件,文件内包含了51单片机的功能定义
            #include<INTRINS.H>     //包含头文件,文件内循环左移函数的
            void  Delay(unsigned int t)
             {
              unsigned int i, j;
              for(i=0;i<t;i++)
              {
                  for(j=0;j<255;j++);
              }
             }
             void main (void)
             {
            unsigned char m;
            P1=0XFF;
            while(1)
            {
            P1=0xfe;
            for(m=0;m<8;m++)
             {
              P1=_crol_(P1,1);
              Delay(1000)
             }
            }
          }
          /*****************************************************************************/

程序说明:

在复杂的单片机程序中也常常用到文件包含。本例中程序前面的#include<reg51.h>和#include <INTRINS.H>语句都是一种文件包含形式。所谓文件包含,是指一个文件将另外一个文件的内容全部包含进来。程序使用了包含命令#include <INTRINS.H>,因为INTRINS.H头文件内有循环左移函数,程序中要使用_crol_循环左移函数是为了由上一个控制码得到下一个控制码。所以在一开始使用了包含命令#include <INTRINS.H>。

            _crol_(unsigned char val,unsigned char n);   //将变量val循环左移n位
            _irol_(unsigned int val,unsigned char n);    //将变量val循环左移n位

3.方法三

此方法为数组方法,适用于控制码毫无规律,花样流水灯。可以把每次对应的控制码预先存入数组中,程序循环读取数组中的每个控制码送往端口,就可以实现自定义花样的自由显示。

            /*****************************************************************************/
            #include <REG51.h>
            unsigned char code sz1[]={0x7e,0xbd,0xdb,0xe7,0xdb,0xbd,0x7e,0x00,0xff};
            void  Delay(unsigned int t)
             {
              unsigned int i, j;
              for(i=0;i<t;i++)
                {
                  for(j=0;j<255;j++);
                }
             }
            void main()
            {
                unsigned char i;
                while (1)
                {
                 for(i=0;i<9;i++)
                 {
                  P1=sz1[i];
                  Delay(1000);
                 }
               }
            }
            /*****************************************************************************/

程序说明:

在C语言编程中,可以将这些运行过程中不会发生变化的数据定义为code存储类型,将这些数据保存在程序内存而不是数据内存。因为数组所占空间较大,且预设后相对固定,因此sz1的存储类型设为code。如果将code改为data也不会影响程序执行,只是在程序运行时数组会被分配到数据RAM。

2.3.4 仿真调试

程序设计采用前面介绍的Keil软件。在计算机上运行Keil,首先新建一个项目工程,项目使用的单片机为AT89C51,这个项目暂且命名为lsd。然后新建一个文件,保存为“lsd.c”文件,并添加到工程项目中。直接在Keil软件界面中编写程序,也可以先把程序清单形成一个TXT文件,然后剪切到Keil的程序编辑界面中。当程序设计完成后,通过Keil编译并创建lsd.HEX目标文件。在Keil的应用过程中,由于编译过程中产生很多文件,因此新建一个项目需在一个目录中建立。

在安装过Proteus软件的PC上运行ISIS文件,即可进入Proteus电路原理仿真界面。利用该软件仿真时操作比较简单,其过程是首先构造电路,然后双击单片机加载HEX文件,最后执行仿真。Proteus界面以及本案例的仿真电路如图2-7所示。仿真过程中,单片机加载程序模拟运行实际状态。电路中单片机采用AT89C51,单片机默认为最小系统,也可以不需要再外接晶体振荡电路和复位电路。仿真时,8个LED灯从上到下逐个点亮,然后循环。

图2-7 Proteus仿真

软件仿真是程序设计结果的验证,能够在没有硬件的条件下验证程序的完整性。计算机是单片机程序设计的重要工具,但单片机的程序设计或相关产品开发必须有相关的软件和硬件,软件仿真虽然节约了一定硬件的投入,但软件仿真不能测试软件的安全性和可靠性,也不能测试电路的完整性。程序的设计往往需要软件仿真和硬件仿真相结合,并且在有限的时间内稳定完成项目的设计工作。

2.3.5 程序烧录

在单片机的开发板或自己焊接的电路板中,编制好程序后需要把程序下载到实验板或电路板中的单片机芯片内。程序下载的过程是把Keil软件生成HEX文件通过一定的接口或手段从PC保存到单片机的内部ROM中。程序下载需要专门的下载软件、下载接口或烧录器完成下载。

1.单片机的下载接口

要完成单片机程序的下载,首先要有一个单片机程序烧写器。单片机的实验板大多支持在线下载,因此在有单片机实验板的情况下,还要有一个能在PC运行的下载工具或软件。由于单片机无法直接与PC联机,因此程序下载还需要一个接口电路。常用的单片机下载接口有并口、串口和USB接口三种下载方式。随着计算机应用普及和技术发展,进来的PC已经省去了并口和串口。因此单片机的下载接口使用的USB接口较多。

不同厂商的单片机下载端口相差较大,如AT89S51采用API总线下载,需要通过专用接口电路与PC的并行口连接。STC89C51单片机采用串口下载方式,但单片机数据电压格式与PC串口输出不同,仍需要专用的下载接口电路。

(1)串口下载接口

STC89C51使用的串口下载电路由一片MAX232电平转换电路组成。MAX232为单一+5V供电,一个芯片能完成发送转换和接收转换的双重功能,如图2-8所示。

图2-8 MAX232引脚及连接图

(2)USB串行通信接口

一些芯片如PL2303、CH341等可以把PC的一个USB接口模拟一个串口,这样很方便地就可以实现单片机程序的USB接口下载。图2-9所示为经常使用的PL2303HX下载电路,图中的USB接口接PC机,R、T分别接单片机的RXD、TXD引脚。

图2-9 PL2303HX连接的USB接口下载电路

PL2303HX支持USB 1.1协议,但需要在PC上先安装PL2303HX的驱动程序。接口电路第一次接入PC时,PC会弹出一个对话框,发现新硬件并安装驱动,同时会在PC的硬件设备管理器界面增加一个串口。这时就可以利用专用的软件,利用此模拟串口下载单片机程序了。

单片机程序下载接口实际是单片机与PC之间的通信接口,在学习单片机与PC通信过程中,还需要利用到这些接口。

2.下载软件

常用的下载软件为STC-ISP,启动即出现如图2-10所示的界面。

图2-10 STC-ISP V391界面

程序的界面主要分为两个部分:左面部分为软件的烧录部分,右面提供了一些常用的工具以及软件的设置。

3.下载过程

如果采用USB接口下载,则首先在PC上安装PL2303芯片的驱动程序。在加电情况下接口电路与PC通过USB数据线连接时,PC会自动识别到新硬件并加载驱动,并会在PC硬件的端口中增加一个串口,如COM3,可以在“我的电脑”的属性下的硬件管理器中查看。USB下载接口实际通过一个串口交换数据。如果知道下载接口占用PC的哪一个串口,通过下载软件就可以下载程序了。

(1)下载软件设置

运行STC-ISP,首先在界面左上方的“MCU Type”栏中选择自己使用的单片机的型号,如STC89C51RC;然后单击“OpenFile/打开文件”按钮,在弹出的对话框中寻找要下载的HEX文件,最后设置下载端口为COM3。

① 基本设置。在“MCU Type”中有5个系列单片机的型号,分别为89C5xRC/RD+系列、12C2052系列、12C5410系列、89C16RD系列和89LE516AD系列,如图2-11所示。在左侧的“+”展开后选择目标机器上使用的MCU的具体型号。“AP Memory”中显示所选用型号的内存范围。

图2-11 选择烧录单片机的型号

COM的下拉菜单中有16个COM口。旁边的绿色灯指示串口开关情况。当端口打开时绿灯点亮。选择与单片机连接的COM口。如果对使用的串口号码不清楚,可以在打开计算机的“设备管理器”查看“端口”一项,防止端口冲突,如图2-12所示。

图2-12 设置烧录端口

② 数据波特率设置。最高波特率通过查询所连接串口的速率来确定。查看的方法是,双击单片机连接的串口,打开“通信端口(COM1)属性”对话框,选取“端口设置”选项卡,如图2-13所示。这里最高波特率选择“9600”,最低波特率不用设置。

图2-13 检查设备管理器内的端口传输速率

③ 倍速设置。这里可以选择单倍速或者双倍速、放大器的增益等项目。对于“下次冷启动P1.0,P1.1”下部的状态框有明确的说明,不再累述。一般使用默认值“与下载无关”,如图2-14所示。

图2-14 倍速设置

(2)程序下载

STC-ISP下载区域如图2-15所示,此时需要注意的是先打开“下载”按钮,再打开单片机电源,进行冷启动。一般情况下,每次需要写入时都需要遵守先“下载”后“上电”的顺序操作。操作时在信息框中反映出来工作情况,如图2-15所示。

图2-15 下载信息

复选项“当目标代码发生变化后自动调入文件,并立即发送下载命令”含义为,对第二步中所选定的文件进行检测,当发现文件被重新生成就开始下载,此时需要做的就是重新冷启动单片机,新的程序就被烧录入单片机。下载设置如图2-16所示。

图2-16 下载设置

STC-ISP在主界面的右上部还提供了几个常用的工具“文件缓冲区”、“串口调试助手”、“工程文件”等实用工具,如图2-17所示。程序烧录完成后,就可在目标板上看到现象。

图2-17 实用工具

【项目总结】

1.单片机的4个8位并行输入/输出口:P0、P1、P2、P3,这是单片机与外部电路联络的引脚。每个口都可以并行输出/输入8位数据,也可以按位使用。每个口都可以作为通用的I/O口,另外P0、P2、P3口都还有其他功能。P0口在作为通用的I/O口使用时,要外接上拉电阻。

2.在使用单片机4个I/O口时,要考虑各个口的驱动能力。一般来讲,P1~P3口引脚输出高电平时拉电流很小(约为30~60μA),属于“弱上拉”,要谨慎使用;输出低电平时,可吸收灌电流约为1.6~15mA,负载能力较强,可以直接驱动发光二极管点亮,所以较常使用。

3.单片机的存储器空间重点是掌握其结构以及片内、片外的大小和分布。

思考与练习

1.AT89C51的4个I/O口使用时有哪些分工和特点?试作比较。

2.AT89C51的4个I/O口作为输入口时,为什么要先写“1”?

3.能否把项目2的LED循环点亮改为LED双向循环点亮?

4.在C语言里,包含单片机管脚定义、特殊功能寄存器定义的头文件是哪些?