文档库 最新最全的文档下载
当前位置:文档库 › 第4章 程序设计

第4章 程序设计

第4章 程序设计
第4章 程序设计

第4章单片机程序设计

4.1 单片机程序设计概述 (1)

4.1.1 MCS-51单片机的编程语言 (1)

4.1.2 源程序的编辑、汇编和调试 (1)

4.1.3 程序编制的步骤和方法 (2)

4.2基本程序结构 (3)

4.2.1 顺序程序设计 (3)

4.2.2 分支(选择)程序设计 (4)

4.2.3 循环程序设计 (4)

4.2.4 子程序设计 (4)

4.1 单片机程序设计概述

4.1.1 MCS-51单片机的编程语言

目前程序设计语言主要有汇编语言和C语言。其中汇编语言是最基本和最常用的编程手段,而C语言则是单片机程序设计的主要发展趋势。

汇编语言有如下特点:

1、用汇编语言编写的程序效率高,占用存储空间小,运行速度快,因此汇编语言能编写出最优化的程序。

2、使用汇编语言编程比使用高级语言困难。因为汇编语言是面向计算机的,汇编语言的程序设计人员必须对计算机硬件有相当深入的了解。

3、汇编语言能直接访问存储器及接口电路,也能处理中断,因此汇编语言程序能直接管理和控制硬件设备。

4、汇编语言缺乏通用性,程序不易移植,各种计算机都有自己的汇编语言,不同计算机的汇编语言之间不能通用。

C语言有如下特点:

编译器能自动完成变量的存储单元的分配,编程者可以专注于应用软件的设计,可以对常用的接口芯片编制通用的驱动函数,对常用的功能模块和算法编制相应的函数,可以方便地进行信号处理算法和程序的移植,从而加快单片机应用系统的开发速度。当代码长度超过4KB以上时,C51比汇编语言更具有明显的优势。

但是高级语言生成的目标程序代码较长,导致应用程序运行速度较慢,这与实时控制应用所要法语的快速响应存在很大的矛盾。也正因为如此,单片机的汇编语言不但不会被高级语言完全取代,而且还将继续占据重要地位。

因此,即便是对那些只想使用C语言进行单片机程序设计的读者来说,了解和懂得单片机的指令系统和汇编语言也是十分有用的。

4.1.2 源程序的编辑、汇编和调试

一、源程序的编辑

源程序的编写要依据80C51汇编语言的基本规则,特别要用好常用的汇编命令(即伪指令),例如下面的程序段:

ORG 0040H

MOV A,#7FH

MOV R1,#44H

END

这里的ORG和END是两条伪指令,其作用是告诉汇编程序此汇编源程序的起止位置。编辑好的源程序应以“ . ASM”扩展名存盘,以备汇编程序调用。

二、源程序的汇编

将汇编语言源程序转换为单片机能执行的机器码形式的目标程序的过程叫汇编。常用的方法有两种:

手工汇编时:把程序用助记符指令写出后,通过手工方式查指令编码表,逐个把助记符指令翻译成机器码,然后把得到的机器码程序(以十六进制形式)键入到单片机开发机中,并进行调试。

机器汇编:是在常用的个人计算机PC上,使用交叉汇编程序将汇编语言源程序转换为机器码形式的目标程序。生成的目标程序由PC机传送到开发机上,经调试无误后,再固化到单

片机的程序存储器ROM中。

现在没有用手工汇编的,都用机器汇编。

源程序经过机器汇编后,形成的若干文件中含有两个主要文件,一是列表文件,另一个是目标码文件。因汇编软件的不同,文件的格式及信息会有一些不同。但主要信息如下:列表文件:

地址目标码汇编程序

ORG 0040H

0040H 747F MOV A,#7FH

0042H 7944 MOV R1,#44H

END

目标码文件:

首地址末地址目标码

0040H 0044H 747F7944

三、源程序的调试

源程序通过汇编、连接获得目标代码后,仅仅代表你的源程序没有语法错误,至于源程序中存在着的其它错误,必须通过调试才能发现并解决,事实上,除了极简单的程序以外,绝大部分程序都是通过反复调试才能得到正确的结果,因此,调试是软件开发中重要的一个环节。

4.1.3 程序编制的步骤和方法

一、汇编语言程序设计步骤

(1)分析问题,确定算法

(2)根据算法,画出程序框图

(3)分配内存工作区及有关端口地址

(4)编写程序。养成在程序的适当位置上加上注释的好习惯。

(5)上机调试。编写完毕的程序,必须“汇编”成机器代码,才能调试和运行,调试与硬件有关程序还要借助于仿真开发工具并与硬件连接。

MCS-51单片机的应用程序的完成,应经过三个步骤;

(1)在微计算机上,运行编辑程序进行源程序的输入和编辑;

(2)对源程序进行交叉汇编得到机器代码;

(3)通过微计算机的串行口(或并行口)把机器代码传送到用户样机(或在线仿真器)进行程序的调试和运行。

第(1)步,只需在微计算机上使用通用的编辑软件即可完成。

第(2)步的交叉汇编所用的汇编程序可在购买单片机的仿真开发工具时,由厂商提供。

第(3)步骤的实现要借助于单片机仿真开发工具进行。

反汇编——分析现成产品的程序,要将二进制的机器代码语言程序翻译成汇编语言源程序。

二、采用模块化(结构化)程序设计方法

应用系统的程序由包含多个模块的主程序和各种子程序组成。各程序模块都要完成一个明确的任务,实现某个具体的功能,如:发送、接收、延时、打印和显示等。

模块化的程序设计方法具有明显的优点,把一个多功能的复杂的程序划分为若干个简单的、功能单一的程序模块,有利于程序的设计和调试,有利于程序的优化和分工,提高了程序的阅读性和可靠性,使程序的结构层次一目了然。

?????

??

??中断服务子程序结构

子程序结构循环结构

分支结构顺序结构模块化设计 三、尽量采用循环结构和子程序

采用循环结构和子程序可以使程序的长度减少、占用内存空间减少。多重循环,注意各重循环的初值和循环结束条件,避免出现 “死循环”现象;通用的子程序,除了用于存放子程序入口参数的寄存器外,子程序中用到的其它寄存器的内容应压入堆栈进行现场保护,并要特别注意堆栈操作的压入和弹出的平衡;中断处理子程序除了要保护程序中用到的寄存器外,还应保护标志寄存器。 四、绘制程序流程图

清晰正确的流程图是编制正确无误的应用程序的基础和条件。所以,绘制一个好的流程图,是程序设计的一项重要内容。

流程图可以分为总流程图和局部流程图。总流程图侧重反映程序的逻辑结构和各程序模块之间的相互关系。局部流程图反映程序模块的具体实施细节。对于简单的应用程序,可以不画流程图。但是当程序较为复杂时,绘制流程图是一个良好的编程习惯。

常用的流程图符号有:开始和结束符号、工作任务符号、判断分支符号、程序连接符号、程序流向符号等

开始或结束符号

工作任务符号

判断分支符号

程序连接符号程序流向符号

程序流向符号

4.2基本程序结构 4.2.1 顺序程序设计

顺序程序是指无分支、无循环结构的程序。其执行流程是依指令在存储器中的存放顺序进行的。

ORG 1000H

START : MOV R0, #60H MOV A , 40H MOV B , #100 …… END

4.2.2 分支(选择)程序设计

分支结构可以分成单分支、双分支和多分支几种情况:

可实现单分支转移的指令有JZ 、JNZ 、CJNE 、DJNZ 等,此外还有以位状态作为条件进行分支的指令,包括JC 、JNC 、JB 、JNB 、JBC 等。使用这些指令,可以完成为0、为1、为正、为负、以及相等、不相等等等名种分支条件判断。

多分支程序结构中没有专门的多分支转移指令,可通过查表指令实现多分支转移,但需要有数据表格配合。 4.2.3

循环程序设计

按某种控制规律重复执行的程序称为循环程序。循环程序有先执行后判断和先判断后执行两种基本结构 :

4.2.4 子程序设计 一、子程序的调用

在实际应用中,经常会遇到一些带有通用性的问题,例如:数值转换、数值计算等,在一个程序中可能要使用多次。这时可以将其设计成通用的子程序供随时调用。

子程序主要特点是,在执行过程中需要由其它程序来调用,执行完后又需要把执行流程返回到调用该子程序的主程序。

MAIN:┇;MAIN为主程序或调用程序标号

LCALL SUB ;调用子程序SUB

SUB:PUSH PSW ;现场保护

PUSH ACC ;

┇;子程序处理程序段

POP ACC ;现场恢复

POP PSW ;

RET ;最后一条指令必须为RET

子程序调用时要注意两点:一是现场的保护和恢复;二是主程序与子程序的参数传递。二、现场保护与恢复

在子程序执行过程中常常要用到单片机的一些通用单元,如工作寄存器R0~R7、累加器A、数据指针DPTR,以及有关标志和状态等。而这些单元中的内容在调用结束后的主程序中仍有用,所以需要进行保护,称为现场保护。

在执行完子程序,返回继续执行主程序前恢复其原内容,称为现场恢复。

保护与恢复的方法有以下两种:在主程序中实现;在子程序中实现。

1、在主程序中实现

示例如下:

PUSH PSW ;保护现场

PUSH ACC ;

PUSH B ;

MOV PSW,#10H ;换当前工作寄存器组

LCALL addr16 ;子程序调用

POP B ;恢复现场

POP ACC ;

POP PSW ;

… …

其特点是结构灵活。

2、在子程序中实现

示例如下:

SUB1:PUSH PSW ;保护现场

PUSH ACC ;

PUSH B ;

… …

MOV PSW,#10H ;换当前工作寄存器组

… …

POP B ;恢复现场 POP ACC ; POP PSW ; RET

其特点是程序规范、清晰。

注意,无论哪种方法保护与恢复的顺序要对应。 三、参数传递

由于子程序是主程序的一部分,所以,在程序的执行时必然要发生数据上的联系。在调用子程序时,主程序应通过某种方式把有关参数(即子程序的入口参数)传给子程序,当子程序执行完毕后,又需要通过某种方式把有关参数(即子程序的出口参数)传给主程序。

??

?

??。:。:。,:嵌套时采用传递数据较多或子程序利用堆栈传递数据较多时采用利用存储器可获得较快传递速度传递数据较少时采用利用累加器或寄存器

参数传递

利用累加器或寄存器

在这种方式中,要把预传递的参数存放在累加器A 或工作寄存器R0~R7中。即在主程序调用子程序时,应事先把子程序需要的数据送入累加器A 或指定的工作寄存器中,当子程序执行时,可以从指定的单元中取得数据,执行运算。反之,子程序也可以用同样的方法把结果传送给主程序。 利用存储器

当传送的数据量比较大时,可以利用存储器实现参数的传递。在这种方式中,事先要建立一个参数表,用指针指示参数表所在的位置。当参数表建立在内部RAM 时,用R0或R1作参数表的指针。当参数表建立在外部RAM 时,用DPTR 作参数表的指针。 利用堆栈

利用堆栈传递参数是在子程序嵌套中常采用的一种方法。在调用子程序前,用PUSH 指令将子程序中所需数据压入堆栈,进入执行子程序时,再用POP 指令从堆栈中弹出数据。

相关文档