单片机C语言中断1

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

单片机C语言中断1

字号:大中小

interrupt中断的关键字,n是中断号提供中断程序的入口地址。

0-INT0 1-T0 2-INT1 3-T1 4-串行中断5-T2

直接访问寄存器和端口

定义

sfr P0 0x80

sfr P1 0x81

sfr ADCON; 0xDE

sbit EA 0x9F

操作

ADCON = 0x08 ; /* Write data to register */

P1 = 0xFF ; /* Write data to Port */

io_status = P0 ; /* Read data from Port */

EA = 1 ; /* Set a bit (enable all interrupts) */

在使用了interrupt 1 关键字之后,会自动生成中断向量

在ISR中不能与其他"后台循环代码"(the background loop code) 共享局部变量

因为连接器会复用在RAM中这些变量的位置,所以它们会有不同的意义,这取决于当前使用的不同的函数

复用变量对RAM有限的51来将很重要。所以,这些函数希望按照一定的顺序执行而不被中断。

timer0_int() interrupt 1 using 2

{

unsigned char temp1 ;

unsigned char temp2 ;

executable C statements ;

}

"interrupt"声明表示向量生成在(8*n+3),这里,n就是interrupt参数后的那个数字

这里,在08H的代码区域生成LJMP timer0_int 这样一条指令

'using' 告诉编译器在进入中断处理器去切换寄存器的bank。这个"contet"切换是

为中断处理程序的局部变量提供一个新鲜的寄存器bank 最快的方式。对时序要求严格的程序,是首选的stack寄存器(保存寄存器到stack)方式。

注意:同样优先级别的中断可以共享寄存器bank,因为他们每次将中断没有危险

如果在timer1 的中断函数原型中使用USING 1, 寄存器的pushing将被MOV to PSW 切换寄存器bank 所替换。

不幸的是,当一个中断入口被加速时。用在入口的直接寄存器寻址将失败。

这是因为C51没有告诉寄存器bank已经改变。如果不工作的寄存器将被使用,如果没有其他函数被调用,优化器.....

Logically, with an interrupt routine, parameters cannot be passed to it or returned. When the interrupt occurs, compiler-inserted code is run which pushes the accumulator, B,DPTR and the PSW (program status word) onto the stack. Finally, on exiting the interrupt routine, the items previously stored on the stack are restored and the closing "}" causes a RETI to be used rather than a normal RET.

逻辑上,一个中断服务程序,不能传递参数进去,也不可返回值。

当中断发生时,编译器插入的代码被运行,它将累加器,B,DPTR和PSW(程序状态字)入栈。最后,在退出中断程序时,预先存储在栈中被恢复。最后的"}"结束符号

将插入RETI到中断程序的最后,

为了用Keil‘C’语言创建一个中断服务程序(ISR),利用interrupt 关键词和正确的中断号声明一个static void 函数。Keil‘C’编译器自动生成中断向量,以及中断程序的进口、出口代码。Interrupt 函数属性标志着该函数为ISR。可用using 属性指定ISR使用哪一个寄存器区,这是可选的。有效的寄存器区范围为1到3。

中断源的矢量位置

中断源Keil中断编号矢量地址

最高优先级 6 0x0033

外部中断0 0 0x0003

定时器0溢出 1 0x000B

外部中断1 2 0x0013

定时器1溢出 3 0x001B

串口 4 0x0023

定时器2溢出 5 0x002B

DMA 7 0x003B

硬件断点8 0x0043

JTAG 9 0x004B

软件断点10 0x0053

监视定时器12 0x0063

1.

函数在调用前定义与在调用后定义产生的代码是有很大差别的(特别是在优化级别大于3级时)。(本人也不太清楚为什么,大概因为在调用前定义则调用函数已经知道被调用函数对寄存器的使用情况,则可对函数本身进行优化;而在调用后进行定义则函数不知被调用函数对寄存器的使用情况,它默认被调用函数对寄存器(ACC、B、DPH、DPL、PSW、R0、R1、R2、R3、R 4、R5、, R6、R7)都已经改变,因此不在这些寄存器中存入有效的数据)

2.

函数调用函数时除在堆栈中存入返回地址之外,不在堆栈中保存其它任何寄存器(ACC、B、DPH、DPL、PSW、R0、R1、R2、R3、R 4、R5、, R6、R7)的内容。(除非被调用函数使用了using特性)

3.

中断函数是一个例外,它会计算自身及它所调用的函数对寄存器(ACC、B、DPH、DPL、PSW、R0、R1、R2、R3、R 4、R5、, R6、R7)的改变,并保存相应它认为被改变了的寄存器。

4.不知算不算是一个小bug)

默认keil c51中的函数使用的是0寄存器组,当中断函数使用using n时,n = 1,2,3或许是对的,但n=0时,程序就已经存在了bug(只有中断函数及其所调用的函数并没有改变R0 ---- R7的值时,这个bug不会表现出来))

一个结论是,在中断函数中如果使用了using n,则中断不再保存R0----R7的值。

当n相同时,这个存在的bug 是多么的隐蔽。(这恰是使人想象不到的)

使用不同寄存器组的函数(特殊情况外)不能相互调用

using"关键字告诉编译器切换register bank

相关文档
最新文档