关于c语言中中断的问题

关于c语言中中断的问题,第1张

1void(中断函数返回类型(空型)) Time1 (中断函数名)(void(参数类型) interrupt 3 (中断号)
2: 中断条件发生时执行中断,比如void Time1(void) interrupt 3 是定时器1定时时间到发生中断,中断函数放在那里无所谓
3:void PxInt0(void) interrupt 0 中断名为PxInt0的0号中断
void PxInt1(void) interrupt 2 中断名为PxInt1的2号中断
void time0_int(void) interrupt 1 中断名为time0_int的1号中断
void time1_int(void) interrupt 3 中断名为time1_int的3号中断
4:中断的代码是你想中断执行的工作,中断的代码是根据任务,需要你自己写的

如果是用C去写的话,像汇编一样,开中断就行了。位置一般就在MAIN 之前的。
//晶振频率221184MHz
#include<at89x52h>

#define TIMER0H 0x4c
#define TIMER0L 0x00
#define TIMER0_RUN TR0=1
#define SECOND_OVERFLOW 40
#define SEG_PORT P0
#define DISPLAY_DIG1 P1&=0xf0;P1|=0x01

unsigned char g_CurrentDigit=0; //当前显示的数字

void timer() interrupt 1
{
static unsigned char s_Count = 0;
TH0 = TIMER0H; //重置定时器初值
TL0 = TIMER0L;
//每次进入中断服务程序,TH0和 TL0 的值都
TIMER0_RUN; //定时器运行,开始下一
if(s_Count != SECOND_OVERFLOW)
{ //未到整秒,把 sCount 值加1
s_Count++;
}
else
{ //到整秒,s_Count归 0,更新把当前显示
s_Count = 0;
if(g_CurrentDigit != 9)
{
g_CurrentDigit++;
}
else
{
g_CurrentDigit = 0;
}
}
return;
}

void Initial(void) //初始化
{
IE = 0x82; //仅允许Timer0 中断
TMOD = 0x01; //Timer0 使用工作方式 1(16位) ,定时器
TH0 = TIMER0H; //设置定时器初值
TL0 = TIMER0L;
TIMER0_RUN; //定时器开始运行
DISPLAY_DIG1;
}

void main()
{
unsigned char code SEG_CODE[]
= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
Initial();
while(1)
{
SEG_PORT = SEG_CODE[g_CurrentDigit]; //显示当前的数字
//当timer0溢出时,单片机响应 timer0 中断,调用 timer 函数,
//每40 次调用当前显示的数字加 1
}
}
程序分析:
程序中主程序做的事只是在死循环中反复显示当前的数字,每产生一次中断,程序就跳
转到中断服务函数 timer()中进行相应的更新。
这里中断服务函数 timer()有别于普通 C函数的地方是在声明中多了“interrupt 1” ,说明
这个函数是中断号为 1的中断服务函数。各个中断对应的中断号如表 38所示。
这个程序需要初始化的东西比较多, 我们把这些初始化语句都放在了初始化函数 Initial()
中,这也是程序初始化很常见的做法。我们还第一次用到了静态变量和全局变量。全局变量
是中断处理函数与外界程序进行参数传递的唯一途径,因此在单片机程序中全局变量的使
用频率要比普通的 C 语言程序高。尽管如此,由于全局变量的使用会影响程序的结构化,
所以在可以不使用全局变量的地方,还是要避免使用全局变量。在程序中,为了把全局变
量与静态变量跟普通变量区别开来,我们在变量前分别加了小写 g_和小写 s_以示区别。
IE 寄存器中的使能位和C中的中断号 中断源
0 外部中断0
1 定时器0溢出
2 外部中断1
3 定时器1溢出
4 串行口中断
5
定时器2溢出(仅在S52、
C52中有此中断源)
好了,以上是我找的一个实例,希望对你有帮助!

对于C51单片机,其内部总共有五级中断源
分别为外部中断0、定时器0、外部中断1、定时器1及串行中断。
C51单片机的中断使用时,主要是通过中断服务号来决定的。
如你定义一个中断服务函数:
void KEY(void) intterrupt 0
{
}
当外部中断0申请中断时
会自动根据interrupt后面的0,找到上面定义的这个中断服务函数。
对于其他四个中断源,其对应的中断号分别为1、2 、3、4

首先,在初始化中设置好I/O口功能。开中断,初始化串口。
然后写个串口中断函数,例如:
void interrupt isr(void)
if(RCIE&&RCIF) //串口接收中断
{
while(!RCIF);
NOP();NOP();NOP();
recive_dat[1]=RCREG; //接收1位数据
NOP();NOP();NOP();
CREN=0;
NOP();NOP();NOP();
CREN=1;
}

当然,你把括号中加上你的函数就好了。
本人建议不要在中断中处理函数,最好在中断中返回个标志位,然后在主函数中执行函数。
如果一定要在中断中执行函数,这个函数最好在其他地方不使用,否则容易出错哦。
你说的RXIF我不知道,我只知道RCIF。

C51中断函数格式
Keil C51编译器中断函数语法定义如下:
(C语言不用处理现场保护了) interrupt n <----这个是重点
void 函数名() interrupt n
{
}
//定时器T0中断
void 函数名() interrupt 1
{

}
C51编译器允许0~31个中断,下列中断及其相关地址为8051控制器所提供的中断:
0:EXTERNAL 0 地址:0003H
1:TIMER/COUNTER 0 地址:000BH
2:EXTERNAL 1 地址:0013H
3:TIMER/COUNTER 1 地址:001BH
4:SERIAL PORT 地址:0023H
编写中断函数时应遵循下列规则:
·不能进行参数传递。如果中断过程包括任何参数声明,则编译器将产生一个错误信息。
·无返回值。如果想定义一个返回值将产生错误,但是,如果返回整型值,编译器将不产生
错误信息,因为整型值是默认值,编译器不能清楚识别。
·在任何情况下,不能直接调用中断函数,否则编译器会产生错误。由于退出中断过程是由
指令RETI完成的,该指令影响MCS-51单片机的硬件中断系统,直接调用中断函数时,硬件
上没有中断请求存在,因而这个指令的结果是不定的,并且通常是致命的。
·编译器从绝对地址8n+3处产生一个中断向量,其中n为中断号,该向量包括一个中断过
程的跳转,向量的产生可由编译器控制指令NOINTVECTOR压缩,因而程序员可以从独立的汇
编模块中提供中断向量。
·可以在中断函数定义中使用using指定当前使用的寄存器组。格式如下:
void 函数名([形式参数])interrupt n [using m]
MCS-51单片机有四组寄存器R0~R7,程序具体使用哪一组寄存器由程序状态字PSW中
的两位RS1和RS0来确定。在中断函数定义时,可以用using指定该函数具体使用哪一组寄
存器,m在0,1,2,3这4个数中取值,对应四组寄存器组。例如:
void delay() interrupt 3 using 2
·在中断函数中调用的函数所使用的寄存器组必须与中断函数相同。当没有使用using指令
时,编译器会选择一个寄存器组作为绝对寄存器访问。程序员必须保证按要求使用相应寄存
器组,C编译器不会对此检查。
·如果在中断函数中执行浮点运算,必须保存浮点寄存器状态,当没有其他程序执行浮点运
算时,可以不保存。

using1 表示用寄存器工作组1。其实不加也可以,在c语言中,是自动分配寄存器的,所以可以不加。。
interrupt 1 后面数字是中断源 ,表示启用中断源1(定时器0)(51单片机里有5个中断源)


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/13182095.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-06-17
下一篇 2023-06-17

发表评论

登录后才能评论

评论列表(0条)

保存