《51单片机应用开发从入门到精通》——2.8 用外部中断控制灯闪烁

简介:

本节书摘来自异步社区《51单片机应用开发从入门到精通》一书中的第2章,第2.8节,作者 张华杰,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.8 用外部中断控制灯闪烁

功能说明:单片机P1端口的8只LED作左移右移,不断循环。当按外部中断INT0开关K1时,循环停止,转而使8只LED闪烁4次,然后再恢复灯的左右移循环。

2.8.1 硬件设计

外部中断INT0电路如图2-11所示。

单片机的P3端口除当一般I/O使用外,还有第二功能,其P3.2(INT0)脚是外部中断0的输入脚,其P3.3(INT1)脚是外部中断1的输入脚。

本电路图中,在P3端口的P3.2引脚上接有外部中断INT0控制开关K1,作为外部中断的输入信号。输出部分由P1端口接的8只LED作输出显示。


screenshot

2.8.2 程序设计

本程序在灯左右移程序的基础上,增加了外部中断INT0。

1.流程图

程序设计流程如图2-12所示。


screenshot

2.程序

汇编语言编写的用外部中断控制灯闪烁源程序ZD01.ASM代码如下:

01:         ORG           00H                  ;起始地址
02:         JMP           START                ;跳到主程序START
03:         ORG           03H                  ;INT0中断起始地址         
04:         JMP           EXT0                 ;跳到中断子程序            
05:START:  MOV           IE,  #10000001B      ;INT0中断开通
06:         MOV           IP,  #00000001B      ;INT0中断优先
07:         MOV           TCON, #00000000B     ;INT0为电平触发
08:         MOV           SP, #70H             ;设定堆栈指针               
09:LOOP:   MOV           R0, #8               ;设置左移位数
10:         MOV           A , #0FEH            ;设置左移初值
11:LOOP1:  MOV           P1,  A               ;输出至P1
12:         ACALL         DELAY                ;调用延时子程序
13:         RL            A                    ;左移一位
14:         DJNZ          R0, LOOP1            ;判断移动位数
15:         MOV           R0, #8               ;设置右移位数
16:LOOP2:  RR            A                    ;右移一位
17:         MOV           P1, A                ;输出至P1
18:         LCALL         DELAY                ;调用延时子程序 
19:         DJNZ          R0, LOOP2            ;判断移动位数
20:         JMP           LOOP                 ;重设显示值           
21:EXT0:   PUSH          ACC                  ;将A值压入堆栈
22:         PUSH          PSW                  ;将PSW值压入堆栈  
23:         SETB          RS0                  ;设定工作寄存器组1  
24:         CLR           RS1                          
25:         MOV           R0, #4               ;设置闪烁次数
26:LOOP3:  MOV           A, #00H              ;A存有P1口欲显值
27:         MOV           P1, A                ;P1端口灯亮
28:         LCALL         DELAY                ;调用延时1s子程序
29:         CPL           A                    ;将A的值反相
30:         DJNZ          R0, LOOP3            ;判断闪烁次数                   
31:         POP           PSW                  ;从堆栈取回PSW值    
32:         POP           ACC                  ;从堆栈取回A值         
33:         RETI                               ;返回主程序                  
34:DELAY:  MOV           R5,  #50             ;延时1s子程序
35:DLY1:   MOV           R6,  #100
36:DLY2:   MOV           R7,  #100
37:         DJNZ          R7,  $    
38:         DJNZ          R6,DLY2
39:         DJNZ          R5,DLY1                             
40:         RET                
41:         END                                ;程序结束

2.8.3 代码详解

1.标号说明

START:起始程序的进入点。

LOOP:左右移循环执行的进入点。

LOOP1:左移循环的进入点。

LOOP2:右移循环的进入点。

LOOP3:闪烁程序循环的进入点。

EXT0:中断子程序的进入点。

DELAY:延时子程序的进入点。

2.寄存器使用分配情况

寄存器P1和A(ACC)的作用与之前相同。R0作计数器,在左移、右移和闪烁程序中都由R0负责计数,R5、R6和R7是延时子程序中的计数器。

PSW、SP、IE、IP、TCON是新用到的特殊功能寄存器,其中PSW是一个8位的专用寄存器,称为程序状态字寄存器,用于存储程序运行中的各种状态信息。其中有两位名为RS0和RS1,改变其值就能选择CPU当前工作的寄存器组。

寄存器组是CPU工作时临时存储数据的地方,共有0~3组,每组8个单元R0~R7,RS0、RS1与寄存器组的对应关系见表2-10。


screenshot

单片机开始工作时,RS0 = 0、RS1 = 0,CPU选用第0组的8个单元为当前工作寄存器。当主程序要调用中断子程序时,通过“CLR RS1”语句使RS1 = 0,通过“SETB RS0”语句使RS0 = 1,即将RS1置为0、RS0置为1,则中断子程序就可以使用第1组8个单元为当前工作寄存器R0~R7。

这样,使主程序使用的第0组R0~R7的内容就能保持不变,即主程序与子程序各自使用各自的寄存器,以免内容混淆。

SP也是一个8位的专用寄存器,称为堆栈指针寄存器,用于暂存堆栈顶部的地址。堆栈是按先进后出、后进先出的原则存取数据的一个专用存储区。数据的进栈出栈由指针SP统一管理。

TCON、SCON、IE和IP是4个特殊功能寄存器,它的作用是对中断进行管理和控制。

3.程序分析解释

01~04:规定起始地址。通过“ORG 00H”语句,规定了标号START所在的地址为00H,即第一条指令从00H开始存放;通过“ORG 03H”语句规定了下面标号EXT0的中断子程序起始地址为03H,03H是外部中断0的入口地址。

05~08:中断设置。首先是对中断允许控制寄存器IE的设置。允许中断是由两层控制,第一层为全面控制(EA),它是总开关,第二层(EX0)是对个别中断的控制,它是分开关。

通过“MOV IE, #10000001B”语句,使中断允许控制寄存器IE中的允许总控制位EA值为1,即中断总允许。使EX0 = 1,即外中断0允许使用。

接着对优先级控制寄存器IP进行设置。中断有优先级,各中断源的优先级由优先级控制寄存器IP进行管理,分低优先级和高优先级:PX0 = 0时,为低优先级;PX0 = 1时,为高优先级。“MOV IP, #00000001B”语句使PX0 = 1,即使外部中断0为高优先级。

中断触发有两种方式:脉冲方式和电平触发方式。两种方式的选择是通过定时寄存器TCON来设定的。通过“MOV TCON, #00000000B”语句将IT0位设置为0,则使外中断0选择了电平触发方式。

语句“MOV SP, #70H”设置堆栈指针地址,当程序中执行保护现场指令PUSH或恢复现场指令POP时,SP会自动加1或减1,然后将数据压入或弹出堆栈,目的是使中断结束后能正确地回到程序调动点继续执行。

09~20:使LED左移和右移。

21~33:中断子程序。

中断子程序由3部分组成:保护现场部分(21~24行语句)、闪烁功能部分(25~30行语句)和恢复现场部分(31~32行语句)。

其中闪烁功能部分是使用中断的目的。而闪烁功能部分前边的保护现场和后边的恢复现场部分是为了使中断结束后能正确地回到原程序调用点继续执行。

21~22行语句是将累加器A和程序状态字寄存器PSW中的值压栈保存;23~24行语句是设置RS1 = 0、RS0 = 1,目的是使中断子程序使用第1组工作寄存器。这样,第0组R0~R7的内容就能保持不变

34~40:延时1s子程序。

41:程序结束。

4.边用边学指令

本节程序新用到的指令有:PUSH、POP、RETI和ORG。

PUSH和POP是两条专用堆栈操作指令,属于数据传送类。堆栈操作的特点是按先进后出、后进先出的原则存取数据。PUSH和POP是成对出现的,PUSH是进栈指令,POP是出栈指令,一般用于在中断子程序中保护现场和恢复现场。

RETI是控制转移类指令,RETI的功能是使中断服务程序结束返回。RETI除具有子程序返回指令RET所具有的全部功能之外,还有清除中断响应时被置位的优先级状态、开放较低级的中断和恢复中断逻辑等功能。

ORG是伪指令,ORG的功能是规定下面目标程序存放的起始地址。

2.8.4 模拟仿真

1.模拟仿真前注意事项

(1)将第12、18、28行调用延时语句前加上分号,如“ACALL DELAY”改为“;ACALL DELAY”。目的是使程序跳过调用延时的语句,节省模拟运行的时间。

(2)将第20行语句“JMP LOOP”改为“JMP EXT0”,使程序能运行标号为EXT0的中断子程序。

(3)重新将程序“编译/汇编”和“产生代码并装入”,然后再调试。
2.模拟仿真中注意事项

(1)注意观察中断设定中特殊功能寄存器IE、IP、TCON和SP值的变化。其中IE、IP、TCON在程序中给出的是二进制值,但在模拟仿真特殊功能寄存器窗口中看到的是十六进制数。

(2)在运行20行语句前,ACC的值是FEH,PSW的值是01H,即PSW中控制工作寄存器组的两个位RS0 = 0、RS1 = 0,所以此时CPU选中的是第0组工作寄存器。

当运行21~24行语句之后,PSW的值改变为09H,即PSW中控制工作寄存器组的两个位RS0 = 1、RS1 = 0,所以此时CPU使用的工作寄存器由第0组改为第1组。使原来第0组工作寄存器的内容能保持不变,起到保护现场的作用。

(3)当程序运行到31~32行之后,PSW的值为01H,ACC的值为FEH,这是通过POP指令取回了PSW和A在进入中断子程序前的值(即原来值),起到恢复现场的作用。

2.8.5 实例测试

将写入程序的单片机插入实验板插座上,检查无误后接通电源,此时将看到亮灯从右向左移动,移到最左端后再从左向右移动,不断循环。

当按开关K1产生中断信号时,灯移动循环停止,转而执行中断服务程序,8只LED闪烁4次。中断服务程序结束之后,亮灯再恢复左右移动循环。

在实例测试时要仔细观察,程序从什么地方发生中断,将从什么地方开始恢复。

亮灯从右端向左移动到第3个时,下一个将是第4个位置灯亮,可以在此时按K1按钮发生中断,灯开始闪烁,当灯闪烁停止后,亮灯会接着从第4个位置开始向左移动。中断后程序能准确地从原中断点开始恢复,主要是因为在中断服务程序中采用了保护现场和恢复现场的措施。

2.8.6 经验总结

编写中断程序要注意以下几步。

(1)确定中断入口地址。

(2)中断设置,包括开通中断、确定优先级和触发方式等,即对4个特殊功能寄存器TCON、SCON、IE和IP进行设置。

(3)在中断处理子程序里,要有保护现场和恢复现场部分,这是中断处理子程序与前面讲的子程序的不同点。

相关文章
|
3月前
|
芯片
毕业设计 基于51单片机的手机蓝牙控制8位LED灯亮灭设计
毕业设计 基于51单片机的手机蓝牙控制8位LED灯亮灭设计
|
6月前
|
编解码 网络性能优化 芯片
如何用51单片机实现pwm调光+呼吸灯(超详细+源码)
如何用51单片机实现pwm调光+呼吸灯(超详细+源码)
387 0
如何用51单片机实现pwm调光+呼吸灯(超详细+源码)
LabVIEW控制Arduino LED灯闪烁(基础篇—2)
利用LIAT中的数字I/O函数库,通过LabVIEW控制Arduino Uno控制板上D13管脚上LED灯,实现等间隔闪烁。
LabVIEW控制Arduino实现PWM呼吸灯(基础篇—5)
利用LIAT中的模拟I/O函数库,通过LabVIEW和Arduino Uno控制板实现LED灯亮度的调节,产生灯会呼吸的效果。
|
10月前
|
存储 IDE 物联网
Blinker 语音控制 51单片机 点灯
Blinker 语音控制 51单片机 点灯
191 0
|
10月前
单片机实验--单片机控制数码管
单片机实验--单片机控制数码管
105 0
单片机实验--单片机控制数码管
|
12月前
|
芯片
蓝桥杯嵌入式之 LED 闪烁
蓝桥杯嵌入式之 LED 闪烁
172 0
|
12月前
单片机入门3.驱动蜂鸣器
单片机入门3.驱动蜂鸣器
142 0
|
12月前
|
C语言 芯片
51单片机入门 第一篇:LED灯
51单片机入门 第一篇:LED灯
306 0
|
12月前
|
C++
【蓝桥杯嵌入式】点亮LED灯,流水灯的原理图解析与代码实现——STM32
【蓝桥杯嵌入式】点亮LED灯,流水灯的原理图解析与代码实现——STM32
430 0