购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

3.10 从单片机最简系统开始设计

单片机最简系统是单片机工作的最小化硬件平台,在这个平台上通过“添枝加叶”就形成了形形色色的单片机系统。至于如何添加各种模块构成功能系统,后面会慢慢展开,这里我们先向最简系统添加两个发光二极管开始,学习单片机是如何控制外设的。

3.10.1 发光二极管交替发光

谈设计前必须对须求进行分析:将要设计一个单片机控制系统,如图3-40所示,单片机控制发光二极管1和发光二极管2交替发光,交替的时间间隔为500ms。

虽然需求很简单,系统框图也不复杂,但是在设计中养成需求分析和画系统框图的习惯非常重要。因为外设为两支发光二极管,所以可以在最简系统基础上添加这两个外设,并给每个发光二极管串联一个限流电阻,如图3-41所示。两支发光二极管的负极分别与单片机的P0.4口(35管脚)和P2.0口(21管脚)相连,如果这两个I/O口为高电平,发光二极管不发光,而如果I/O口为低电平,发光二极管发光。

图3-40 单片机控制发光二极管交替发光系统框图

图3-41 单片机控制发光二极管交替发光系统电路图

3.10.2 程序设计

当如图3-41所示的电路在面包板或万用板中搭建出来后,还并不能马上实现两支发光二极管交替发光的功能。因为单片机中还没有程序,它现在“脑子里一片空白”,并不能控制发光二极管。

于是我们需要写一段程序,把控制的意图让单片机去执行。这段程序所要表达的操作流程如图3-42所示,一开始,令P0.4=0、P2.0=1,这样,发光二极管D1点亮而D2熄灭。延时500ms使得这个状态保持500ms,接着P0.4=1、P2.0=0,发光二极管D1熄灭而D2点亮,再保持这个状态500ms后回到一开始的D1点亮而D2熄灭。以此循环,发光二极管D1、D2就在不断的交替发光。

图3-42 单片机控制发光二极管交替发光操作流程

前面说过可使用汇编或C51语言来书写单片机程序,如图3-42所示的流程如果用汇编语言来描述可得到程序3-1。这是我们接触的第一个单片机程序,程序的每一行都是一条指令,先来看看阴影部分的主程序是如何与图3-42所示的操作流程对应的。

首先标号“MAIN:”表明这是程序的主程序段,接下来的指令“MOV P0,#00H”把立即数00H(十六进制数),也就是0000 0000(对应的二进制数)从P0口输出,单片机执行完这条指令后P0口上全部为0,即低电平。自然P0.4=0,于是发光二极管D1点亮。

接着,指令“MOV P2,#0FFH”则把立即数FFH(十六进制数),也就是1111 1111 (对应的二进制数)从P2口输出,单片机执行完这条指令后P2口上全部为1,即高电平。自然P2.0=1,于是发光二极管D2不亮。

经过以上两条“MOV”指令后,发光二极管已经实现了D1亮、D2灭的状态。接着指令“CALL DELAY”是调延时子程序的指令,单片机根据“CALL”后面的操作数“DELAY”到程序的后半部分的标号“DELAY:”处开始执行延时500ms的操作。在此期间发光二极管D1、D2保持原有状态不变。

500ms后,单片机又跳回主程序“MAIN:”中“CALL DELAY”的下一行继续执行。这次,指令“MOV P0,#0FFH”使得P0口全部为1,于是发光二极管D1熄灭;而指令“MOV P2,#00H”使得P2口全部为0,于是发光二极管D2点亮。

经过以上两条“MOV”指令后,两支发光二极管状态对调,原来点亮的D1熄灭,而原来熄灭的D2点亮。接着又是一条调延时子程序的指令“CALL DELAY”,D1、D2的状态又将保持500ms。

最后,当单片机执行指令“JMP MAIN”时,就会根据“JMP”后面的操作数“MAIN”跳转到主程序“MAIN:”一开始循环执行程序。

可见,单片机将会不断循环地执行程序3-1。如果把程序3-1下载到单片机(下一章会介绍下载方法),就会在实际系统中观察到发光二极管D1、D2,以500ms为间隔进行交替发光。

程序3-1:单片机控制发光二极管交替发光(对应图3-42)

指令小贴士:

3.10.3 初见汇编语言

程序3-1是一个用汇编语言书写的单片机程序,它以伪指令ORG和END为开始和结束的标志。如图3-43所示,伪指令只是告诉汇编器(把汇编语言转换成单片机“认识”的代码的工具)一些汇编的信息,对单片机的操作没有影响。真正指挥单片机干活的是从“MAIN:”开始到“END”之前的多行指令。

图3-43 汇编语言书写的单片机程序

3.10.4 初识指令

汇编程序中除了标号以外每一行都是一条指令,每一条指令都指挥着单片机完成一个操作。比如程序3-1中主程序段里的第1行指令“MOV P0,#00H”,实现将立即数00H从单片机的P0口输出,执行完这条指令后,单片机的8个P0口全为低电平。如果在图3-41中,则与P0口相连的发光二极管被点亮。

指令一般由助记符、目的操作数、源操作数、注释(有时可省略)组成,如图3-44所示,有时还为某条指令或某段程序添加标号。汇编语言对字母的大小写不敏感,但习惯上程序中都使用大写字母。接下来我们对这些组成部分解释一下。

图3-44 指令的组成

· 标号——以英文字母开头的字符串,用于指向某条指令的地址。例如“LOOP_1:”、“START:”、“KEY2”等都可作为标号。在设计程序时,尽量用具有实际含义的标号来提示程序或指令的功能。比如在延时子程序中常常用延时的英文单词“DELAY”作为标号。另外,标号可以和其他指令在同一行,也可以单独为一行。

· 助记符——表达指令的功能。比如图3-44中助记符“MOV”是移动的单词“Move”的缩写,其功能是把源操作数“移入”或者“载入”目的操作数中。

· 目的操作数——指令最终作用的对象。一条指令执行过后最终影响的是目的操作数。

· 源操作数——参与指令的操作。指令的执行将使用到源操作数,如图3-44中的指令把源操作数00H载入目的操作数P0口。在源操作数中的“#”号代表其后的00H (十六进制数)是一个立即数,表明该指令的源操作数由一个立即数充当。立即数可以暂时理解为一个常数。注意目的操作数和源操作数之间有“,”号分隔。

· 注释——是为了他人或自己阅读程序时方便而标记的。汇编程序中,“;”号之后的部分都是注释,不会被单片机执行。注释可提高程序的可读性和调试的方便性,也就是说,注释只是用来装装门面,并不是可执行程序的一部分。

3.10.5 立即数

在如图3-44所示指令中,立即数00H是一个十六进制数,“H”是十六进制数(hex)特有的后缀。在汇编语言中,十六进制数后面必须附上H,否则将认为十进制数。如果十六进制数以字母A、B、C、D、E、F开头时,应该在前面加上0。例如,十六进制数B7H,在指令中应当写成0B7H,如“MOV P1,#0B7H”。

如果把十六进制的立即数转换成二进制数,就可知道指令所影响目的操作数每一位的情况。比如指令“MOV P0,#00H”,立即数00H转换成二进制数为0000 0000,所以指令把这8个0载入P0口,于是图3-41中8个P0口都出现低电平。有时为了直观,可把二进制数作为立即数,但是需要在后面加上B,如“MOV P0,#00000000B”。在数字基础中我们知道,二进制数由1和0组成,每一个二进制数称为一个位(bit),8个位构成1个字节(byte)。如二进制数1001 1100有8位,即长度是1个字节。立即数长度通常都为1个字节。

当然,立即数也可以由十进制数充当,比如“MOV P0,#23”实现把十进制数23载入P0寄存器中,执行后P0口的状态为0001 0111(十进制数23对应的二进制数)。表3-3是几种常用数制的换算关系。

表3-3 十进制、二进制、十六进制 ADFf7TBZwM0uexXwJmNcE21ulearOjOhtVS417E510lKgUUZfwGxT37ZOmV+GL6B

点击中间区域
呼出菜单
上一章
目录
下一章
×