Arduino 中用millis()延时溢出问题的解决

本文介绍了在Arduino中使用delay()函数的局限性,提出使用定时器和millis()函数进行非阻塞延时。重点讨论了如何避免millis()溢出对延时精度的影响,提供了一种基于计数器边界值计算延时的新方法。
摘要由CSDN通过智能技术生成
   在我们用Arduino程序的时候会用到大量的延时,在这是通常都会使用delay()函数来做延迟,但是delay()含有有一个致命弱点,那就是会阻塞,如果延时的时间较短还没有多少影响,主要程序的执行效率要求不高倒也能接受,但是如果要求效率高的情况下delay()函数就不太适用了。这是外面可选的就必须时非阻塞的情况下还能达到延时效果,在Arduino可以使用定时器来实现延时,但是这样会额外的占用定时器,在资源紧张的情况下最好的方法接受使用millis()运行时间计数函数,这样尽量减少了额外的开销的同时还能达到延时的效果。通常使用millis()做延时的做法如下:
unsigned long previousMillis;
void setup() {
  pinMode(D5_PIN, OUTPUT);  // 将D5针脚配置为输出模式
}
void loop() {
  outWater();  // 执行灌溉操作
}
void myDelay(unsigned long interval) {              
    unsigned long currentMillis=millis();
    if(currentMillis-previousMillis>interval){
       previousMillis=currentMillis;
       //延时时间到,执行需要执行的任务
   }
}

这个程序就是反复把当前值赋予给previousMillis。但是一旦millis()溢出归零,那么previousMillis是个很大的数字,
currentMillis-previousMillis>interval这句程序看似没什么问题,但是外面都知道,数字的大小是有限制的,一旦超过限制大小就会出现溢出,从这句代码看,好像也不会有太大影响,因为即使溢出,条件也会成立,因为外面申明的数据类型为无符号类型,所以条件都会成立,只是当溢出时,条件会提前满足,达不到精准延时的效果。
下面提出了另外的一种解决方法,我们都知道数字类型的大小是有边界的,那么当溢出后,计数器会从0 开始从新计数,那么这时候可用用数字最大边界值来减去历史时间戳,得到在溢出前一毫秒的持续时间长度,然后再加上从新计数的长度就得到了精确的延时时间。代码如下:

unsigned long previousMillis;
void setup() {
  pinMode(D5_PIN, OUTPUT);  // 将D5针脚配置为输出模式
}
void loop() {
  outWater();  // 执行灌溉操作
}
void myDelay(unsigned long interval) {              
    unsigned long currentMillis=millis();
    unsigned long elapsed;
    if(currentMillis<previousMillis){
      elapsed=((unsigned long)-1)-previousMillis+currentMillis;
    }else{
      elapsed=currentMillis-previousMillis;
    }
    if (elapsed >= interval) {  // 比较持续时间
       previousMillis=currentMillis;
       //延时时间到,执行需要执行的任务
   }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值