分享

Arduino 中断

 宽宽r700 2016-12-17

困扰

  • 一些遗憾,可能是一些遗憾的事情,比如中断发生的时候破坏了别的中断。

发现

  • 看起来是很有限的中断
  • Mega8看起来有两个中断,就是 PD2、PD3
  • 中断端口在中断时也可以正常读取,不影响原来功能-作为输入的。
  • 没被停止的中断会一直进行触发
  • 在中断中的程序会导致的问题:
    • 延时异常,因为timer0无法配合Arduino工作。
    • 但是可以在中断程序里置sei(),开启,而可能会导致的问题是别的中断来产生。
    • 最好的逻辑可能还是长时间的操作交回给主程序。
  • Arduino有一套停止中断的玩意
noInterrupts();
  //重要、时间敏感的代码
  interrupts();
  //其他代码写在这里

经验

  • 当使用LOW低电平触发的时候最好加个上拉电阻
开启的见识-Arduino 上拉电阻

中断的本质

在Mega8中
SLboat-Screen 2012-11-07 0.46.27.png

使用中断

Arduino的方式

void setup(){
  attachInterrupt(0, work, LOW); //中断0,D2低电平
}

void loop(){
//do some thing
}

void work(){
//here there -- 来到了中断
}

中断端口

  • 中断0,对应D2,PD2,INT0
  • 中断1,对应D3,PD3,INT1
  • 注意Mega8和UNO一样有最基本的两个


SLboat-Screen 2012-11-06 21.24.21.png

中断适合做什么

  • 适合用来配置一个标记,或者主程序的控制变量
  • 改变主程序的看法
  • 当只是检测输入的话,那么一个很长的比如显示周期里,几乎每次要检测,看起来很笨
    • 但是使用中断的话不太妨碍当前的事情。

中断不适合做什么

  • 执行一大段复杂涉及主要的程序
  • 因为那会中止别的所有事情进行
  • 中断就像是有急事找你,你得速度解决,因为还有别的事你要做,你不只有中断这么一件事情

设置调用函数

  • 只要函数名即可
  • 只能不带值的函数,否则不会被接受。
  • 看起来Arduino处理了,并且变成了指针。
  • 函数定义位于:WInterrupts.c
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)

终止中断

  • 看起来只要指定中断编号,然后使用:
detachInterrupt(0)

中断类型

  • LOW 指定端口只要是低电平就触发
  • CHANGE 指定端口值改变
  • RISING 指定端口变为高电平,看起来还要一个上升沿啥的
  • FALLING 指定端口从高变为低触发
有趣的是,CHANGE带来的改变可能被触发两次
比如空-高-空、或者低高低

中断实验

Arduino实验 切换跑马灯

全局中断

概念

停止所有一切的中断,来处理当前的现场,看起来是这样描述。

使用

全局中断禁止

cli();

全局中断开启

sei();

想法

  • 看起来cli停止了、sei又开始了

困扰

  • 这样之后中断的一切状态还在吗?

发现

  • 得带上括号不然啥也不会执行。
  • cli会影响到包括timer0的运作,在Arduino里意味着delay可能会在里面失常。
  • 如果没用cli、sei默认的也会开启。
  • 如果开了cli没用sei那么中断就不会开启。

官方文档

attachInterrupt()

Description

Specifies a function to call when an external interrupt occurs. Replaces any previous function that was attached to the interrupt. The Arduino Uno has :two external interrupts: numbers 0 (on digital pin 2) and 1 (on digital pin 3).
The table below shows the available interrupt pins on various Arduino boards.
Board interrupt 0 interrupt 1 interrupt 2 interrupt 3 interrupt 4 interrupt 5
Uno, Ethernet 2 3
Mega2560 2 3 21 20 19 18
Leonardo 3 2 0 1

见识

开始 Arduino 之旅! - 第三章 沿途见识[1]

那么我们该怎么做才能实现一个中断呢?这非常容易,除了有一些限制外。你只能监控两个端口(对一个普通arduino板)或者在 Arduino mega 上监控六个。此外,你还不能在中断函数中使用 delay() 函数。现在,你需要决定三件事:你需要监控的端口 (数字端口 2 或者 3, 被映射为中断 0 或 1);当中断发生时要执行的函数;以及要监控的端口上触发中断的行为——也就是端口状态变化的情况。你要监控数字端口也需要使用 pinMode();. 函数来设置成输出模式(译者注:可能John在这个地方写错了,需要监听的端口是不需要使用pinMode()函数来指定模式的,这已经在arduino语言中被预定义过,被硬编码为监听模式了)。

对于监听端口的状态变化,共有四种情况:LOW (当监听端口为低电平),CHANGE (电平状态发生变化,低变高或者高变低),RISING (由低电平变为高电平) 以及 FALLING (由高电平变为低电平)。一开始看上去挺难记住这些的,但是当你理解后就会觉得非常简单了。

/*
例子 3.2 – 中断
创建于 21/04/2010 —  作者 John Boxall — http://tronixstuff. —  CC by-sa v3.0
向 LCD 屏幕传送一些信息,同时监听两个中断
*/
#include <LiquidCrystal.h> // 需要这个库来控制LCD
// 使用指定的端口,初始化LCD函数库
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
float noisy = 0;
void setup()
{
lcd.begin(16, 2);             // 需要制定LCD显示屏显示的行数和列数
lcd.setCursor(0,0);
lcd.println('* example 3.2 * ');
lcd.setCursor(0,1);
lcd.println('tronixstuff.com ');
lcd.setCursor(0,1);
delay(4000);
lcd.clear();
randomSeed(analogRead(0)); // 刷新随机数种子
attachInterrupt(0, panicone, RISING); // 当中断 0 (数字端口 2) 的状态发生改变,将触发中断并执行函数 'panicone'
attachInterrupt(1, panictwo, RISING); // 当中断 1 (数字端口 3) 的状态发生改变,将触发中断并执行函数 'panictwo'
}
void loop()
{
noisy=random(1000);
lcd.setCursor(0,0);
lcd.print('Random Numbers!');
lcd.setCursor(0,1);
lcd.print('Number: ');
lcd.print(noisy,0);
delay(1000);
}
void panicone()
{
lcd.clear();
lcd.println('Interrupt one   ');
}
void panictwo()
{
lcd.clear();
lcd.println('Interrupt two   ');
}

AVR中断的学习_avr 沿途见识[2]

  八、中断标志会一直保持,如果中断被禁止或者是cpu不能马上响应的话。这是称作“挂起”,一旦cpu可以响应了,则马上按优先级处理中断。

  九、个别中断不带中断标志,比如配置为低电平触发的外部中断。只要满足条件就会向cpu一直发送中断申请。

  这里就会出现这样的问题:

  1.cpu暂时没响应中断,低电平没有了,这样就少了一次服务

  2.cpu响应了,响应完事,低电平还在,又多服务了一次

  所以设计的时候要注意

  一般这种低电平触发中断方式用于唤醒处于休眠模式的cpu,可参考具体方案。

  十、AVR响应中断时会将全局中断允许位关掉,不响应其它中断,所以也就不允许中断的嵌套。

  当然可以在中断服务程序中,将其开启,但是这样做是非常危险的,不提倡。

  十一、中断响应的过程如下

  1.清零全局中断

  2.将具体被响应的中断标志位清零

  3.中断断点地址压入堆栈,同时SP减2

  4.自动将中断向量地址压入PC,强制执行。

  以上均由硬件自动完成,软件需要做的事情如下:

  1.中断入口处指令:rjmp reset

  2.中断服务程序

  3.返回指令 reti

  十二、

  非常要注意的是中断只保存和恢复了断点的PC值,对其它的寄存器均没有保护,所以如果在中断服务程序中要是改变了某些寄存器的值的话就容易出现问题。

  所以,中断服务程序要尽量短,不做多余的操作,并且一旦对sreg有破坏的话,一定要在先将其压入堆栈。


引用信息

以下是[Arduino 中断]所有用到的引用信息,向这些伟大的家伙致敬:
  1. 跳转 ^ http://arduino./ch03.html
  2. 跳转 ^ http://www./html/avr/10746.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多