极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 10358|回复: 2

求教关于millis() 的问题?

[复制链接]
发表于 2014-9-10 23:16:09 | 显示全部楼层 |阅读模式
我是初学,请指教!!{:soso_e100:}

在《Arduino 从基础到实践》(代码如下),英文资料说millis() 在大约50天后清零,我想问:如果刚刚在上一次按钮按动后millis() 恰好清零了,重新计数了,这样的话程序中if(state == HIGH && (millis() - changeTime)> 5000)的条件该如何比较??有可能两次按钮时间间隔不到5秒!!也可能超过5秒!!

//项目三 -- 互动交通信号灯
int carRed = 12; //设置汽车灯
int carYellow = 11;
int carGreen = 10;
int button = 9; //按钮引脚
int pedRed = 8; //设置行人灯
int pedGreen = 7;
int crossTime = 5000;//允许行人通过的时间
unsigned long changeTime;//按钮按下后的时间

void setup() {
     //所有LED设置为输出模式
      pinMode(carRed, OUTPUT);
      pinMode(carYellow, OUTPUT);
      pinMode(carGreen, OUTPUT);
      pinMode(pedRed, OUTPUT);
      pinMode(pedGreen, OUTPUT);
      pinMode(button, INPUT); //按钮设置为输入模式
      digitalWrite(carGreen, HIGH); //开始时,汽车灯绿灯
      digitalWrite(pedRed, HIGH);  //行人灯为红灯
}

void loop() {
     int state = digitalRead(button);
     //检测按钮是否被按下,并且是否距上次按下后有5秒的等待时间
     if(state == HIGH && (millis() - changeTime)> 5000){
                //调用变灯函数
               changeLights();
       }
}

void changeLights() {
       digitalWrite(carGreen, LOW); //汽车绿灯灭
       digitalWrite(carYellow, HIGH); //汽车黄灯亮
       delay(2000); //等待2秒
               
       digitalWrite(carYellow, LOW); //汽车黄灯灭
       digitalWrite(carRed, HIGH); //汽车红灯亮
       delay(1000); //为安全考虑等待1秒
               
       digitalWrite(pedRed, LOW); //行人红灯灭
       digitalWrite(pedGreen, HIGH); //行人绿灯亮

       delay(crossTime); //等待一个通过时间
               
       //闪烁行人灯绿灯,提示可过马路时间快到
       for (int x=0; x<10; x++) {
               digitalWrite(pedGreen, HIGH);
               delay(250);
               digitalWrite(pedGreen, LOW);
               delay(250);
        }                        
        digitalWrite(pedRed, HIGH);//行人红灯亮
        delay(500);

        digitalWrite(carRed, LOW); //汽车红灯灭
        digitalWrite(carYellow, HIGH); //汽车黄灯亮        
        delay(1000);
        digitalWrite(carYellow, LOW); //汽车黄灯灭
        digitalWrite(carGreen, HIGH); //汽车绿灯亮

        changeTime = millis(); //记录自上一次灯变化的时间
        //返回到主函数循环中
}


回复

使用道具 举报

发表于 2014-9-11 09:40:55 | 显示全部楼层
本帖最后由 Super169 于 2014-9-11 09:49 编辑

基於 unsigned long 的特性, 本身就沒有問題的.

有懷疑的話, 你可以試試以下程式.
millis() 會在  4,294,967,295 之後出現 rollover, 用 1234 - 4294967200, 數學上的結果應該是負數的.
但由於結果是 (unsigned long), 反而解決了問題, 可以得到想要的結果 1300.  (詳情自己研究一下數字的 binary 儲存方法)

如果害怕結果不是 unsigned long, 可以自己指定轉成 unsigned long, 但由於 millis() 本身回傳 unsigned long, 所以是沒必要的.

  1. unsigned long start_ms = 4294967200;
  2. unsigned long end_ms = 1234;
  3. unsigned long elapsed_ms;
  4. void setup() {
  5.   // put your setup code here, to run once:
  6.   Serial.begin(57600);
  7.   Serial.println(end_ms - start_ms);
  8.   elapsed_ms = (unsigned long)(end_ms - start_ms);
  9.   Serial.println(elapsed_ms);
  10.   Serial.println(millis() - start_ms);
  11.   Serial.println((unsigned long)(millis() - start_ms));
  12.   if ((millis() - start_ms) > 50) {
  13.     Serial.println("(millis() - 4294967200) > 50");
  14.   }
  15. }

  16. void loop() {
  17.   // put your main code here, to run repeatedly:

  18. }
复制代码


首兩個輸出結果都是 1300 = 1234 + 96 吧, 之後直接用 millis() 的結果, 應該是 96 吧 (當時的 millis() 應該還是 0), 最後測試比較是否大於 50, 當然是成立了.

如果你還是不放心, 可以改一改指定結果以 (unsigned long) 測試就可以了 (其實看了以上的測試, 應該知道是不必要的):
  1. if(state == HIGH && (millis() - changeTime)> 5000){
复制代码
改成
  1. if(state == HIGH && ((unsigned long)(millis() - changeTime)> 5000)){
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-9-11 11:08:33 | 显示全部楼层
Super169 发表于 2014-9-11 09:40
基於 unsigned long 的特性, 本身就沒有問題的.

有懷疑的話, 你可以試試以下程式.

非常感谢,我慢慢研究研究
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-15 08:27 , Processed in 0.050014 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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