直接拜访寄存器和端口
界说
sfr
操作
ADCON = 0x08 ;
在运用了interrupt 1 关键字之后,会主动生成中止向量
在 ISR中不能 与其他 “后台循环代码”(the background loop code) 同享局部变量
由于 连接器 会复用 在RAM中这些变量的 方位 ,所以它们会有不同的含义,这取决于当时运用的不同的函数
复用变量对 RAM有限的51来将很重要。所以,这些函数期望依照必定的次序履行 而不被中止。
timer0_int() interrupt 1 using 2
{
}
“interrupt”声明 表明 向量生成在 (8*n+3),这儿,n便是interrupt参数后的那个数字
这儿,在08H的代码区域 生成 LJMP timer0_int 这样一条指令
“using” tells the compiler to switch register banks on entry to an interrupt routine. This “context” switch is the fastest way of providing a fresh registerbank for an interrupt routines local data and is to be preferred to stacking registers for very time-critical routines. Note that interrupts of the same priority can share a register bank, since there is no risk that they will interrupt each other.
using 告知编译器 在进入中止处理器 去切换寄存器的bank。这个”contet”切换是
为中止处理程序的局部变量供给一个新鲜的寄存器bank 最快的方法。对时序要求严厉的程序,是首选的 stack寄存器(保存寄存器到stack)方法。
留意:相同优先级其他中止 能够同享 寄存器bank,由于他们每次将中止 没有风险
If a USING 1 is added to the timer1 interrupt function prototype, the pushing of registers is replaced by a simple MOV to PSW to switch registerbanks. Unfortunately, while the interrupt entry is speeded up, the direct register addressing used on entry to sys_interp fails. This is because C51 has not yet been told that the registerbank has been changed. If no working registers are used and no other function is called, the optimizer eliminiates teh code to switch register banks.
假如在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。
中止源的矢量方位
中止源
最高优先级
外部中止0
守时器0溢出
外部中止1
守时器1溢出
串口
守时器2溢出
DMA
硬件断点
JTAG
软件断点
监督守时器
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.
运用C写程序时,尽量少运用using n (n=0,1,2,3)特性。(这个特性在自己运用的进程中存在一些问题,不知是不是是一个小bug)
默许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 是多么的荫蔽。(这恰是使人幻想不到的)
运用不同寄存器组的函数(特殊情况外)不能彼此调用
using”关键字告知 编译器 切换 register bank
假如中止程序不重要,using关键字 能疏忽。
假如一个函数被从中止程序调用,而此中止强制运用using
当编译一个被调用的函数时,编译器有必要告知它
1)
在函数前 有必要用伪 指令
#pragma NOAREGS
在进入 函数
#pragma RESTORE
或许
#pragmas AREGS
这样就不会运用 “肯定地址定位”
2)
#pragma REGISTERBANK(n)
用这个指定告知当时运用的 bank
用NOAREGS指令 移除 MOV R7,AR7
中止服务例程
timer0_int() interrupt 1 USING 1 {
unsigned char temp1 ;
unsigned char temp2 ;
}
被调用的函数
#pragma SAVE // Rember current registerbank
#pragma REGISTERBANK(1)
void func(char x) {
// with “using1”
}
#pragma RESTORE // Put back to original registerbank
假如中止服务例程运用了 USING,被中止服务例程 调用的函数必定要
REGISTERBANK(n)
一个被ISR调用的 函数 也或许被 后台程序 调用
为了函数 “reentrant”(可重入)
8051 系列 MCU 的根本结构包含:32 个 I/O 口(4 组8 bit 端口);两个16 位守时计数器;全双工串行通讯;6 个中止源(2 个外部中止、2 个守时/计数器中止、1 个串口输入/输出中止),两级中止优先级;128 字节内置RAM;独立的 64K 字节可寻址数据和代码区。中止产生后,MCU 转到 5 个中止进口处之一,然后履行相应的中止服务
处理程序。中止程序的进口地址被编译器放在中止向量中,中止向量坐落程序代码段的最低地址处,留意这儿的串口输入/输出中止共用一个中止向量。8051的中止向量表如下:
中止源 中止向量
—————————
上电复位 0000H
外部中止0 0003H
守时器0 溢出 000BH
外部中止1 0013H
守时器1 溢出 001BH
串行口中止 0023H
守时器2 溢出 002BH
interrupt 和 using 都是 C51 的关键字。C51 中止进程经过运用 interrupt 关键字和中止号(0 到 31)来完成。中止号指明编译器中止程序的进口地址中止序号对应着 8051中止使能寄存器IE 中的使能位,对应联系如下:
IE寄存器 C51中的 8051的
的使能位 中止号 中止源
——————————–
IE.0 0 外部中止0
IE.1 1 守时器0 溢出
IE.2 2 外部中止1
IE.3 3 守时器1 溢出
IE.4 4 串口中止
IE.5 5 守时器2 溢出
有了这一声明,编译器不需理睬寄存器组参数的运用和对累加器A、状况寄存器、寄存器B、数据指针和默许的寄存器的维护。只要在中止程序中用到,编译器会把它们压栈,在中止程序完毕时将他们出栈。C51 支撑一切 5 个 8051 规范中止从 0 到 4 和在 8051 系列(增强型)中多达 27 个中止源。
using 关键字用来指定中止服务程序运用的寄存器组。用法是:using 后跟一个0 到3 的数,对应着 4 组作业寄存器。一旦指定作业寄存器组,默许的作业寄存器组就不会被压栈,这将节约 32 个处理周期,由于入栈和出栈都需求 2 个处理周期。这一做法的缺陷是一切调用中止的进程都有必要运用指定的同一个寄存器组,不然参数传递会产生过错。因而关于using,在运用中需灵敏取舍。