单片机学习之十二:按键控制跑马灯(中断)
二极管作左右跑马灯,当按下外部按键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,#
单片机按键控制跑马灯中 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)