|

楼主 |
发表于 2007-8-4 14:49:20
|
显示全部楼层
从以上例子我们可以发现:
1。每个程序都是从尾到头循环;
2。根据外部条件决定程序往哪儿走,因此每次循环都要问P3.2,P3.3,P3.4是否按下,这种就是所谓“查询”方式。
单片机还有一种非常重要的运行方式:中断方式。在中断方式,单片机在运行中,可能为外部条件打断当前的运行,转而插入另外一个过程,此过程完结后再回到原来的程序中去。
C51有外中断0(INT0):对应P3.2引脚;(INT1),对应P3.3;定时/计数器0(C/T0)计数对应P3.4,定时内部;(C/T1),P3.5;串口中断。每个中断都有自己的中断入口和处理程序,这些中断入口位于ROM地址的0003H,000BH,0013H,001BH,0023H,要使用哪个中断就在哪个入口加一条转移指令,跳到中断程序的实际位置去执行,当然前提是程序中必须开放中断允许,这样P3.2等的低电位状态才会引发中断产生。在上面的所有例子中,因为不涉及中断,所以P3.2等只是作为普通I/O口。
所以在程序中要使用中断功能,必须在入口加跳转指令;必须有中断子程序;必须开放中断。在C51中,有个专门控制中断开启和关闭的寄存器IE,其相应各位和]功能如下:
IE: 7 6 5 4 3 2 1 0
EA - - ES ET1 EX1 ET0 EX0
总中断允许 - - 串口 C/T1 INT1 C/T0 INT0
上列各位,为1允许,为0禁止。例如我们要开放INT0中断,就可以在程序中加入:
MOV IE,# 81H :置IE的位7 和位0为1 ,允许INT0中断并且开放总中断。当然也可以用“位指令”直接置位:
SETB EA
SETB EX0
在中断处理程序中通常
1。关闭中断:避免在中断处理中因本中断信号未消失而反复响应,如果不想响应更高级别的中断,则关闭总中断;
2。保存先前程序有关寄存器或RAM的状态,以便中断结束后恢复原有过程继续进行,通常用压栈PUSH指令。
3。运行“真正的”中断处理。
4。恢复保存的寄存器等等,通常用弹出POP指令。
5。开启已经关闭的中断
6。通过RETI指令,从中断子程序返回。下面是个例子:
ORG 0000H
AJMP MAIN
ORG 0003H ;INT0中断人口
AJMP SUB_INT0
ORG 0030H
MAIN: MOV SP,#30H ;堆栈从31H单元开始
SETB EA ;开总中断
SETB EX0 ;允许INT0中断
POS1: MOV A,#1 ;按下P3.3, P1.0灯灭。其余亮
JB P3.3,$ ;
MOV P1,A
JB P3.4,$ ;按下P3.4循环灭灯
POS2: RL A ;
ACALL DELAY
MOV P1,A
JB P3.5,POS2 ;只有按下P3.5才停止循环灭灯(程序当然没有停止)
AJMP POS1
DELAY: MOV R7,#250 ;延时子程序
DELAY1:MOV R6,#200
DJNZ R6,$
DJNZ R7, DELAY1
RET
SUB_INT0: CLR EX0 ;INT0中断子程序,关总中断
CLR EA ;关INT0中断
PUSH PSW ;保存原先PSW寄存器
PUSH ACC ;保存累加器A:注意这里ACC代表A的直接地址0E0H
PUSH P1 ;保存P1口
MOV A, #00110011B ;中断处理是停止灭灯循环,而间隔两个灯亮灭
MOV P1,A
JNB P3.2 ,$ ;为了清楚起见只有松开P3.2才结束中断
POP P1 ;恢复保存的各个寄存器
POP ACC ;
POP PSW ;
SETB EA ;重新开总中断
SETB EX0 ;重新开INT0中断
RETI ;从中断返回主程序
END
汇编运行后用p3.4按键开始跑马灯,如果按下p3.2则停止,变成亮亮灭灭,直到放开p3.2继续跑马灯。如图:
[ 本帖最后由 wey05 于 2007-8-4 15:00 编辑 ] |
|