中断的应用中对断点的保护
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
【016】中断的应用中对断点的保护 [51]
点击数:430 发布日期:2006-8-22 20:37:00
【收藏】【评论】【打印】【编程爱好者论坛】【关闭】
实验参考: 笨笨工作室-实验八、按键控制跑马灯(中断)。(查看)
实验板: FB51A。(查看)
实验目的: <1> 掌握堆栈在中断程序中的作用。
<2> 掌握让程序保护现场的方法。
实验现象: 二极管作左右跑马灯,当按下外部按键 K1 时, 8 个二极管全部闪烁 5 次后从 K1 按下之前的位置继续作跑马灯。
在应用中断时,若主程序在正常运行的过程中响应了中断就要转而去执行中断服务程序。那如何在执行完中断服务程序之后完全恢复原来的主程序呢?这就需要在执行中断服务程序之前将相关的状态保护起来,在中断完成后再将这些状态恢复,从而继续执行主程序。
51单片机中允许我们从内部 RAM 中指定一个空间专门保存这些断点处的状态,这个空间就是堆栈。并且还专门给了我们一个 8 位的堆栈指针,让我们用它来开辟堆栈空间。例如我们给堆栈指针赋值: mov sp, #70h ,就表示我们把内部数据 RAM 的地址为 70H 开始的单元设为堆栈。
MCS-51的片内存储器(RAM)共有256字节,高128字节是特殊功能寄存器,地址范围80H~FFH。这一部分可看作系统资源,不能随便利用。而剩下的低12 8字节区分如下:
──┬────────────┐
7FHㄧ用户RAM区ㄧ
ㄧ(数据缓冲区、堆栈区)ㄧ
30Hㄧ 80 byte ㄧ
──┼────────────┤
2FHㄧ可位寻址区ㄧ
20Hㄧ 16 byte ㄧ
──┼────────────┤
1FHㄧ第3组工作寄存器区ㄧ
18Hㄧ 8 byte ㄧ
──┼────────────┤
17Hㄧ第2组工作寄存器区ㄧ
10Hㄧ 8 byte ㄧ
──┼────────────┤
0FHㄧ第1组工作寄存器区ㄧ
08Hㄧ 8 byte ㄧ
──┼────────────┤
07Hㄧ第0组工作寄存器区ㄧ
00Hㄧ 8 byte ㄧ
──┴────────────┘
在这低128字节中,工作寄存器区和位寻址区的地址已分配好,我们可以利用的只有 30H ~ 7FH 的数据缓冲区。所以我们的堆栈指针只能设在这个区域。
在主程序中,让程序作左右跑马灯(参考【004】流水灯实验),。程序中通过把寄存器a中的数进行左环移来实现的。而a又是最常用的一个寄存器,在中断服务程序中也多数会用到,所以在响应中断时要将其保存起来(压入堆栈)。由于程序状态字寄存器PSW(位于特殊功能寄存器区)的不同位包含了程序运行状态的不同信息,所以进入中断时也要将PSW的值保护起来。在返回主程序之前,再把它们取出来,这样就可以使得程序从进入中断之前的位置开始,继续作跑马灯。
键识别部分参考【015】中断方式按键一文。
所用电路如下:
显示部分:
键盘部分:
程序如下:
org 0000h
ljmp start
org 0013h
ljmp ext1
org 0020h
start: setb ea ; CPU开中断
setb ex1 ; 允许外部中断1申请中断
setb it1 ; 设置外部中断1为跳变方式触发 mov sp, #70h ; 设置堆栈入口
loop1: lcall led_flow ; 调用左右流水灯程序
ljmp loop1
ext1: ; 中断服务程序
clr ea ; CPU关中断
push acc ; a 入栈
push psw ; psw 入栈
lcall key ; 调用键识别子程序
pass: pop psw ; 恢复现场(与入栈顺序相反)
pop acc
setb ea ; CPU开中断
reti ; 中断返回
led_flow: mov a, #0ffh ; 左右流水灯子程序
clr c ; 清Cy进位标志位
mov r7, #08h ; 左循环次数
lloop: rlc a ; a循环左移
mov p0, a ; a送P0口
lcall del100ms ; 延时100ms
djnz r7, lloop ; 左移8次
mov r6, #06h ; 右循环次数
rloop: rrc a
mov p0, a
lcall del100ms
djnz r6, rloop
ret
key: mov a, p1 ; 键识别子程序
anl a, #0fh
cjne a, #0dh, pass
lcall del10ms
mov a, p1
anl a, #0fh
cjne a, #0dh, pass
lcall key_flash ; K1按下则调用灯闪程序
ret
key_flash: mov a, #00h ; 灯闪5次子程序
mov r5, #10 ; 闪一次有一亮一灭
loop2: mov p0, a
call del100ms
cpl a ; 取反
djnz r5, loop2
ret
del10ms: ; 10ms延时子程序(12M)
mov r4, #20 ; 2机器周期
temp1: mov r3, #248 ; 2机器周期
djnz r3, $ ; 2机器周期 2+2×248=498