处理程序。中止程序的进口地址被编译器放在中止向量中,中止向量坐落程序代码段的最低地址处,留意这儿的串口输入/输出中止共用一个中止向量。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,在运用中需灵敏取舍。
关于using:
您在文中阐明“这一做法的缺陷是一切调用中止的进程都有必要运用指定的同一个寄存器组”是不是这个意思?
举个比如来说:
界说一个函数
void func(unsigned char i) {
。..
if(++i==0x12) {
。..
}
。..
}
有如下一个中止函数
void int_0(void) interrupt 0 using 1 {
。..。
}
在默许状况下,func运用寄存器组0(BANK0),那么当int_0调用func时是否存在当传递参数时会形成参数传递过错?
谢谢!
假如在中止服务函数 ISR 中运用寄存器,那么有必要处理好 using 的运用问题:
1、中止服务函数运用 using 指定与主函数不同的寄存器组(主函数一般运用 Register bank 0)。
2、中止优先级相同的ISR 可用 using 指定相同的寄存器组,但优先级不同的 ISR 有必要运用不同的寄存器组,在 ISR 中被调用的函数也要运用 using 指定与中止函数相同的寄存器组。
3、假如不必 using 指定,在 ISR 的进口,C51 默许挑选寄存器组0,这相当于中止服务程序的进口首要履行指令:
MOV PSW #0
这点确保了,没运用 using 指定的高优先级中止。能够中止运用不同的寄存器组的低优先级中止。
4、运用 using 关键字给中止指定寄存器组,这样直接切换寄存器组而不必进行很多的 PUSH 和 POP 操作,能够节约RAM空间,加快 MCU 履行时刻。寄存器组的切换,总的来说比较简单犯错,要对内存的运用状况有比较明晰的知道,其正确性要由你自己来确保。特别在程序中有直接地址拜访的时分, 一定要小心翼翼!至于“什么时分要用到寄存器组切换”,一种状况是:当你企图让两个(或以上)作业一起运转,并且它们的现场需求一些阻隔的时分,就会用上 了。在 ISR 或运用实时操作体系RTOS 中,寄存器十分有用。
寄存器组运用的准则:
1、8051 的最低32 个字节分红 4 组 8 寄存器。分别为寄存器R0 到R7。寄存器组由PSW 的低两位挑选。在 ISR 中,MCU 能够切换到一个不同的寄存器组。对寄存器组的拜访不行位寻址,C51 编译器规则运用 using 或 制止中止的函数(#pragma disable)均不能回来 bit 类型的值。
2、主程序(main函数)运用一组,如 bank 0;低中止优先级的一切中止均运用第二组,如 bank 1;高中止优先级的一切中止均运用再其他一组,如 bank 2。明显,同级其他中止运用同一组寄存器不会有问题,因为不会发生中止嵌套;而高优先级的中止则要运用与低优先级中止不同的一组,因为有或许呈现在低优先级中止中发生高优先级中止的状况。编译器会主动判别何时可运用肯定寄存器存取。
3、在 ISR 中调用其它函数,有必要和中止运用相同的寄存器组。当没用 NOAREGS 指令做清晰的声明,编译器将运用肯定寄存器寻址方法拜访函数选定(即用 using 或 REGISTERBANK 指定)的寄存器组,当函数假定的和实践所选的寄存器组不一起,将发生不行预知的成果,然后或许呈现参数传递过错,回来值或许会在过错的寄存器组中。
举一比如:当需求在中止内和中止外调用同一个函数,假定依照程序的流程操控,不会呈现函数的递归调用现象,这样的调用会不会呈现问题?若确认不会发生重入状况,则有以下两种状况:
1、假如 ISR 和主程序运用同一寄存器组(主程序缺省运用BANK 0,若 ISR 没有运用 using 为其指定寄存器区,则缺省也运用 BANK 0),则不需其他设置。
2、假如 ISR 和主程序运用不同的寄存器组(主程序缺省运用BANK 0,ISR 运用 using 指定了其他 BANK),则被调用函数有必要放在:
#pragma NOAREGS
#pragma AREGS
操控参数对中,指定编译器不要对该函数运用肯定寄存器寻址方法;或许也可在 OpTIons-》C51,选中“Don‘t use absolute register accesses”,使一切代码均不运用肯定寄存器寻址方法(这样,履行功率将稍有下降)。不管以上的哪一种状况,编译器均会给出重入正告,需手艺更改 OVERLAY 参数,做重入阐明。
3、还有一种方法:假如被调用函数的代码不是很长,仍是将该函数仿制一份,用不同的函数名替代,这种状况合适ROM有满足剩余的空间。
因而,对using关键字的运用,假如没把握,宁可不必,交给编译体系自己去向理好了。interrupt xx using y
跟在interrupt 后边的xx 值得是中止号,便是说这个函数对应第几个中止端口,一般在51中
0 外部中止0
1 定时器0
2 外部中止1
3 定时器1
4 串行中止
其它的根举相应得单片机有自己的意义,实践上c载编译的时分便是把你这个函数的进口地址方到这个对应中止的跳转地址
using y 这个y是说这个中止函数运用的那个寄存器组便是51里边一般有4个 r0 — r7寄存器,假如你的终端函数和其他程序用的不是同一个寄存器组则进入中止的时分就不会将寄存器组压入仓库回来时也不会弹出来节约代码和时刻一般只要using 0,1,2,3
单片机中止呼应能够分为以下几个过程:1、中止主程序运转。当时指令履行完后当即停止现行程序的运转。2、维护断点。把程序计数器PC 的当时值压入仓库,保存停止的地址(即断点地址),以便从中止服务程序回来时能持续履行该程序,3、寻觅中止进口。依据5 个不同的中止源所发生的中止,查找5 个不同的进口地址。4、履行中止处理程序。这就不讲了;5、中止回来。履行完中止处理程序后,就从中止处回来到主程序,持续往下履行。
以上作业是由计算机主动完结的,与编程者无关,在这5 个进口地址处寄存有中止处理的程序(这是程序编写时放在那儿的,假如没把中止处理程序放在那儿可就错了,因为中止程序无法被履行到)。有点杂乱是吗?没联系,持续往下看。
五个中止源的天然优先级由高到低的摆放次序为外中止0→定时器0→外中止1→定时器1→串口中止。假如咱们不对其进行设置,单片机就依照此次序不断的循环 查看各个中止标志(就像咱们日子中依照习气处理事物相同),但有时咱们需求人工设置高、低优先级,也便是说由编程者来设定哪些中止是高优先级、哪些中止是 低优先级(当然因为只要两级,所以必定只要一些中止处于优先等级,而其他的中止则处于同一等级,处于同一级其他中止次序就由天然优先级来确认,这一点请大 家必须搞清楚了)。
已然能够设定人工优先级,那么它又是如何来设置的呢?其实很简单,咱们只要把IP 寄存器的对应方位“1”就能够了,看下面的表:
×××PSPT1PX1PT0PX0
串口T1INT1T0INT0
开机时,每个中止都处于低优先级,咱们能够用指令来对优先级进行设置。例如:现在有如下要求,将T0、INT1 设为高优先级,其它为低优先级,求IP 的值。
IP 的首3 位没用,可任意取值,设为000,后边依据要求写:00000110,即IP=06H,看下面的表。
× × × PS PT1 PX1 PT0 PX0
00000110