✅ 操作成功!

单片机中断程序

发布时间:2023-06-12 作者:admin 来源:文学

单片机中断程序

单片机中断程序

南非和中国时差-两圆的位置关系

2023年3月17日发(作者:诗经是我国)

单片机外部中断详解及程序

单片机在自主运行的时候一般是在执行一个死循环

程序,在没有外界干扰(输入信号)的时候它基本处于一

个封闭状态。比如一个电子时钟,它会按时、分、秒的

规律来自主运行并通过输出设备(如液晶显示屏)把时间

显示出来。在不需要对它进行调校的时候它不需要外部

干预,自主封闭地运行。如果这个时钟足够准确而又不

掉电的话,它可能一直处于这种封闭运行状态。但事情

往往不会如此简单,在时钟刚刚上电、或时钟需要重新

校准、甚至时钟被带到了不同的时区的时候,就需要重

新调校时钟,这时就要求时钟就必须具有调校功能。因

此单片机系统往往又不会是一个单纯的封闭系统,它有

些时候恰恰需要外部的干预,这也就是外部中断产生的

根本原由。

实际上在第二个示例演示中,就已经举过有按键输入的

例子了,只不过当时使用的方法并不是外部中断,而是

用程序查询的方式。下面就用外部中断的方法来改写一

下第二个示例中,通过按键来更改闪烁速度的例子(第二

个例子)。电路结构和接线不变,仅把程序改为下面的形

式。

#include;

unsignedintt=500;//定义一个全局变量t,并设定初

始值为500次

//===========延时子函数,在8MHz晶振时约

1ms=============

voiddelay_ms(unsignedintk)

{

unsignedinti,j;

for(i=0;i

{

for(j=0;j<1140;j++)

;

}

}

//============主函数

==================================

voidmain(void)

{

DDRB=0xFF;//设置端口B为输出方向

PORTB=0xFF;//设置端口B的输出为全高电平

DDRD=0x00;//设置端口D为输入方向

PORTD=0xFF;//设定端口D为内部上拉方式,无信号输

入时处于高电平状态

MCUCR=0x0A;//设定INT0、INT1为下降沿触发

GICR=0xC0;//使能INT0、INT1中断

SREG=0x80;//使能总中断

while(1)

{

PORTB=0x55;//让接在端口B上的LED显示01010101

delay_ms(t);//延时t个ms

PORTB=0xAA;//让接在端口B上的LED显示01010101

delay_ms(t);//延时t个ms

}

}

//============中断函数(外部

0)==========================

#pragmavector=INT0_vect

__interruptvoidINT0_Server(void)

{

t=100;//设定t的值为100次

}

//============中断函数(外部

1)==========================

#pragmavector=INT1_vect

__interruptvoidINT1_Server(void)

{

t=500;//设定t的值为500次

}

把上述程序进行编译并下载到单片机中,可以看到结果

与第二个示例中的完全一致。下面就来分析一下键盘中

断的程序原理。

在分析程序之前,先来了解一下什么叫“外部中断

”。前面已讲述过,在没有打扰的情况下,单片机

的程序在封闭状态下自主运行,但如果在某一时刻需要

响应一个外部事件(比如有按键被按下),这时就需要用

外部中断。具体来讲,外部中断就是在单片机的一个引

脚上,由于外部因素导致了一个电平的变化(比如由高变

低),而通过捕获到这个变化,单片机内部自主执行的程

序就被暂时打断,转而去执行相应的中断处理程序,执

行完后又回到原来中断的地方继续执行原程序。这个引

脚上的电平变化,就申请了一个外部中断事件,而这个

能申请外部中断的引脚就是外部中断的触发引脚。在上

面的例子中,可以看到两个按键S1、S2被接到了

ATMega16的PD3和PD2引脚,而这两个引脚正是该单片

机的两个外部中断(INT1和INT0)的触发引脚(第二功

能)。当按键没有按下时,这两个引脚都为高电平(执行

过PORTD=0xFF),当按键被按下时,引脚电平跳变为低

电平,这时若单片机设置成允许中断申请,就会触发外

部中断事件,从而转去执行中断服务程序。明白了这个

过程之后,接下来就可以分析程序了。

程序执行后,主程序就一直在不停的运行while(1)内的

这个死循环,让LED以t=500ms的初始值来交替闪烁,直

到有外部中断来打断它。假设某一时刻按键S2被按下,

这时由于引脚PD2上的电平突然被拉低,申请了一个外

部中断0(INT0),这时的程序就转去执行外部中断0的

中断服务程序(即__interruptvoidINT0_Server(void)

函数)。这时全局变量t的值被该函数重新赋值为100(即

延时为100ms),完成后又回到主函数中的while(1)内去

继续执行,因此LED闪烁的速度就变快了。

观察程序可看出,如果没有中断去调用中断服务子程序,

在主程序中是没有语句去调动它的。也就是说如果没有

外部中断,中断服务子程序(即__interruptvoid

INT0_Server(void)函数)是永远不会被执行的。这也说

明,中断服务子程序是一类特殊的子程序,它不能被主

程序调用,只能被中断申请调用。因此,中断服务子程

序有它固定的格式和写法。在不同的编译系统中的写法

不完全一样,下面给出IAR下的中断服务子程序的格式。

#pragmavector=INT0_vect

__interruptvoidINT0_Server(void)

{

中断服务程序代码

}

以上是固定格式,除斜体部分外,其余部分不可更改。

斜体部分中的INT0_vect表示中断的向量号,不同的中

断名称不一样(原型在头文件iom16.h中)。斜体部分中

的INT0_Server是中断函数的名称,是由开发者自己定

义的。虽然可以自定义,但名称还是要取得“见名

知义”,这样一看就知道是什么中断服务了。

👁️ 阅读量:0