11195浏览
查看: 11195|回复: 1

[进阶] Arduino编程之---周期性任务

[复制链接]
  Arduino在编程使用过程中,有一种情况非常常见。那就是某一项任务需要周期性的执行。可能是获取传感器的数值,也可能是控制灯的亮灭,或者发送串口数据等等。
       那么现在就来介绍下编写这些周期性任务的方法吧。

一、中断概念。
       很多使用Arduino的童鞋都没有用过其他种类的单片机,可能对中断的概念不是很了解。这里简要的说一下。
       大家都知道,程序在Arduino里是顺序执行的。一个循环走完,再继续下一个循环。当执行一个函数的时候,会跳转到那个函数的代码段去执行。中断与函数类似,也是在执行的过程中,会跳转到某一个函数去执行。但是中断的最大特点是他不是由代码来触发的,而是由一个“中断条件”来触发。也就是说当设置好“中断条件”之后,这个中断所跳转的函数不需要代码来触发,而是由“中断条件”来触发。
       那么中断条件有哪些?
       大概有两类软件中断和硬件中断。
       软件中断就是写个特定代码,让中断产生,这种方式与函数调用非常类似。所以一般只用在调试中。
       硬件中断是主要有实际意义的方式,常用的包含IO口产生的中断,定时器产生的中断,以及其他外设如:串口,I2C,SPI等产生的中断。
       中断产生之后,去执行的那段代码,我们称为“中断函数”。至此,中断相关的概念介绍的就差不多了。

二、利用定时器中断
       我们要完成一个周期性任务,需要的便是设置定时器中断。此时“中断条件”为定时器时间到。“中断函数”为你所要执行的任务。
       下面的程序是用定时器中断让13引脚 led灯每500ms变化一次。

ARDUINO 代码
  1. // led灯接UNO的13管脚
  2. #include <MsTimer2.h>  //定时器库的 头文件
  3. void flash() //中断处理函数,改变灯的状态
  4. {                        
  5.   static boolean output = HIGH;
  6.   digitalWrite(13, output);
  7.   output = !output;
  8. }
  9. void setup()
  10. {
  11.   pinMode(13, OUTPUT);
  12.   MsTimer2::set(500, flash);// 中断设置函数,每 500ms 进入一次中断
  13.   MsTimer2::start();     //开始计时
  14. }
  15. void loop()
  16. {
  17. }
复制代码


例子中MsTimer2::set(500,flash)便是设定中断条件500ms,中断函数为flash.
二、用一种简单的替代方式。

       在此再提供一种方法,利用  mills()同样函数可以实现中断的功能。mills()函数功能是获取系统运行的时间长度,单位ms。最大为9小时22分,如果超出时间将从0开始。函数的返回值为unsigned long型。

下面程序的功能让led灯亮灭各500ms :
ARDUINO 代码
  1. unsigned long ledOn=500,ledOff=500;
  2. //定义led灯变化的时间长度,每500ms变化一次
  3. int ledStatus;                     
  4. //定义LED灯的状态,HIGH or LOWm
  5. void setup()
  6. {
  7.     pinMode(13,OUTPUT);
  8.     digitalWrite(13,HIGH);
  9.     ledStatus=HIGH;
  10. }
  11. void loop()
  12. {
  13.     unsigned long nowtime=millis(); //获取当前的系统运行时间长度
  14.     if(ledStatus==HIGH)
  15.     //如果当前lled灯状态为高电平,则执行该程序
  16.     {
  17.       if(nowtime>ledOn)            
  18. //检测系统运行时间长度是否到500ms
  19.       {
  20.         ledOn=nowtime;              
  21. //记录当前时间长度,第一次为500ms,赋值给ledOn
  22.         ledOff=nowtime+500;         
  23. //计算出下一次led灯变化的时刻,第一次运行程序时应该在1000ms时关灯
  24.         digitalWrite(13,LOW);         //关掉led灯
  25.         ledStatus=LOW;            
  26. //记录当前led灯状态,下一次使用     
  27.       }
  28.     }
  29.   else{      
  30.          if(nowtime>ledOff)
  31.          {   
  32.           ledOff=nowtime;
  33.           ledOn=nowtime+500;
  34.           digitalWrite(13,HIGH);
  35.           ledStatus=HIGH;
  36.          }
  37.        }
  38. }
复制代码


该方式同样可以在大部分情况下达到500ms执行一次任务,但是该方式与之前中断的思想是完全不同的,同时也有一定的风险。即,当整个循环的时间大于500ms的时候,那么这个任务可能就没法及时的执行了,有被阻塞的风险。
       PS:使用mills()函数虽然没有中断可靠,但相比于delay()函数还是有很大优势的。其占用的整个程序运行时间短,如果用用delay()函数,在延时的时间内,CPU不能干别的事儿。


dsweiliang  初级技神

发表于 2015-12-29 09:36:49

我来消灭0回复吧~很好的帖子啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail