您的位置 首页 硬件

单片机学习之十二:按键操控跑马灯(中止)

一、实验现象:二极管作左右跑马灯,当按下外部按键K0时,8个二极管全部闪烁5次后从K0按下之前的位置继续作跑马灯。二、实验目的掌握堆…

一、实验现象:

二极管作左右跑马灯,当按下外部按键K0时,8个二极管悉数闪耀5次后从K0按下之前的方位持续作跑马灯。

二、实验意图

把握仓库在中止程序中的效果

把握让程序维护现场的办法

三、实验任务分析:

有了曾经各个实验的经历,信任这个实验对咱们来说,难度不是很大。咱们仅有接触到的新的知识点是:让程序从回来中止之前的方位持续履行跑马灯,那么怎么能够让程序在进入中止之前记住其时所在的方位,在履行中止之后,能够回来这个当地持续往下履行呢?

咱们能够这样作:在进入中止之前,把该时间的程序信息放到一个当地保存下来,在回来中止之前,再到这个当地把咱们寄存的程序信息取出来。这样不就能够从进入中止的方位开端从头履行程序了吗?那么,这个暂存数据的当地在哪里呢?

单片机给咱们考虑的很周到,答应咱们从内部RAM中指定一个空间专门来作这个作业,这个空间便是仓库。而且单片机还专门给了咱们一个8位的仓库指针,让咱们用它来拓荒仓库空间。(为什么是8位呢?因为内部RAM的地址空间是256字节,所以8位就满足拉。)

例如:假设咱们给仓库指针赋值:mov sp,#70h,就表明咱们把内部数据RAM的地址为70h开端的单元设为仓库啦。

那么,咱们一般把内部数据RAM的那些当地作为仓库呢?让咱们来温习一下内部RAM的结构吧。

前面咱们现已说过,内部RAM共有256字节,分为两组。还记得它们各自的功用吗?高128字节是特别功用寄存器区,咱们没有办法运用,那就打低128字节的主见吧。咱们再来看看低128字节的RAM空间分配。

咱们发现在低128字节中,作业寄存器区和位寻址区的地址现已分配好了,咱们能够运用的只要30h~7fh的数据缓冲区了。所以咱们的仓库指针只能设在这个区域,从30h今后的规模为宜。在该程序中,咱们把仓库设在70h的方位。

好啦,知道仓库设在哪里,下面咱们就要考虑怎么把程序运转的相关信息放入仓库拉。那么,程序运转的相关信息在哪里呢?

因为在主程序中,咱们让程序作左右跑马灯。还记得实验三吗,咱们的左右跑马灯是经过把寄存器a中的数,经过进位标志CY(程序状态字PSW的最高位),进行左右环移来完结的。一起,因为寄存器a是单片机中最最常用的寄存器,咱们在中止程序中也要用到它。为了防止中止程序改动寄存器a的值,所以咱们在中止服务程序开端之前,把a的值放到仓库中保存起来。相同咱们也要把psw的值也保存起来。在回来主程序之前,再把它们取出来,这样就能够使得程序从进入中止之前的方位开端,持续作跑马灯。

把数据存入仓库和从仓库中取出,是经过仓库操作指令完结的。

例如:假如想把a中的数据存入仓库,就:push acc;假如想把a的内容从仓库中取出,就:pop acc。(一般称之为:压入,弹出)。

还需要阐明一点的是:仓库中的数据是选用“后进先出”的结构方法处理的。就像咱们摞盘子相同,最终摞进去的盘子,获得时分是最早取出的。所以咱们压入数据后,再弹出的时分要特别留意次序,后压入的要先弹出,不要弄错啦。

现在来看看这个实验的程序吧。

四、实验程序如下:

org 0000h

ljmp start

org 0013h

ljmp ext1

org 0020h

start: clr p1.5 ;防止蜂鸣器响

setb ea ;CPU开中止

setb ex1 ;答应外部中止1请求中止

setb it1 ;设置外部中止1跳变方法触发

mov sp,#70h ;设置仓库进口

loop1: lcall light1 ;调用左右跑马灯子程序

ljmp loop1

;以下是中止服务程序

ext1: clr ea ;封闭CPU中止

push acc ;把寄存器a的内容压入仓库

push psw ;把程序状态字压入仓库

lcall keyreader ;调用键辨认子程序

pass: pop psw ;康复现场,留意次序,要先弹出程序状态字

pop acc ;弹出寄存器a的内容,

setb ea ;CPU开中止

reti ;中止回来

light1: mov a,#0ffh ;light1是左右跑马灯子程序,咱们能够参阅实验三的内容

clr c

mov r7,#08h

lloop: rlc a

mov p0,a

lcall del100ms

djnz r7,lloop

mov r6,#06h

rloop: rrc a

mov p0,a

lcall del100ms

djnz r6,rloop

ret

keyreader: mov a,p1 ;keyreader是键辨认子程序,咱们能够参阅实验7

anl a,#0fh

cjne a,#0dh,pass

lcall del10ms

mov a,p1

anl a,#0fh

cjne a,#0dh,pass

lcall light2 ;假如确认K0按键按下,调用灯火闪耀子程序

ret

light2: mov a,#00h ;light2是让灯火闪耀5次的子程序

mov r5,#10

loop2: mov p0,a

call del10ms

cpl a ;把a寄存器中的数据取反

djnz r5,loop2;

ret

del10ms: mov r4,#15h ;延时10ms子程序

del1: mov r3,#0ffh

del2: djnz r3,del3

djnz r4,del1

ret;

del100ms:mov r2,#0c8h ;延时100ms子程序

del3: mov r1,#0ffh

del4: djnz r1,del4

djnz r2,del3

ret

end

咱们把这个程序下载到学习板上看看,会发现每次按下按键的时分,程序进入中止后,在回来的时分,会回到那个方位持续开端左右循环。这便是因为咱们在进入中止的时分维护了现场的原因。

五、几点阐明

主程序是左右跑马灯,其间用到了r7,r6寄存器,还调用了100ms延时,所以也用到了r2,r1寄存器。所以咱们要特别留意,在中止服务程序中,要防止运用这几个寄存器。不然,就会导致在中止程序中,修改了r寄存器的内容,导致回来主程序的时分出现问题。

在中止服务程序中,用到了10ms延时程序,这个延时程序运用的寄存器是r4,r3。别的,还调用了light2子程序,其间用到了r5寄存器。所以。主程序和中止服务程序用到的寄存器r就没有抵触。

那么假如因为条件的约束,使得主程序和中止程序的寄存器的数量较多,一组8个寄存器不行,该怎么办呢?

咱们也能够象维护a寄存器相同,在进入中止之后,首先把某一个在中止服务程序中也要用到的r寄存器的内容压入仓库,在退出中止之前再弹出来。

或许咱们就从头挑选寄存器区吧,因为咱们缺省运用的是0区的寄存器组,所以咱们就改动psw程序状态字中的rs1和rs0,就能够换别的的一组寄存器区了。例如,咱们在进入中止服务程序之后,写这样的两条指令:

clr rs1

setb rs0

这样,咱们就用了1区的8个寄存器,这样就没有问题啦。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/yingjian/266862.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部