用C51写中断函数,和用汇编语言写中断程序,在用法上基本相同,都是中断源发出中断请求并允许中断时去执行中断程序的。并不能由主程序或其它程序调用。但中断程序的起始地址的定义方法不同。C语言用interrup n语句,n为中断源编号。而汇编语言则是用伪指令ORG直接定义的。如定时器T0的起始地址为000BH,则可写,ORG 000BH。
ORG 0000H
LJMP START
ORG 000BH
LJMP Timer0Interrupt
START:
MOV SP,#60H
LCALL InitTimer0
LOOP:
;add your code here!
LJMP LOOP
InitTimer0:
MOV TMOD,#01H
MOV TH0,#0FCH
MOV TL0,#18H
SETB EA
SETB ET0
SETB TR0
RET
Timer0Interrupt:
PUSH DPH
PUSH DPL
PUSH ACC
MOV TH0,#0FCH
MOV TL0,#18H
CPL P10
POP ACC
POP DPL
POP DPH
RETI
END
这是定时器0的一个1ms中断一次的程序 在P10端口输出1KHz方波
如果是用C去写的话,像汇编一样,开中断就行了。位置一般就在MAIN 之前的。
//晶振频率221184MHz
#include<at89x52h>
#define TIMER0H 0x4c
#define TIMER0L 0x00
#define TIMER0_RUN TR0=1
#define SECOND_OVERFLOW 40
#define SEG_PORT P0
#define DISPLAY_DIG1 P1&=0xf0;P1|=0x01
unsigned char g_CurrentDigit=0; //当前显示的数字
void timer() interrupt 1
{
static unsigned char s_Count = 0;
TH0 = TIMER0H; //重置定时器初值
TL0 = TIMER0L;
//每次进入中断服务程序,TH0和 TL0 的值都
TIMER0_RUN; //定时器运行,开始下一
if(s_Count != SECOND_OVERFLOW)
{ //未到整秒,把 sCount 值加1
s_Count++;
}
else
{ //到整秒,s_Count归 0,更新把当前显示
s_Count = 0;
if(g_CurrentDigit != 9)
{
g_CurrentDigit++;
}
else
{
g_CurrentDigit = 0;
}
}
return;
}
void Initial(void) //初始化
{
IE = 0x82; //仅允许Timer0 中断
TMOD = 0x01; //Timer0 使用工作方式 1(16位) ,定时器
TH0 = TIMER0H; //设置定时器初值
TL0 = TIMER0L;
TIMER0_RUN; //定时器开始运行
DISPLAY_DIG1;
}
void main()
{
unsigned char code SEG_CODE[]
= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
Initial();
while(1)
{
SEG_PORT = SEG_CODE[g_CurrentDigit]; //显示当前的数字
//当timer0溢出时,单片机响应 timer0 中断,调用 timer 函数,
//每40 次调用当前显示的数字加 1
}
}
程序分析:
程序中主程序做的事只是在死循环中反复显示当前的数字,每产生一次中断,程序就跳
转到中断服务函数 timer()中进行相应的更新。
这里中断服务函数 timer()有别于普通 C函数的地方是在声明中多了“interrupt 1” ,说明
这个函数是中断号为 1的中断服务函数。各个中断对应的中断号如表 38所示。
这个程序需要初始化的东西比较多, 我们把这些初始化语句都放在了初始化函数 Initial()
中,这也是程序初始化很常见的做法。我们还第一次用到了静态变量和全局变量。全局变量
是中断处理函数与外界程序进行参数传递的唯一途径,因此在单片机程序中全局变量的使
用频率要比普通的 C 语言程序高。尽管如此,由于全局变量的使用会影响程序的结构化,
所以在可以不使用全局变量的地方,还是要避免使用全局变量。在程序中,为了把全局变
量与静态变量跟普通变量区别开来,我们在变量前分别加了小写 g_和小写 s_以示区别。
IE 寄存器中的使能位和C中的中断号 中断源
0 外部中断0
1 定时器0溢出
2 外部中断1
3 定时器1溢出
4 串行口中断
5
定时器2溢出(仅在S52、
C52中有此中断源)
好了,以上是我找的一个实例,希望对你有帮助!
按一下L键显示一个红色的L,按ESC退出
================================以下为程序代码
assume cs:code
code segment
in al,60H
mov cs:switch,al
;-------将键盘控制器发送的扫描码保存到switch变量里
mov al, 20H
out 20H, al
;-------以上两条令中断控制器可以再次相应中断
iret
temp1 dw
temp2 dw
switch db
start: mov ax,0
mov ds,ax
mov bx,94+2
mov ax,[bx]
mov cs:temp1,ax
mov ax,code
mov [bx],ax
mov bx,94
mov ax,[bx]
mov cs:temp2,ax
mov word ptr [bx],0
;-------保存并设置新的 INT 9 中断入口
mov ax,0B800H
mov ds,ax
;-------显存段地址
mov bx,0
;-------写现存时的偏移地址
s:mov al,cs:switch
cmp al,01H
jz exit
;-------判断是否是ESC,如果是,退出
cmp al,26H
jnz s
;-------判断'L'键是否按下,如果不是,继续循环
p:mov byte ptr [bx],76
inc bx
mov byte ptr [bx],00001100B
inc bx
mov cs:switch,0
jmp s
;-------如果是'L', *** 作相应的显存,显示一个红色的'L'
exit:mov ax,0
mov ds,ax
mov bx,94+2
mov ax,cs:temp1
mov [bx],ax
mov bx,94
mov ax,cs:temp2
mov [bx],ax
;-------恢复原来的 INT 9 的中断入口
mov ax,4C00H
int 21H
code ends
end start
ORG 0000H
start: AJMP MAIN ;转主程序
ORG 000BH
AJMP CTC0 ;转中断服务程序
ORG 0030H
MAIN: MOV TMOD,#01H ;设置T0为方式1
MOV TL0,#0B0H ;送初值,定时50ms,晶振为12MHz时
MOV TH0,#3CH
MOV B, #0FEH
MOV R0,#00H
SETB EA ;CPU开中断
SETB ET0 ;T0中断允许
SETB TR0 ;启动定时
HERE: SJMP HERE ;等待中断
;中断服务程序
ORG 0120H
CTC0: MOV TL0,#0B0H ;重新装如初值
MOV TH0,#3CH
INC R0
MOV A,R0
CJNE A,#14H,NEXT
MOV R0,#00H
MOV A,B
RL A
MOV B,A
NEXT:
RETI
以上就是关于c51中断函数和汇编语言中断服务程序用法上有何不同全部的内容,包括:c51中断函数和汇编语言中断服务程序用法上有何不同、用单片机汇编语言编写中断程序、单片机的C语言中如何实现汇编中的中断程序,写哪里还有org这个伪指令可以在C中实现吗等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)