millis函数超时溢出问题

作者:Hing | 更新时间:2020-03-24 | 浏览量:1605

在看官方给出的开关例子时,有一个这样的疑惑,麻烦各位大佬给解答一下

void loop() {
  //每一定时间查询一次设备在线状态,同时替代心跳
  if (millis() - lastCheckStatusTime > postingInterval) {
    checkStatus();
  }
  //checkout 50ms 后 checkin
  if ( checkoutTime != 0 && millis() - checkoutTime > 50 ) {
    checkIn();
    checkoutTime = 0;
  }
  //读取串口信息
  while (Serial.available()) {
    String inputString = Serial.readStringUntil('\n');
    //检测json数据是否完整
    int jsonBeginAt = inputString.indexOf("{");
    int jsonEndAt = inputString.lastIndexOf("}");
    if (jsonBeginAt != -1 && jsonEndAt != -1) {
      //净化json数据
      inputString = inputString.substring(jsonBeginAt, jsonEndAt + 1);
      int len = inputString.length() + 1;
      char jsonString[len];
      inputString.toCharArray(jsonString, len);
      aJsonObject *msg = aJson.parse(jsonString);
      processMessage(msg);
      aJson.deleteItem(msg);
    }
  }
}
//查询设备在线状态
//{"M":"status"}\n
void checkStatus() {
  Serial.print("{\"M\":\"status\"}\n");
  lastCheckStatusTime = millis();
}

在官方给出的例子中,使用了millis()函数,通过查阅资料了解到该函数将在大约50天后溢出,重新归零。再看一下官方给出的例子,”每一定时间查询一次设备在线状态,同时替代心跳“所使用的是一个if判断,距离上次发送查询信息40秒后再次发送查询信息,这里用的是”millis() - lastCheckStatusTime > postingInterval“,”lastCheckStatusTime“是上次查询的时间,”postingInterval“是设定的时间间隔为40秒,再看一下if里面的函数,查询函数checkStatus()里的是先发送查询信息,”Serial.print("{\"M\":\"status\"}\n");“,然后将millis()里的的时间传递给”lastCheckStatusTime“,”lastCheckStatusTime = millis();“,那么这里也就会出现一个问题,假如在一次查询时程序的运行时间也就是millis()函数里面的值为49天23时59秒(millis()里是毫秒,这里为了好理解这样表示),前面说到在查询函数里先发送查询信息,然后将millis()里的的时间传递给”lastCheckStatusTime“,那么此时”lastCheckStatusTime“里存放的也就是49天23时59秒,那么回过头来再看心跳代码”millis() - lastCheckStatusTime > postingInterval“,这里的”lastCheckStatusTime“里存放的也就是49天23时59秒,而四十秒过后millis()函数将溢出,里面的值将变为39秒,此时  39秒 - 49天23时59秒   是小于”postingInterval“里设定的40秒的,那么if判断将为假,也就不会在执行查询函数了,也就没有心跳,两次后设备会掉线。这个问题该怎样解决,同样,在设备登陆是也用到了millis()函数,该如何解决?


评论:共1条

bunagi 评论于:2021-08-16 21:29:55
你首先应该看一下lastCheckStatusTime的数据类型 ,我猜想应该是无符号整形(unsigned int)。一个负数强制赋值给此类型的变量将变成这个负值的反码
返回顶部