您的位置 首页 发布

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

单片机在自主运行的时候一般是在执行一个死循环程序,在没有外界干扰(输入信号)的时候它基本处于一个封闭状态。比如一个电子时钟,它会按

单片机在自主运转的时分一般是在履行一个死循环程序,在没有外界搅扰(输入信号)的时分它底子处于一个关闭状况。比方一个电子时钟,它会准时、分、秒的规则来自主运转并经过输出设备(如液晶显现屏)把时间显现出来。在不需求对它进行调校的时分它不需求外部干涉,自主关闭地运转。假如这个时钟满足精确而又不掉电的话,它或许一向处于这种关闭运转状况。但工作往往不会如此简略,在时钟刚刚上电、或时钟需求从头校准、乃至时钟被带到了不同的时区的时分,就需求从头调校时钟,这时就要求时钟就必须具有调校功用。因而单片机体系往往又不会是一个单纯的关闭体系,它有些时分恰恰需求外部的干涉,这也便是外部中止发生的底子原由。
实际上在第二个示例演示中,就现已举过有按键输入的比方了,只不过其时运用的办法并不是外部中止,而是用程序查询的方法。下面就用外部中止的办法来改写一下第二个示例中,经过按键来更改闪耀速度的比方(第二个比方)。电路结构和接线不变,仅把程序改为下面的方法。
#include
unsigned int t=500; //界说一个全局变量t,并设定初始值为500次
//===========延时子函数,在8MHz晶振时约1ms=============
void delay_ms(unsigned int k)
{
unsigned int i,j;
for(i=0;i{
for(j=0;j<1140;j++)
;
}
}
//============主函数==================================
void main( 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)==========================
#pragma vector = INT0_vect
__interrupt void INT0_Server(void)
{
t = 100; //设定t的值为100次
}
//============中止函数(外部1)==========================
#pragmavector= INT1_vect
__interrupt void INT1_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的中止服务程序(即__interrupt void INT0_Server(void)函数)。这时全局变量t的值被该函数从头赋值为100(即延时为100ms),完结后又回到主函数中的while(1)内去持续履行,因而LED闪耀的速度就变快了。
调查程序可看出,假如没有中止去调用中止服务子程序,在主程序中是没有句子去调集它的。也便是说假如没有外部中止,中止服务子程序(即__interrupt void INT0_Server(void)函数)是永久不会被履行的。这也阐明,中止服务子程序是一类特别的子程序,它不能被主程序调用,只能被中止请求调用。因而,中止服务子程序有它固定的格局和写法。在不同的编译体系中的写法不完全相同,下面给出IAR下的中止服务子程序的格局。
#pragmavector= INT0_vect
__interrupt void INT0_Server(void)
{
中止服务程序代码
}
以上是固定格局,除斜体部格外,其余部分不行更改。斜体部分中的INT0_vect表明中止的向量号,不同的中止称号不相同(原型在头文件iom16.h中)。斜体部分中的INT0_Server是中止函数的称号,是由开发者自己界说的。尽管能够自界说,但称号仍是要获得“见名知义”,这样一看就知道是什么中止服务了。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/changshang/fabu/317316.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部