Arduino UNO R3自学笔记17 之 Arduino为啥要用中断?

注意:学习和写作过程中,部分资料搜集于互联网,如有侵权请联系删除。

前言:学习Arduino中断的概念及其功能。

1.什么是中断?

        单片机在执行程序时,发生一些其它紧急的事情,单片机将立即暂停当前程序,赶去处理中断程序,处理完中断程序后再返回刚才暂停处接着执行原来的程序。这个过程称之为中断

        举个通俗易懂的例子:当你在看电视的时候,突然电话响了,你去接电话。接完电话回来继续看电视,这就是一个中断过程。我们以此为例分析一下:

                                          主进程:看电视;

                                          中断触发源:电话响了;

                                          中断服务子程序:接电话;

   通过上述例子我们了解了一些术语,以及中断这个过程。

        思考一个问题,当在上述接电话的时候厨房的燃气报警器突然报警,是不是我们会立即挂掉电话去处理燃气的报警问题,在这个过程中出现了,在中断中又发生了中断,我们称之为中断嵌套,燃气报警器突然报警这个事件的后果很严重,因此我们挂了电话去执行检查开窗通风等操作,在这个过程中,我们认识到这个燃气报警器突然报警这个事件更加需要紧急处理,电话事件次之,看电视事件 紧急程度最低,这种紧急处理的排序就称之为  中断优先级

2.为什么要用中断?

        中断系统的主要目的:

                ●提高系统效率。

                ●维持系统可靠正常工作。

                ●满足实时处理要求。

                ●提供故障现场处理手段。

          为什么要用中断?为此我们继续做一个程序案例进行分析。

3.实验硬件及代码测试

硬件连接图:

代码:

void setup()
{  

Serial.begin(115200); //初始化串口,使用波特率115200,其余默认
Serial.println("Hello, I'm in a terminal!");
Serial.println();
pinMode(2, INPUT);
}
void loop()
{
 static uint32_t lastMillis = 0; //用于存储第一次获取的运行时间
 static uint32_t time0 = 0;      //用于存储时间差
 //A
/*
 lastMillis = micros();          //获取运行时间
    for(unsigned int m=0;m<10000;m++)  //一个嵌套,消耗CPU时间
    {
        for(unsigned int n=0;n<10000;n++)
        {
           __asm__ __volatile__ ("nop"); //这是一个空指令,但是会花费一个周期去执行
        }
    }
//B
*/
 time0=micros() - lastMillis;  //计算A到B的执行时间差
 Serial.print("程序A点运行到B点耗时:  ");
 Serial.print(time0/1000000);
 Serial.println("秒");
if(digitalRead(2)==0) Serial.println("按钮被按下!");
 delay(200);
}

  测试视频如下:

 

        通过视频我们看出按钮硬件及软件上监测是没有问题的(我们屏蔽了A到B 的代码是为了测试其余代码的正确)。

4.案例分析

直接给出如下代码:

void setup()
{  

Serial.begin(115200); //初始化串口,使用波特率115200,其余默认
Serial.println("Hello, I'm in a terminal!");
Serial.println();
}
void loop()
{
 static uint32_t lastMillis = 0; //用于存储第一次获取的运行时间
 static uint32_t time0 = 0;      //用于存储时间差
 //A
 lastMillis = micros();          //获取运行时间
    for(unsigned int m=0;m<10000;m++)  //一个嵌套,消耗CPU时间
    {
        for(unsigned int n=0;n<10000;n++)
        {
           __asm__ __volatile__ ("nop"); //这是一个空指令,但是会花费一个周期去执行
        }
    }
//B
 time0=micros() - lastMillis;  //计算A到B的执行时间差
 delay(200);
 Serial.print("程序A点运行到B点耗时:  ");
 Serial.print(time0/1000000);
 Serial.println("秒");
}

仿真运行效果:上述程序执行后,程序A点运行到B点耗时: 31秒。

        也就是说当有扫描式按钮在主程序等待被监测按下按钮这个动作时,至少会被阻塞31秒,也就是说,在那31秒内按钮按下也不会被监测到!当然一般程序不会有这种情况存在(阻塞31秒),这里将阻塞时间做了放大,实际可能阻塞有几秒钟,但是这种阻塞是非常不利于程序的实时性。

        此时我们再做一个按钮按下监测实验,不屏蔽阻塞代码,看阻塞代码对此按键扫描的影响。

        调整后代码如下:

void setup()
{  

Serial.begin(115200); //初始化串口,使用波特率115200,其余默认
Serial.println("Hello, I'm in a terminal!");
Serial.println();
pinMode(2, INPUT);
}
void loop()
{
 static uint32_t lastMillis = 0; //用于存储第一次获取的运行时间
 static uint32_t time0 = 0;      //用于存储时间差
 //A

 lastMillis = micros();          //获取运行时间
    for(unsigned int m=0;m<1600;m++)  //一个嵌套,消耗CPU时间
    {
        for(unsigned int n=0;n<10000;n++)
        {
           __asm__ __volatile__ ("nop"); //这是一个空指令,但是会花费一个周期去执行
        }
    }
//B

 time0=micros() - lastMillis;  //计算A到B的执行时间差
 Serial.print("程序A点运行到B点耗时:  ");
 Serial.print(time0/1000000);
 Serial.println("秒");
if(digitalRead(2)==0) Serial.println("按钮被按下!");
 delay(200);
}

注意:上述代码,我把阻塞时间调整了一下,由原来31秒调整到了5秒,好录测试视频。

测试视频如下:

        通过上述仿真视频看到,阻塞非常严重,你在设备端不断按按钮,但是系统却没检测到!这样的系统实时性就非常的差,操作体验感不佳!

        我们修改代码,用中断的方式监测按钮按下,硬件不变,代码如下:

void btn_press();
void setup()
{  

Serial.begin(115200); //初始化串口,使用波特率115200,其余默认
Serial.println("Hello, I'm in a terminal!");
Serial.println();
attachInterrupt(0, btn_press, LOW);//引脚20外部中断
}
void loop()
{
 static uint32_t lastMillis = 0; //用于存储第一次获取的运行时间
 static uint32_t time0 = 0;      //用于存储时间差
 //A
 lastMillis = micros();          //获取运行时间
    for(unsigned int m=0;m<10000;m++)  //一个嵌套,消耗CPU时间
    {
        for(unsigned int n=0;n<10000;n++)
        {
           __asm__ __volatile__ ("nop"); //这是一个空指令,但是会花费一个周期去执行
        }
    }
//B
 time0=micros() - lastMillis;  //计算A到B的执行时间差
 Serial.print("程序A点运行到B点耗时:  ");
 Serial.print(time0/1000000);
 Serial.println("秒"); 
 delay(200);
}
void btn_press()
{
    Serial.println("按钮被按下!");  
}

测试视频如下:

可以看到实时性非常强,基本和按下是同步检测到的!,这就是中断的优势。这也就是为什么用中断的缘故,Arduino的中断相关知识下一篇细讲。

上一篇:Arduino UNO R3自学笔记16 之 Arduino的定时器介绍及应用

下一篇:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ω-QAQ-Ω

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值