极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 27936|回复: 10

利用内部时间中断函数如何实现多次不同间隔时间的中断啊?

[复制链接]
发表于 2013-5-12 10:59:32 | 显示全部楼层 |阅读模式
如程序所示:想实现第多次不同间隔时间让LED灯亮灭一次
  1. // led灯接UNO的13管脚
  2. #include   <MsTimer2.h>     //定时器库的 头文件
  3. int i=500;                   //定义初始值,500MS执行中断
  4. int flag=1;                  //记录中断的次数

  5. void flash()                //中断处理函数,13#LED灯亮500MS后灭
  6. {                        
  7.   digitalWrite(13, HIGH);
  8.   delay(500);              //这里用delay函数是否影响其他程序
  9. digitalWrite(13, LOW);
  10.   switch (flag) {
  11. case 1:                //第一次中断后设置下一次中断的时间
  12.     {i=i+1000;              //下次中断的时间设置1.5秒
  13.      flag+=1;
  14.      break;}
  15. case 2 :               //第二次中断后设置下一次中断的时间
  16. { i=i+2500;          //下次中断的时间设置4秒
  17.      flag+=1;              
  18.      break;}
  19. case 3:            //第三次中断后设置下一次中断的时间
  20.     { i=i+ 4500;            //下次中断的时间设置8.5秒
  21.      flag+=1;
  22.      break;}
  23. }
  24.   }
  25. void setup()
  26. {
  27.   pinMode(13, OUTPUT);
  28.   MsTimer2::set(i, flash);   // 中断设置函数,
  29.   MsTimer2::start();         //开始计时
  30. }

  31. void loop()
  32. {

  33. }
复制代码
回复

使用道具 举报

 楼主| 发表于 2013-5-12 11:13:35 | 显示全部楼层
  1. // led灯接UNO的13管脚
  2. #include   <MsTimer2.h>     //定时器库的 头文件
  3. int i=500;                   //定义初始值,500MS执行中断
  4. int flag=1;                  //记录中断的次数

  5. void flash()                //中断处理函数,13#LED灯亮500MS后灭
  6. {                        
  7.   digitalWrite(13, HIGH);
  8.   delay(500);              //这里用delay函数是否影响其他程序
  9.   digitalWrite(13, LOW);
  10.   
  11.   }
  12. void setup()
  13. {
  14.   pinMode(13, OUTPUT);
  15.   
  16. }

  17. void loop()
  18. {
  19.   MsTimer2::set(i, flash);   // 中断设置函数,
  20.   MsTimer2::start();         //开始计时
  21.   switch (flag) {
  22. case 1:                //第一次中断后设置下一次中断的时间
  23.     {i=i+1000;              //下次中断的时间设置1.5秒
  24.      flag+=1;
  25.      break;}
  26. case 2 :               //第二次中断后设置下一次中断的时间
  27.     { i=i+2500;            //下次中断的时间设置4秒
  28.      flag+=1;              
  29.      break;}
  30. case 3:                //第三次中断后设置下一次中断的时间
  31.     { i=i+ 4500;            //下次中断的时间设置8.5秒
  32.      flag=1;
  33.      i=500;
  34.      break;}
  35. }

  36. }
复制代码
改成以上代码之后,LED没有反应;
有几个问题:1
1.定时中断函数不能放入LOOP循环里吗?
2.能够修改中断函数的时间;
3.中断函数能否用delay();
回复 支持 反对

使用道具 举报

发表于 2013-5-12 12:07:36 | 显示全部楼层
本帖最后由 学长 于 2013-5-12 12:34 编辑

我最近也是接触定时器.. 你用的是 mstime2
我用的是 TimerOne
不过, 大致上要把握2个重点,
1.中断 interupt 的动作是停止目前 CPU 所执行的程序
然後进行中断指定的处理指定.. 一般来说,中断之後会指定一个中断处理函数。
2. ATmega 168/328 并非真实的多执行绪

所以解答就出来了
1.  中断函数如果放入 loop 里面, 那函数就不只有中断时执行。
2.  中断时间可以修改, 我比较习惯的方式是, 把 timer 当是计时器,  每 Tick 多少时间,
     再由 Tick 来还原时间,并执行相应的函数。
3.  應該能使用 但手冊上 說中斷時 delay 時間不變
回复 支持 反对

使用道具 举报

发表于 2013-5-12 12:13:10 | 显示全部楼层
BTW
你更改过後的程序逻辑就不对了.. .
Setup 跟 loop 还没分清楚吧?
回复 支持 反对

使用道具 举报

发表于 2013-6-1 15:30:25 | 显示全部楼层
本帖最后由 zjyylj 于 2013-6-2 20:37 编辑

中断函数发生时,delay()和millis()的数值将不会继续变化。
这儿有个第三方的Timer库

你可以试试看,我正在学习。
回复 支持 反对

使用道具 举报

发表于 2013-6-1 16:56:19 | 显示全部楼层
本帖最后由 zjyylj 于 2013-6-1 17:00 编辑

首先有些概念上的错误:
【1】MsTimer2::set(unsigned long ms, void (*f)())这个函数第一个参数的类型是unsigned long,不是int。
【2】setup()中的函数只执行一遍,也就是MsTimer2::set(i, flash);执行完之后,虽然 i 改变了,但是定时器的间隔并没有变化。
【3】在中断函数发生时,delay的值不会变化。
我的板子是Mega2560,用不了MsTimer2,用FlexiTimer2代替,按你的要求写了个类似的程序,测试通过。
  1. /* 用FlexiTimer2实现不同时间间隔的中断
  2.    要点:在中断函数的子块中要暂停原来的中断,开始新的中断
  3.          这样新的时间间隔才能生效
  4.          如果只是执行一个LED的通断,
  5.          最好不要使用delay(),
  6.          在需要控制的时候再调用函数,
  7.          其他时间释放MCU。
  8.    功能:13脚的LED点亮2秒,熄灭0.5秒。
  9.          在case中添加更多情况可实现更多功能。
  10.     ******* Made by zjyylj *********
  11. */

  12. #include   <FlexiTimer2.h>     //定时器库的 头文件
  13. unsigned long i=1000;            //定义初始值,1000MS执行中断
  14. int flag=1;                  //中断index号

  15. void flash()                //中断处理函数
  16. {                        
  17.   Serial.println("main");

  18.   switch (flag) {
  19.   case 1:                //第一次中断后设置下一次中断的时间
  20.     {
  21.       FlexiTimer2::stop;
  22.       digitalWrite(13, HIGH);
  23.       i=i+1000;              //下次中断的时间设置2秒
  24.       flag=2;
  25.       Serial.println("case1");
  26.       FlexiTimer2::set(i, flash);
  27.       FlexiTimer2::start();
  28.       break;
  29.     }
  30.   case 2 :               //第二次中断后设置下一次中断的时间
  31.     {
  32.       FlexiTimer2::stop;
  33.       digitalWrite(13, LOW);
  34.       i=500;              //下次中断的时间设置0.5秒
  35.       flag=1;
  36.       Serial.println("case2");
  37.       FlexiTimer2::set(i, flash);
  38.       FlexiTimer2::start();
  39.       break;
  40.     }
  41.   }
  42. }
  43. void setup()
  44. {
  45.   Serial.begin(9600);
  46.   pinMode(13, OUTPUT);
  47.   FlexiTimer2::set(i, flash);   // 中断设置函数,
  48.   FlexiTimer2::start();         //开始计时
  49. }

  50. void loop()
  51. {
  52. }
复制代码
这个同时只能启用一个中断,过段时间我写个用第三方Timer库做的多种间隔中断同时启用。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2013-6-1 18:04:38 | 显示全部楼层
本帖最后由 zjyylj 于 2013-6-2 20:37 编辑

第三方Timer库已经翻译,详见
wiki链接
回复 支持 反对

使用道具 举报

发表于 2014-4-13 10:31:43 | 显示全部楼层
zjyylj 发表于 2013-6-1 16:56
首先有些概念上的错误:
【1】MsTimer2::set(unsigned long ms, void (*f)())这个函数第一个参数的类型是u ...

好像你这也只循环一次吧  进入setup中,执行初始化,执行Flash函数,switch中break 直接跳出整个。loop中
中中断函数和计时函数吧
回复 支持 反对

使用道具 举报

发表于 2014-5-13 04:57:08 | 显示全部楼层
zjyylj 发表于 2013-6-1 16:56
首先有些概念上的错误:
【1】MsTimer2::set(unsigned long ms, void (*f)())这个函数第一个参数的类型是u ...


FlexiTimer2怎么用啊

看wiki里有 Timer - 利用millis()函数来模拟多线程 的用法

另外求一个 Timer库
回复 支持 反对

使用道具 举报

发表于 2014-6-21 11:25:25 | 显示全部楼层
初学Arduino定时器,thank you!
回复 支持 反对

使用道具 举报

发表于 2016-5-28 12:00:14 | 显示全部楼层
存了
有时间看看
回复 支持 反对

使用道具 举报

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

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-29 12:20 , Processed in 0.056304 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表