c51中断函数和汇编语言中断服务程序用法上有何不同

c51中断函数和汇编语言中断服务程序用法上有何不同,第1张

用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中实现吗等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9279771.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-26
下一篇 2023-04-26

发表评论

登录后才能评论

评论列表(0条)

保存