jasonqiu 发表于 2014-9-10 23:16:09

求教关于millis() 的问题?

我是初学,请指教!!{: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(); //记录自上一次灯变化的时间
      //返回到主函数循环中
}


Super169 发表于 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, 所以是沒必要的.

unsigned long start_ms = 4294967200;
unsigned long end_ms = 1234;
unsigned long elapsed_ms;
void setup() {
// put your setup code here, to run once:
Serial.begin(57600);
Serial.println(end_ms - start_ms);
elapsed_ms = (unsigned long)(end_ms - start_ms);
Serial.println(elapsed_ms);
Serial.println(millis() - start_ms);
Serial.println((unsigned long)(millis() - start_ms));
if ((millis() - start_ms) > 50) {
    Serial.println("(millis() - 4294967200) > 50");
}
}

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

}

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

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

jasonqiu 发表于 2014-9-11 11:08:33

Super169 发表于 2014-9-11 09:40 static/image/common/back.gif
基於 unsigned long 的特性, 本身就沒有問題的.

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


非常感谢,我慢慢研究研究
页: [1]
查看完整版本: 求教关于millis() 的问题?