
1.3 单片机能做什么
单片机究竟能做些什么,它与数字芯片有什么关系呢?下面来回顾几个典型数字芯片实例电路,然后用单片机来实现其控制功能。
【实例1-1】 产生秒脉冲信号
方法1:用555芯片实现
在数字电路中可利用555芯片构成多谐振荡器电路产生秒脉冲。多谐振荡器电路如图1-2所示。
电路分析:
由图1-2可知,数字芯片555定时器外接电阻R1、R2和电容C1构成了一个多谐振荡器,图中电阻R1、R2和电容C1组成充电电路,电阻R2、电容C1和555芯片内的放电管T组成放电电路。在接通电源后,电源VCC通过R1和R2对电容C1充电,此时输出端OUT为高电平,充电时间常数τ =(R1+R2)C1;当电容C1两端电压充电到uC>2/3VCC时,放电管T导通,此时电容C1开始通过电阻R2和放电管T放电,输出端OUT为低电平。这一过程周而复始振荡下去,便产生如图1-2(b)所示的脉冲波。
图中输出高电平的脉冲宽度 t1由电容C1的充电时间来决定,t1=0.7(R1+R2)C1;输出低电平的脉冲宽度t2由电容C1的放电时间来决定,t2=0.7R2C1;脉冲周期t=t1+t2。

图1-2 555芯片多谐振荡器电路
由此可知,可以通过改变电阻R1、R2和电容C1的值来改变输出脉冲的宽度。
调试与仿真:
调用Proteus仿真软件,观察仿真电路运行情况,其仿真结果如图1-3所示。

图1-3 555芯片多谐振荡器电路仿真
方法2:用单片机控制实现
现在用单片机控制来完成秒脉冲,单片机控制LED电路框图如图1-4所示。

图1-4 单片机控制LED电路框图
电路分析:
由图1-4可知,只要给单片机的P1.0口送0信号,LED灯亮;送1信号,LED灯灭。如果不断反复地送0、1、0、1…信号,LED灯便可以不断循环闪烁。
编写程序:
编写C51控制源程序如下所示。
/************************************************************************** * @File:chapter 1_1.c * @Function:LED1灯间隔1s循环闪烁 *************************************************************************/ #include<reg51.h> //51系列单片机头文件 #include<stdio.h> //标准I/O库函数头文件 #define uint unsigned int //宏定义 sbit LED1=P1^0; //定义单片机P1口的第一位接LED灯 uint i,j; //定义变量 void main() //主函数 { SCON=0x52; //串口初始化打开串口窗口 TMOD=0x20; TH1=0xf3; TR1=1; printf("Program Running!\n"); //输出三行信息 printf("LED1 ON : 1s \n"); printf("LED1 OFF: 1s \n"); printf("\n "); while(1) //大循环 { LED1=0; //点亮第一个发光二极管 for(i=1000;i>0;i--) //延时1s for(j=125;j>0;j--); LED1=1; //关闭第一个发光二极管 for(i=1000;i>0;i--) //延时1s for(j=125;j>0;j--); } }

图1-5 LED1灯间隔1s循环闪烁
调试与仿真:
启用Keil软件编译、调试、运行程序,同时调出键盘、LED显示实验仿真板,在Keil开发环境中进行仿真,其仿真显示结果如图1-5所示。
通过调试程序可以发现,要想改变输出脉冲的宽度,不用修改硬件电路,只需改变调试程序里的延时函数的参数值即可,也就是实现了用软件来控制硬件电路,使电路功能的调试修改更加简单方便。
【实例1-2】 实现8个LED灯循环点亮与熄灭
方法1:用74LS194芯片实现
在数字电路中可利用两片74LS194双向移位寄存器来实现八彩灯的循环点亮与熄灭,电路原理图如图1-6所示。

图1-6 数字芯片完成8个LED轮流循环点亮与熄灭电路
电路分析:
由图1-6可知,两片74LS194芯片连接成了一个8位二进制双向移位电路,通过A、B控制端控制74LS194双向移位寄存器的方向。
(1)右移:将控制端A接低电平,B接高电平,秒信号输入端(CP)接图1-2多谐振荡器电路OUT端。接通电源,电路中的发光二极管从左至右逐个循环点亮,然后又从左至右逐个循环熄灭,依此规律不断循环。
(2)左移:关闭电源,将控制端A接高电平,控制端B接低电平,秒信号输入端(CP)接555定时器构成的秒信号发生器。再次接通电源后,与原来的显示方式不同,电路中的发光二极管从右至左逐个循环点亮,然后又从右至左逐个循环熄灭,依此规律不断循环。
调试与仿真:
调用Proteus仿真软件,观察仿真电路运行情况,其电路仿真结果如图1-7所示。

图1-7 数字芯片8个LED轮流循环点亮与熄灭电路仿真
对于上述电路,要想改变八彩灯显示花样,需要重新设计电路图才行,这样做相当麻烦,所以单一由数字芯片构成的数字电路其控制灵活性较差。
方法2:单片机控制实现
现在用单片机控制来实现8个LED轮流循环点亮与熄灭,同时通过修改程序改变显示花样和显示速度。

图1-8 单片机控制八彩灯电路框图
单片机控制八彩灯电路框图如图1-8所示。
电路分析:
由图1-8可知,要使8个LED灯循环点亮与熄灭,只需在单个LED闪烁的基础上,循环点亮或熄灭下一个LED灯即可。在这里采用数组形式定义彩灯的花样代码,每经过1s,再取下一个LED灯的花样代码,不断循环。
编写程序:
编写C51控制源程序如下所示。
/************************************************************************** * @ File:chapter 1_2.c * @ Function:8个LED轮流循环点亮与熄灭 **************************************************************************/ #include<reg51.h> //51系列单片机头文件 #include<stdio.h> //标准I/O库函数头文件 #define uint unsigned int //宏定义 #define uchar unsigned char //定义LED显示花样代码 uchar code table[4][8]={{0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00}, {0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff}, {0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01,0x00}, {0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff}} ; void delayms(); //延时函数声明 void main() //主函数 { uchar x,y; //定义变量 SCON=0x52; //串口初始化 TMOD=0x20; TH1=0xf3; TR1=1; printf("Program Running!\n"); //输出两行信息 printf("8个LED轮流循环点亮与熄灭 "); printf("\n "); while(1) //大循环 { for(x=0;x<4;x++) { for(y=0;y<8;y++) { P1=table[x][y]; delayms(); } } } } void delayms() //延时函数 { uint i,j; for(i=1000;i>0;i--) for(j=125;j>0;j--); }
调试与仿真:
启用Keil软件编译、调试、运行程序,同时调出键盘、LED显示实验仿真板,在Keil开发环境中进行仿真,其仿真显示结果如图1-9所示。

图1-9 8个LED间隔1s轮流循环点亮与熄灭显示仿真
对于上述单片机控制系统,要想改变八彩灯的显示花样,只需要通过调试程序,修改数组中定义LED显示花样中的代码值,便可以很方便地改变八彩灯的显示花样;同时通过改变延时函数中的循环参数值,可以很方便地控制花样彩灯的显示速度。
【实例1-3】 实现0~9数字计数、译码、显示
方法1:用74LS161芯片实现
在数字电路中可利用74LS161计数芯片实现数字增1计数,再通过74LS48译码器芯片译码,最后将译码得到的二进制代码送八段数码管显示,电路原理图如图1-10所示。

图1-10 数字芯片实现计数译码显示逻辑电路
电路分析:
该逻辑电路的功能是对555定时器输出的秒脉冲的个数(0~9)进行递增计数,并通过译码显示电路将所计的脉冲数显示出来。
555定时器产生秒脉冲信号,每产生一个脉冲,由74LS161计数芯片完成对秒脉冲的计数,将计数值送给74LS48译码器芯片进行译码,再通过LED数码管显示出对应的脉冲个数。
调试与仿真:
调用Proteus仿真软件,观察仿真电路运行情况,其电路仿真结果如图1-11所示。

图1-11 数字芯片0~9计数译码显示电路仿真
对于上述电路,如想改变显示结果,同样需要通过改变硬件电路才能实现。
方法2:单片机控制实现
现在用单片机控制来完成0~9数字计数译码显示。
单片机控制实现0~9数字显示电路框图如图1-12所示。
电路分析:
由图1-11可知,采用单片机控制实现0~9数字显示,只要通过单片机P0口,每经过1s送一个数字0~9的字形代码即可,0~9数字代码用数组形式定义。

图1-12 单片机控制实现0~9数字显示电路框图
编写程序:
编写C51控制源程序如下所示。
/************************************************************************** * @ File:chapter 1_3.c * @ Function:10s计数显示 **************************************************************************/ #include<reg51.h> //51系列单片机头文件 #include<stdio.h> //标准I/O库函数头文件 #define uint unsigned int //宏定义 #define uchar unsigned char uchar code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80, 0x90}; //共阳极数码管0~9字形码 void delayms(); //延时函数声明 void main() //主函数 { int num1; //定义变量 SCON=0x52; //串口初始化 TMOD=0x20; TH1=0xf3; TR1=1; printf("Program Running!\n"); //输出两行信息 printf("10秒显示 "); printf("\n "); while(1) //大循环 { for(num1=0;num1<10;num1++) { P0=table[num1]; //送字形码 P2=0xfe; //送位选码 delayms(); } } } void delayms() //延时函数 { uint i,j; for(i=1000;i>0;i--) for(j=125;j>0;j--); }
调试与仿真:
启用Keil软件编译、调试、运行程序,同时调出键盘、LED显示实验仿真板,在Keil开发环境中进行仿真,其仿真显示结果如图1-13所示。

图1-13 10秒计数显示仿真
三个典型实例总结:
用数字电路去实现某一功能,往往需要使用很多芯片,每种芯片分别完成不同的功能,然后再组合到一起实现整个电路功能。这样设计,电路很复杂、烦琐,且功能单一,灵活性差,一个电路只能完成一个功能,要想改变其功能几乎不可能实现。而用单片机实现控制,则灵活方便,硬件平台相对简单稳定,要改变实现的功能,在硬件方面改动较少时,只需增减外围电路,通过修改程序即可改变控制功能,十分易于产品功能的扩展和升级。