定时计数器T0在C51中断服务函数关键字interrupt关键字对应的中断号是几?

您的举报已经提交成功,我们将尽快处理,谢谢!
这要根据编程机型而定
Keil C51 的 用
函数名()_intterupt 0 using 1
keil ARM 用中断向量
函数名()_ir...
1)点A(4,m)和B(-1,n)分别在Y=8/X图象上,则:
m=8/4=2;n=8/-1=-8.即点A为(4,2),点B为(-1,-8);
ORG0000HAJMPSTARTORG0023HLJMPACTNT;串口中断入口地址ORG0000H;------主程序-------- ,#20H;置定时器...
1、11.3+17.7+1=30、17.3+11.7+1=30…&br /&2、题能用整数解决1、3、5、7、9、11、13、15都奇数根据计算规律:奇数+奇数...
沙参皮饮: 沙参10克,皮30克,二者洗净后放入锅中,加适量水煎煮,分成2~3份,一天内服完
大家还关注
在线回答小学数学问题 小明有面值8角和1...4855人阅读
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,在使用中需灵活取舍。&
关于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”就可以了,看下面的表:
× × × PS PT1 PX1 PT0 PX0
串口 T1 INT1 T0 INT0
开机时,每个中断都处于低优先级,我们可以用指令来对优先级进行设置。例如:现在有如下要求,将T0、INT1 设为高优先级,其它为低优先级,求IP 的值。
IP 的首3 位没用,可任意取值,设为000,后面根据要求写:,即IP=06H,看下面的表。
× × × PS PT1 PX1 PT0 PX0
0 0 0 0 0 1 1 0
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:172262次
积分:1996
积分:1996
排名:第15976名
原创:44篇
转载:55篇
评论:20条
(1)(1)(1)(2)(8)(5)(2)(3)(2)(2)(1)(5)(2)(1)(2)(1)(1)(12)(4)(2)(2)(10)(3)(3)(1)(5)(3)(3)(3)(1)(1)(5)(1)403 Forbidden
403 Forbidden&&/&&&&/&&&&/&&
要求:编写一个计数器程序,将T0 作为计数器来使用,对外部信号计数,将所计数字
显示在数码管上。
该部分的硬件电路如图 6-1 所示,U1 的P0 口和P2 口的部份引脚构成了6 位LED 数码
管驱动电路,数码管采用共阳型,使用PNP 型三极管作为片选端的驱动,所有三极管的发
射极连在一起,接到正电源端,它们的基极则分别连到P2.0&#,当P2.0&# 中某引脚
输是低电平时,三极管导通,给相应的数码管供电,该位数码管点亮哪些笔段,则取决于笔
段引脚是高或低电平。图中看出,所有6 位数码管的笔段连在一起,通过限流电阻后接到
P0 口,因此,哪些笔段亮就取决于P0 口的8 根线的状态。
编写程序时,首先根据硬件连线写出 LED 数码管的字形码、位驱动码,然后编写程序
#include &reg51.h&
#define uchar unsigned char
#define uint unsigned int
uchar code BitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB}; //位驱动码
uchar code
DispTab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x8
6,0x8E,0xFF}; //字形码
uchar DispBuf[6]; //显示缓冲区
void Timer1() interrupt 3
uchar C //计数器,显示程序通过它得知现正显示哪个数码管
TH1=()/256;
TL1=()%256; //重置初值
tmp=BitTab[Count]; //取位值
P2=P2|0 //P2 与B 相或
P2=P2& //P2 与取出的位值相与
tmp=DispBuf[Count];//取出待显示的数 tmp=DispTab[tmp]; //取字形码
if(Count==6)
void main()
TMOD=0x15; //定时器0 工作于计数方式1,定时器1 工作于定时方式1
TH1=()/256;
TL1=()%256; //定时时间为3000 个周期
TR0=1; //计数器0 开始运行
{ tmp=TL0|(TH0&&8); //取T0 中的数值
DispBuf[5]=tmp%10;
DispBuf[4]=tmp%10;
DispBuf[3]=tmp%10;
DispBuf[2]=tmp%10;
DispBuf[1]=tmp/10;
DispBuf[0]=0;
这个程序中用到了一个新的知识点,即数组,首先作一个介绍。
数组是 C51 的一种构造数据类型,数组必须由具有相同数据类型的元素构成,这些数
据的类型就是数组的基本类型,如:数组中的所有元素都是整型,则该数组称为整型数组,
如所有元素都是字符型,则该数组称为字符型数组。
数组必须要先定义,后使用,这里仅介绍一维数组的定义,其方式为:
类型说明符 数组名[整型表达式]
定义好数组后,可以通过:数组名[整型表达式]来使用数组元素。
在定义数组时,可以对数组进行初始化,即给其赋予初值,这可用以下的一些方法实现:
1. 在定义数组时对数组的全部元素赋予初值:
例:int a[5]={1,2,3,4,5};
2. 只对数组的部分元素初始化;
例:int a[5]={1,2};
上面定义的a 数组共有5 个元素,但只对前两个赋初值,因此a[0]和a[1]的值是1、2,
而后面3 个元素的值全是0。
3. 在定义数组时对数组元素的全部元素不赋初值,则数组元素值均被初始化为 0
4. 可以在定义时不指明数组元素的个数,而根据赋值部分由编译器自动确定
例:uchar BitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB};
则相当于定义了一个BitTab[6]这样一个数组。
5.可以为数组指定存储空间,这个例子中,未指定空间时,将数组定义在内部RAM
中,可以用code 关键字将数组元素定义在ROM 空间中。
uchar code BitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB};
用这两种定义分别编译,可以看出使用了code 关键字后系统占用的RAM 数减少了,
这种方式用于编程中不需要改变内容的场合,如显示数码管的字形码等是很合适的。
6.C 语言并不对越界使用数组进行检测,例如上例中数组的长度是6,其元素应该是
从BitTab[0]~BitTab[5],但是如果你在程序中写上BitTab[6],编译器并不会认为这有语法错
误,也不会给出警告(其他语言如BASCI 等则有严格的规定,这种情况将视为语法错误),
因此,编程者必须自己小心确认这是否是你需要的结果。
程序分析:程序中将定时器T1用作数码管显示,通过interrupt 3 关键字定义函数Timer1()
为定时器1 中断服务程序,在这个中断服务程序中,使用
TH1=()/256;
TL1=()%256;
来重置定时器初值,这其中3000 即为定时周期,这样的写法可以直观地看到定时周期数,
是常用的一种写法。其余程序段分别完成取位码以选择数码管、从显示缓冲区获得待显示数
值、根据该数值取段码以点亮相应笔段等任务。其中使用了一个计数器,该计数器的值从
0~5 对应第1 到第6 位的数码管。
主程序的第一部分是做一些初始化的操作,设置定时器工作模式、开启定时器 T1、开
启计数器T0、开启T1 中断及总中断,随后进入主循环,主循环首先用unsigned int 型变量
tmp 取出T0 中的数值,这里使用了&tmp=TL0|(TH0&&8);&这样的形式,这相当于
tmp=TH0*256+TL0,但比之于后一种形式,该方式可以得到更高的效,其后就是将tmp 值
不断地除10 取整,这样将int 型数据的各位分离并送入相应的显示缓冲区。
推荐文章 TOP10}

我要回帖

更多关于 c51计数器程序 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信