2.1 任务4 LED循环点亮控制
工作任务
使用STC89C52单片机,将P1口引脚接8个LED的阴极,通过程序按一定的规律向P1口引脚输出低电平和高电平,控制8只发光二极管循环点亮。
2.1.1 LED循环点亮电路设计
按照任务要求,LED循环点亮电路是由单片机最小系统和8个LED电路构成的,如图2-1所示。
8个LED采用共阳极接法,LED的阳极通过220Ω限流电阻后连接到5V电源上,P1口接LED的阴极。P1口的引脚输出低电平时,对应的LED点亮,输出高电平时,对应的LED熄灭。LED循环点亮Proteus仿真电路的设计过程与任务1基本一样,这里只给出不同的设计过程,不再赘述具体设计过程。
(1)新建设计文件,设置图纸尺寸,设置网格,保存设计文件,将文件命名为“LED循环点亮”。
(2)选取元器件。从Proteus元器件库中选取元器件:AT89C52(单片机)、CRYSTAL(晶振)、CAP(电容)、CAP-ELEC(电解电容)、RES(电阻)、LED-RED(红色发光二极管)。
(3)放置元器件,编辑元器件,放置终端,连线。按图2-1所示放置元器件并连线。
(4)属性设置。右击元器件电容C1,在弹出的“编辑元件”对话框中将电容量改为30pF,单击“确定”按钮完成元器件电容C1的属性编辑。采用同样方法编辑其他元器件属性(如修改AT89C52为STC89C52)。
图2-1 LED循环点亮电路
(5)电气规则检测。单击“工具”→“电气规则检查”,弹出检查结果窗口,完成电气检测。若检测出错,根据提示修改电路图并保存,直至检测成功。
2.1.2 LED循环点亮程序设计
LED循环点亮电路设计完成以后,还不能看到LED循环点亮的现象,需要编写程序来控制单片机引脚电平的高低变化,进而控制LED的亮灭,实现LED循环点亮。
1. LED循环点亮功能实现分析
LED循环点亮电路的LED采用共阳极接法,我们可以通过“0”和“1”来控制LED的亮和灭。例如:在P1口输出十六进制数0xfe(二进制数11111110B),D1被点亮。在P0口输出十六进制数0x7f(二进制数01111111B),则D8被点亮。LED循环点亮功能的实现过程如下所示。
(1)8个LED全灭,控制码为0xff;
(2)D1点亮,P1口输出0xfe,取反为0x01(二进制数00000001B),初始控制码为0x01;
(3)D2点亮,P1口输出0xfd,取反为0x02(二进制数00000010B),控制码为0x02;
(4)D3点亮,P1口输出0xfb,取反为0x04(二进制数00000100B),控制码为0x04;
……
(5)D8点亮,P1口输出0x7f,取反为0x80(二进制数10000000B),控制码为0x80;
(6)重复第二步,就可以实现LED循环点亮。
2. LED循环点亮控制程序设计
从以上分析可以看出,首先使所有的LED都熄灭,然后将控制码取反,从P1口输出,点亮相应的LED。控制码左移一位,即可获得下一个控制码。
LED循环点亮控制的C语言程序如下:
#include <reg52.h> //包含reg52.h头文件 void Delay() //延时函数 { unsigned char i, j; for (i=0;i<255;i++) for (j=0;j<255;j++); } void main() { unsigned char i; unsigned char temp; P1 = 0xff; //十六进制全1,熄灭所有LED while(1) { temp = 0x01; //第1位为1,即初始控制码为0x01 for (i=0;i<8;i++) { P1 = ~ temp; //temp值取反送P1口 Delay(); temp = temp << 1 ; //temp值左移一位,获得下一个控制码 } } }
在程序开始,将初始控制码取反后从P1口输出,这个数本身是让P1.0为低电平,其他位为高电平,点亮D1;然后延时一段时间,再让控制码左移一位,获得下一个控制码;之后再对控制码取反后输出到P1口,这样就实现了“LED循环点亮”效果。
再次强调,由于人眼的视觉暂留效应以及单片机执行每条指令的时间很短,在控制LED亮灭的时候应该延时一段时间,否则就看不到“LED循环点亮”的效果了。
2.1.3 LED循环点亮控制电路焊接制作
根据图2-1所示电路图,在万能板上完成LED循环点亮控制电路的焊接制作,元器件清单如表2-1所示。
表2-1 LED循环点亮控制电路元件清单
1. 电路板焊接
电路板的焊接步骤和焊接注意事项同焊接LED控制电路一样。焊接好的电路板如图2-2所示。
图2-2 LED循环点亮控制焊接电路板
2. 硬件检测与调试
上电之前,先检测一下焊接好的LED循环点亮电路板,与任务2的检测方法一样。
上电后,按下复位按键,检测STC89C52单片机P1口和8个LED阴极是否为高电平,如果是,说明单片机工作正常,P1口到8个LED阴极之间的通路也正常。同时,检测8个LED阳极也应有5V左右的电压,如果没有,再检测5V电源至LED阳极之间的电路是否存在短路。
3. 软件下载与调试
通过stc-isp下载软件,把“LED循环点亮.hex”文件烧入单片机芯片中。如果LED运行结果与设计功能相符,说明上面的焊接过程和程序均正常,否则需进行调试,直到功能实现。软件下载、调试的步骤请参照任务2,不再赘述。
2.1.4 并行I/O端口电路
单片机有4组8位并行I/O端口,称为P0口、P1口、P2口和P3口,每个端口又各有8条I/O口线,每条I/O口线都能独立地用作输入或输出。P0口负载能力为8个TTL门电路,P1口、P2口和P3口负载能力为4个TTL门电路。实际上,它们已被归入特殊功能寄存器之列,并且具有字节寻址和位寻址功能。
1. P0口
P0口某位结构图如图2-3所示,由1个数据输出锁存器(D触发器)、2个三态数据输入缓冲器、1个输出控制电路和1个输出驱动电路组成。输出控制电路由1个多路开关MUX、1个与门及1个非门组成,输出驱动电路由一对场效应管(VT1和VT2)组成,其工作状态受输出控制电路的控制。
图2-3 P0口某位结构图
P0口有两种功能:通用I/O口和地址/数据分时复用总线。
(1)P0口作通用I/O口使用
P0口作为通用的I/O口使用时,内部的控制信号为低电平,封锁与门,将输出驱动电路的上拉场效应管(VT1)截止,同时使多路开关MUX接通锁存器Q端的输出通路。
注意
当P0口进行一般的I/O输出时,由于输出电路是漏极开路电路,因此必须外接上拉电阻才能有高电平输出;当P0口进行一般的I/O输入时,必须先向电路中的锁存器写入“1”,使场效应管(VT2)截止,以避免锁存器为“0”时对引脚读入的干扰。因为如果VT2管是导通的,不论P0.X引脚上的状态如何,输入都会是低电平,将导致输入错误。
(2)P0口作地址/数据分时复用总线使用
当P0口输出地址或数据时,由内部发出控制信号,打开上面的与门,并使多路开关MUX将内部地址/数据线与驱动场效应管(VT2)接通。输出驱动电路与上、下两个驱动场效应管处于反相,形成推拉式电路结构,使负载能力大为提高。
若地址/数据线为1,则VT1导通,VT2截止,P0口输出为1;反之VT1截止,VT2导通,P0口输出为0。当输入数据时,读引脚使三态数据输入缓冲器打开,数据信号直接从引脚通过数据输入缓冲器进入内部总线。
2. P1口
P1口某位结构图如图2-4所示。P1口是一个双向8位I/O口,每一位均可单独定义为输入或输出口。
图2-4 P1口某位结构图
P1口通常作为通用I/O口使用,在电路结构上与P0口有一些不同之处:首先,它不再需要多路开关MUX;其次,电路的内部有上拉电阻,与场效应管共同组成输出驱动电路。为此,P1口作为输出口使用时,已经能向外提供推拉电流负载,无需再外接上拉电阻。
当作为输出口时,将1写入锁存器,Q(非)=0,场效应管截止,内部上拉电阻将电位拉至1,此时该口输出为1;将0写入锁存器,Q(非)=1,场效应管导通,输出则为0。当作为输入口时,必须先向锁存器写入1,Q(非)=0,场效应管截止,此时该位既可以把外部电路拉成低电平,也可以由内部上拉电阻拉成高电平。
3. P2口
P2口某位结构图如图2-5所示,它由1个数据输出锁存器(D触发器)、2个三态数据输入缓冲器、1个多路开关MUX、1个数据输出驱动电路和1个控制电路组成。
P2口电路比P1口电路多了1个多路开关MUX,这正好与P0口一样。P2口可以作为通用I/O口使用,这时多路开关MUX倒向锁存器Q端。在实际应用中,P2口通常作为高8位地址线使用,此时多路开关MUX应倒向相反方向。
图2-5 P2口某位结构图
在无外部扩展存储器的系统中,4个I/O口都可以作为通用I/O口使用。
在有外部扩展存储器的系统中,P2口送出高8位地址AB8~AB15,P0口分时送出低8位地址AB0~AB7和8位数据D0~D7。由于地址有16位,MCS-51单片机最大可外接64KB程序存储器和64KB数据存储器。
4. P3口
P3口某位结构图如图2-6所示。P3口除了作为通用I/O口使用,每一根线还具有第二功能。
P3口的第一功能和P1口一样,可作为输入/输出端口,同样具有字节操作和位操作两种方式,每一位均可定义为输入或输出。
图2-6 P3口某位结构图
P3口的特点:为适应引脚的第二功能的需要,增加了第二功能控制逻辑。在真正的应用电路中,第二功能显得更为重要。由于第二功能信号有输入、输出两种情况,因此分以下两种情况加以说明。
(1)对于第二功能为输出的信号引脚,当作为I/O使用时,第二功能信号引线应保持高电平,与非门开通,以维持从锁存器到输出端数据输出通路的畅通。当输出第二功能信号时,该位的锁存器应置“1”,使与非门对第二功能信号的输出是畅通的,从而实现第二功能信号的输出。
(2)对于第二功能为输入的信号引脚,在第二功能的输入电路上增加了一个缓冲器,输入的第二功能信号就从这个缓冲器的输出端取得。而作为I/O使用的数据输入,仍取自三态缓冲器的输出端。不管是作为输入口使用还是作为第二功能信号输入,输出电路中的锁存器输出和第二功能输出信号线都应保持高电平。
P3口的第二功能定义如表2-2所示。
表2-2 P3口第二功能定义
【技能训练2-1】P0口外接上拉电阻
任务3通过程序按一定规律向P1口的引脚输出低电平和高电平,实现LED循环点亮。如果改为通过P0口完成LED循环点亮,那么我们应该如何实现?
1. P0口和P1口对比分析
(1)由于P0口输出电路是漏极开路电路,所以在进行输出时,必须外接上拉电阻才能有高电平输出。
(2)由于P1口输出电路有上拉电阻,所以P1口在作为输出口使用时,无须再外接上拉电阻。
2. P0口LED电路设计
本电路设计与任务3的LED循环点亮电路基本一样,差别是使用了排阻、P0口接LED的阴极,以及在P0口和LED阴极之间外接了上拉电阻,如图2-7所示。
8个电阻的功能完全一样,将它们加工到一个器件里面,这个器件通常称之为排阻。为了在电路板上占很小的地方,方便安装和生产,在电路设计时常常选择排阻。
PR1和PR2都是排阻,阻值分别为8×4.7kΩ和8×220Ω。PR1排阻是上拉电阻,其功能是在这个引脚没有信号的时候,起到电位上拉的作用。PR2和普通的电阻用途没有任何不同,起到限流作用,使通过LED的电流被限制在十几个毫安左右。
图2-7 P0口LED循环点亮电路
3. P0口LED程序设计
本程序设计与任务3的LED循环点亮程序基本一样,差别如下:
void main() { …… P0 = 0xff; //熄灭所有LED …… P0 = ~temp; //temp 值取反送P0口 …… }