Keil C51的一些有趣特性
实在无法避免,则把有效数据存入固定的RAM中。 对于中断函数问题,当你看到下面的程序相差55 Byte时,不知你会怎么想的。 例2: void OSTimeDly(void); //using 1 static void Timer0OVInt(void) interrupt 1 //using 1 { TR0 = 0; TH0 = 100; TL0 = 100; TR0 = 1; OSTimeDly(); } void OSTimeDly(void) //using 1 { } 与 void OSTimeDly(void) //using 1 { } static void Timer0OVInt(void) interrupt 1 //using 1 { TR0 = 0; TH0 = 100; TL0 = 100; TR0 = 1; OSTimeDly(); } 它们的汇编代码分别是, ; static void Timer0OVInt(void) interrupt 1 //using 1 RSEG ?PR?Timer0OVInt?TEST USING 0 Timer0OVInt: PUSH ACC PUSH B PUSH DPH PUSH DPL PUSH PSW MOV PSW,#00H PUSH AR0 PUSH AR1 PUSH AR2 PUSH AR3 PUSH AR4 PUSH AR5 PUSH AR6 PUSH AR7 USING 0 ; SOURCE LINE # 24 ; { ; TR0 = 0; ; SOURCE LINE # 26 CLR TR0 ; TH0 = 100; ; SOURCE LINE # 27 MOV TH0,#064H ; TL0 = 100; ; SOURCE LINE # 28 MOV TL0,#064H ; TR0 = 1; ; SOURCE LINE # 29 SETB TR0 ; ; OSTimeDly(); ; SOURCE LINE # 31 LCALL OSTimeDly ; } ; SOURCE LINE # 32 POP AR7 POP AR6 POP AR5 POP AR4 POP AR3 POP AR2 POP AR1 POP AR0 POP PSW POP DPL POP DPH POP B POP ACC RETI ; END OF Timer0OVInt ; ; ; void OSTimeDly(void) //using 1 RSEG ?PR?OSTimeDly?TEST OSTimeDly: ; SOURCE LINE # 35 ; { ; SOURCE LINE # 36 ; ; } ; SOURCE LINE # 38 RET ; END OF OSTimeDly 及 ; void OSTimeDly(void) //using 1 RSEG ?PR?OSTimeDly?TEST OSTimeDly: ; SOURCE LINE # 22 ; { ; SOURCE LINE # 23 ; ; } ; SOURCE LINE # 25 RET ; END OF OSTimeDly CSEG AT 0000BH LJMP Timer0OVInt ; ; static void Timer0OVInt(void) interrupt 1 //using 1 RSEG ?PR?Timer0OVInt?TEST USING 0 Timer0OVInt: ; SOURCE LINE # 27 ; { ; TR0 = 0; ; SOURCE LINE # 29 CLR TR0 ; TH0 = 100; ; SOURCE LINE # 30 MOV TH0,#064H ; TL0 = 100; ; SOURCE LINE # 31 MOV TL0,#064H ; TR0 = 1; ; SOURCE LINE # 32 SETB TR0 ; ; OSTimeDly(); ; SOURCE LINE # 34 LCALL OSTimeDly ; } ; SOURCE LINE # 35 RETI ; END OF Timer0OVInt 这个例子的汇编代码很好的解释了上面的特性1及3。 至于第四个特性,值得特别说明一下。看下例: 例3: void OSTimeDly(void); static void Timer0OVInt(void) interrupt 1 using 0 { TR0 = 0; TH0 = 100; TL0 = 100; TR0 = 1; OSTimeDly(); } void OSTimeDly(void) // using 0 { } 它的汇编代码是 ; static void Timer0OVInt(void) interrupt 1 using 0 RSEG ?PR?Timer0OVInt?TEST USING 0 Timer0OVInt: PUSH ACC PUSH B PUSH DPH PUSH DPL PUSH PSW USING 0 MOV PSW,#00H ; SOURCE LINE # 24 ; { ; TR0 = 0; ; SOURCE LINE # 26 CLR TR0 ; TH0 = 100; ; SOURCE LINE # 27 MOV TH0,#064H ; TL0 = 100; ; SOURCE LINE # 28 MOV TL0,#064H ; TR0 = 1; ; SOURCE LINE # 29 SETB TR0 ; ; OSTimeDly(); ; SOURCE LINE # 31 LCALL OSTimeDly ; } ; SOURCE LINE # 32 POP PSW POP DPL POP DPH POP B POP ACC RETI ; END OF Timer0OVInt ; ; void OSTimeDly(void) // using 0 RSEG ?PR?OSTimeDly?TEST OSTimeDly: ; SOURCE LINE # 34 ; { ; SOURCE LINE # 35 ; ; } ; SOURCE LINE # 37 RET ; END OF OSTimeDly 此例中除了中断函数使用了using 0之外,与上例中的程序并无区别,但是汇编的代码相差却很大。此例中的汇编代码不再保存R0 ---- R7的值。(默认keil c51中的函数使用的是0寄存器组,当中断函数使用using n时,n = 1,2,3或许是对的,但n=0时,程序就已经存在了bug(只有中断函数及其所调用的函数并没有改变R0 ---- R7的值时,这个bug不会表现出来)) 一个结论是,在中断函数中如果使用了using n,则中断不再保存R0----R7的值。 由此可以推论出,一个高优先级的中断函数及一个低优先级的中断函数同时使用了using n,(n = 0,1,2,3)当n相同时,这个存在的bug 是多么的隐蔽。(这恰是使人想象不到的) 最后再来看一例 例4: void OSTimeDly(unsigned char i); static void Timer0OVInt(void) interrupt 1 using 1 { TR0 = 0; TH0 = 100; TL0 = 100; TR0 = 1; OSTimeDly(5); } void OSTimeDly(unsigned char i) // using 0 { while(i--); } 汇编的结果 ; static void Timer0OVInt(void) interrupt 1 using 1 RSEG ?PR?Timer0OVInt?TEST USING 1 Timer0OVInt: PU
- Proteus软件仿真与Keil的单片机系统设计(09-08)
- 基于AT89C51单片机的量程自切换频率计(01-25)
- ARM菜鸟:JLINK与JTAG的区别(03-01)
- 基于单片机的可测温式电子万年历(03-02)
- Matlab/RTW实时仿真与嵌入式系统开发(02-03)
- 基于IAP和Keil MDK的远程升级设计(12-19)
