当前位置:机电之家首页 >> 电工园地>> 电工知识 >> 弱电系统工程 >> 8051单片机模块化编程技巧
8051单片机模块化编程技巧

目前在8051应用开发中主要有两种编程语言:和c51 语言。c51 语言是一种结构化的编程语言,采用c51 编写的应用程序结构清晰、模块化程度高、可读性强、并容易移植。但c51 语言也有缺点,就是编译后生成的目标代码空间要比汇编的大。

而且目前单片机的教材还是侧重于汇编语言。因此学习用单片机汇编语言程序进行结构化设计还是很有必要的。我们知道c51 语言是函数式语言,其程序由函数构成,每一个源程序有且只有一个主函数main() 和若干个函数组成。其中每一个函数都用于完成某一特定任务。也就是说,一个项目若具有几个功能,实现这些功能就会需要由若干个任务来完成,那么它的源程序中就会有若干个或以上的函数。而在汇编语言中,源程序中只有程序和子程序。那么我们能否以子程序为基本单位,用一个子程序实现一种功能来做到模块化编程呢?实践证明是可行的。但在编制程序中不要忘记汇编语言的特点,注意子程序之间对单片机资源的使用,避免不同子程序交叉共用同一资源引起程序的错误执行。子程序嵌套调用的级数等。本文以“60秒倒计时电路”为例谈一谈51 单片机汇编语言模块化编程的一点技巧。

一、60秒倒计时电路及编程

1. 功能要求

所谓倒计时,就是首先给定一个初始值,然后对初始值进行减“1”操作,直到该值为“0”为止。60 秒倒计时就是对给定的初始值“60”每隔1 秒钟对其进行减“1”,一直减到该值为“0”为止。

该倒计时电路要求有两个按钮。一个是“复位”按钮,按下按钮设置倒计时初始值,并把指示灯熄灭;另一个是“开始”按钮,按下按钮开始倒计时。并用两位led 数码管显示当前倒计时值。计时时间到,指示灯点亮。

2. 电路组成

实现上述功能要求的单片机接口电路如图1 所示。

图1 单片机接口电路

图中用按钮sb1 作为“置初值”按钮,按钮sb2 作为“开始”按钮。按下sb1 按钮,将显示值设置为“60”。

按下按钮sb2,每隔一秒显示值减“1”,直到值为“0”

停止计数。按钮和指示灯接在p0 口上,p0.0 为初始按钮,p0.1 为开始按钮,p0.7 为指示灯。十位led 数码管接p2 口,个位led 数码管接p1 口。图2 为单片机基本系统电路。

图2 单片机基本系统电路

3. 功能分析

根据60 秒倒计时的功能要求,需要单片机完成以下任务:

⑴ 按键扫描。用来判断有没有键被按下,是哪个键被按下?根据不同的键,给出相应的键值。

⑵ 计时显示。这里时间值使用的是两位数,故需要将被显示的时间值取出个位数和十位数,然后才能进行显示。

⑶ 被显示数转换成7 段码。由于单片机中的数据都是以二进制形式存放或运算的。而这里输出显示使用了两位led 数码管来显示计时数值的,一个被显示的数要点亮数码管的某几段才能显示出这个数,不同的数需要点亮数码管的不同段。因此需要将被显示的这个数转换成相应的显示段码,才能被正确显示出来。

⑷ 延时。包括1秒钟延时和按键消抖的10毫秒延时。

⒋ 程序编制

程序按实现功能采用模块化结构,有一个主程序和若干个子程序组成。每个子程序分别是完成某个任务的独立模块,有时会用到调用参数。本实例共有5 个子程序,分别是按键扫描子程序、10ms 延时子程序、1s 延时子程序、显示子程序、取段码子程序。

⑴ 按键扫描子程序

按键扫描子程序完成对按键进行扫描,确定有没有键被按下,当有键被按下并抬起后将相关键值返回给主程序的任务。其流程如图3 所示。该子程序没有入口参数,但有一个出口参数,即按键的键值,存放在寄存器r3 中。寄存器r3 中的值为“60h”表示sb1 键被按下;寄存器r3 中的值为“00h”表示sb2 键被按下。

图3 按键扫描子程序流程图

按照图3 的流程图和51 单片机的指令系统编制的子程序如下:

;----------- 按键扫描描--------------

; 出口参数键值存放在寄存器r3 中,用于识别哪个键。

;r3=60h, 说明sb1 被按下;r3=00h, 说明sb2 被按下

key_scan: jnb kb_init, k1check ; sb1 按下转移

jnb kb_begin, k2check ; sb2 按下转移

sjmp ksr ;

k1check: acall del10 ; 调用毫秒延时,去抖

jb kb_init, ksr ; 干扰,返回

jnb kb_init,$ ; 等待按键释放

mov r3, #60h; 是sb1,键值“60h”送寄存器r3

sjmp ksr ; 是,不进行任何操作返回

k2check: acall del10 ; 调用毫秒延时,去抖

jb kb_begin, ksr ; 干扰,返回

jnb kb_begin,$ ; 等待按键释放

mov r3, #00h; 是sb2,键值“00h”送寄存器r3

ksr: ret ; 返回

;---------------------------------

⑵ 显示子程序

显示子程序完成从被显示值中取出十位数将其转换成显示断码,并送单片机的p2 口;从被显示值中取出个位数将其转换成显示断码,并送单片机的p1 口任务。其流程如图4 所示。该子程序有一个入口参数,即被显示的值,存放在寄存器r2 中。

图4 显示子程序流程图

按照图4 的流程图和51 单片机的指令系统编制的子程序如下:

;------------ 显示子程序------------

; 入口参数存放在寄存器r2 中

display:mov a, r2 ; 取被显示值

mov b, #10; 取被显示值的十位数

div ab;

acall seg7; 调用转换子程序,取显示断码

mov p2, a ; 十位数段码送p2 口

mov a, b; 取个位数

acall seg7 ; 调用转换子程序,取显示断码

mov p1, a ; 个位数段码送p1 口

ret ; 返回

;---------------------------------

⑶ 取段码子程序

取段码子程序完成将被显示的数转换成7 段共阳led 数码管对应数的段码的任务。其流程如图5 所示。

图5 取段码子程序流程图

该子程序有一个入口参数和一个出口参数。入口参数就是被显示的数,出口参数就是该数的段码(相应位=0表示亮),都存放在累加器a 中。

按照图5 的流程图和51 单片机的指令系统编制的子程序如下:

;-------------- 取段码--------------

; 对累计器a 中的值由查表得到显示断码

; 入口和出口参数存放在累计器a 中

seg7: inc a ; 取被显示数,累加器a 加1

movc a, @a+pc ; 查表

ret ; 返回

db 0c0h,0f9h,0a4h,0b0h;0123

db 99h,92h,82h,0f8h;4567

db 80h,90h,88h,83h;89ab

db 0c6h,0a1h,86h,8eh;cdef

;---------------------------------

⑷ 延时子程序

延时子程序完成一定的延时时间任务。这里有两个延时时间不同的子程序(也可以调用100 次10ms 做1s 延迟),其流程如图6 所示。延时子程序没有入口和出口参数。

图6 延时子程序流程图

按照图6 的流程图和51 单片机的指令系统编制的子程序如下;

;----------- 延时10ms 程序----------

; 用到寄存器组1 中的r6 和r7 寄存器

del10: setb psw.3 ; 切换至第1 组寄存器

mov r7, #0bh ;

dl1: mov r6, #0ffh ;

dl2: djnz r6, dl2 ;

djnz r7, dl1;

clr psw.3 ; 切换至第0 组寄存器

ret ;

;---------------------------------

;------------- 延时1s 程序-----------

; 用到寄存器组1 中的r1、r2 和r3 寄存器

del1s: setb psw.3 ; 选用寄存器区1

mov r1 , #46; 立即数46 送寄存器r1

del0: mov r2 , #100; 立即数100 送寄存器r2

del1: mov r3 , #100 ; 立即数100 送寄存器r3

djnz r3 , $ ; 寄存器r3 中的内容减1,不为零转移到当

前指令

djnz r2 , del1; 寄存器r2 中的内容减1,不为零转移到

del1

djnz r1 , del0; 寄存器r1 中的内容减1,不为零转移到

del0

clr psw.3 ; 选用寄存器区0

ret ; 子程序返回

;---------------------------------

⑸ 主程序编制

主程序需要实现的功能是:完成单片机端口定义;初始化任务;调用键扫描子程序,根据按键状态实现置初值或进行倒计时,并调用显示子程序等。其流程如图7 所示。

图7 主程序编制流程图

按照图7 的流程图和51 单片机的指令系统、以上编制的各子程序,主程序如下:

;**********************************************************

; 文件名:counter.asm 功能:60 秒倒计时

; 说明:p2 和p1 口分别接一个led 数码管, 显示两位

十进制数。

; p0.0 和p0.1 口接置初值按钮和开始倒计时按钮,p0.7

接提示led。

; 晶振频率11.0592mhz.

;**********************************************************

;------------ 端口定义--------------

kb_init bit p0.0 ; 置初值按钮定义

kb_begin bit p0.1 ; 开始按钮定义

warn bit p0.7 ; 提示

;---------------------------------

org 0000h

ajmp begin

;============ 主程序===============

org 00b0h

begin:

mov sp, #50h ; 初始化

mov p0, #0ffh

mov p1, #0ffh

mov p2, #0ffh

mov r2, #60

mov r3, #0ffh

main:

lcall key_scan ; 按扫描键

mov a, r3 ; 取返回值

cjne a, #60h, lp1 ; 非sb1 按键转移

mov r2, #60 ; 初值送寄存器r2

setb p0.7 ; 清指示灯

acall display ; 调显示子程序

ajmp main ; 转移

lp1: mov a, r3 ; 取返回值

cjne a, #00h, main ; 非sb2 按键转移

setb p0.7

mov r2, #60

lp2: acall display

acall del1s ; 调用1 秒延时子程序

dec r2

cjne r2, #00h,lp2

acall display

clr p0.7

mov r3, #0ffh

ajmp main

;=================================

二、keil c 中编译

1. 新建项目

打开“keil c”软件,新建一个项目。项目名也不妨为“counter”。

点击桌面上的图标,进入keil c51 μvision2集成开发环境。在主界面上点下拉菜单“project”,选“new project?”命令。在弹出的对话框中将项目命名为“counter”。点“保存”按钮,选“atmel”下的“at89s52”后返回。

2. 添加源程序

打开已建立的文件“counter.asm”;并将该文件添加到“source group 1”中。

在μvision2 主界面上点击打开文件按钮,在弹出的对话框内找到刚才新建并保存的文件“counter.asm”。点“打开”按钮打开。

在中间左边的“项目空间(project workspace)”内,点击“+”展开。再用右键点击“source group 1”文件夹,在弹出的菜单命令中选“add files to group‘source group 1’”。

3. 参数设置

在“options for target‘ target 1’”中的“output”标签页上进行设置。

点下拉菜单“project”, 选“options for target‘target 1’”。在弹出对话框上的“target”标签页内,把单片机的运行频率调整为11.0592mhz。在“output”标签页上,点“create hex file”前的复选框,使其内出现“√”,这样编译后就能生成目标文件了。点“确定”按钮返回。

4. 程序编译

点编译和建立目标文件,得到“counter.hex”文件。

在μvision2 主界面上点重新编译按钮,对源程序文件进行编译,结果如图8 所示。

图8

三、preteus仿真

isis 仿真图如图9 所示。设置cpu:89c51 的特性,加载counter.hex 代码加载,运行仿真。将光标移至按钮sb1,使光标变成一只“手”时,点击鼠标左键,使按钮按下。按钮释放后,数码管显示值加“60”,如图9 所示。启动倒计时。将光标移至按钮sb2,使光标变成一只“手”时,点击鼠标左键,使按钮按下。按钮释放后倒计时开始。原文来自www.dqjsw.com.cn

图9isis 仿真图

四、基本系统上运行

用单片机基本系统板来验证程序,首先准备好实验用器材基本系统板、下载器、和万能板及所需。然后按下面步骤进行操作。

⒈在应用实验板上按图1 焊接好电阻、、数码管和接插件、按钮等。

⒉拔去最小系统板上的跳线j101、j102、j103,插上at89s52 芯片。将下载线的接口板插入的并口上,连接电缆把最小系统与接口板连好,再在最小系统上接上电源。如图10 所示。

图10

⒊打开下载软件,并设置好有关参数;加载待写文件“counter.hex”;点“编程”按钮下载程序。必要时须先对芯片进行“擦写”( 若该芯片中曾烧录过程序)。

⒋完成上面的操作后,关闭电源,拔下连接电缆,插上跳线j101,接上实验电路。

⒌上电验证程序,按下按键sb1 置初值,按下按键sb2 开始倒计时。若不符合要求则进行修改(可以先在μvision2 进行调试或proteus 中仿真)。

⒍重复上述步骤直到实现要求的功能。

五、结束语

用汇编语言编制应用程序时虽然要考虑单片机的硬件资源的分配,且实现相同功能时的语句可能比c51 编程更多,汇编的模块按结构化编程,同样也能编制出结构清晰、功能明确、可读性强、的应用程序。

作者:未知 点击:1038次 [打印] [关闭] [返回顶部]
本文标签:8051单片机模块化编程技巧
* 由于无法获得联系方式等原因,本网使用的文字及图片的作品报酬未能及时支付,在此深表歉意,请《8051单片机模块化编程技巧》相关权利人与机电之家网取得联系。
电子样本

富林泰克产品系列j电子样
:胡先生
:13736436955
:嘉兴市科力电子有限公司
个人求购

 【求购】  室外配电箱  2024-9-26
陈强 【求购】  水马  2024-9-26
姜远志 【求购】  两级真空泵  2024-9-26
机电用户 【求购】  振动抛光机  2024-9-25
李凤 【求购】  液压油  2024-9-25
 【求购】  色度计  2024-9-25
哈哈哈 【求购】  液压遥控截...  2024-9-25
曹经理 【求购】  防滑剂  2024-9-25
VIP公司推荐