2014-11-03 65 views
0

所以我重寫了我的代碼。當我按下連接在引腳2上的按鈕時,它使引腳13爲高電平,並通過收發器將信號發送給接收器(收發器和接收器的類型無關緊要)。我將接收器(引腳13變爲高電平)的導線連接到arduino上的引腳7。我還將LED連接到引腳8以指示何時引腳7爲高電平。計算信號時間

我的主要焦點是計算按下按鈕直到引腳7在Arduino上變爲高電平所花費的時間。我使用的是Arduino Leonardo(也是無關緊要的信息)。

這是我的代碼:

int buttonState; 
int buttonPin = 2; 
int LbuttonState; // last button state 
int pin13 = 13; 
int pin7state; 
int pin7 = 7; 
int Lpin7state; // last pin 7 state 
int pin8 = 8; 
long startTimeKeeper; 
long endTimeKeeper; 
long elapsedTime; 

void setup() { 
    Serial.begin(9600); 
    pinMode(buttonPin, INPUT); 
    pinMode(pin13, OUTPUT); 
    pinMode(pin7, INPUT); 
    pinMode(pin8, OUTPUT); 
} 

void loop() { 
    buttonState = digitalRead(buttonPin); 

    if(buttonState == HIGH && LbuttonState == LOW) { 
    startTime(); // start the time 
    digitalWrite(pin13, HIGH); 
    LbuttonState = buttonState; 
    } else if(buttonState == HIGH && LbuttonState == LOW) { 
    digitalWrite(pin13, LOW); 
    } else if(buttonState == LOW && LbuttonState == HIGH) { 
    digitalWrite(pin13, LOW); 
    LbuttonState = buttonState; 
    } else//(buttonState == LOW && LbuttonState == LOW) 
    digitalWrite(pin13, LOW); 

    pin7state = digitalRead(pin7); 

    if(pin7state == HIGH && Lpin7state == LOW) { 
    stopTime(); // stop the time 
    digitalWrite(pin8, HIGH); 
    Lpin7state = pin7state; 
    } else if(pin7state == HIGH && Lpin7state == HIGH) { 
    digitalWrite(pin8, HIGH); 
    } else if(pin7state == LOW && Lpin7state == HIGH) { 
    digitalWrite(pin8, LOW); 
    Lpin7state = pin7state; 
    } else//(pin7state == LOW && Lpin7state == LOW) 
    digitalWrite(pin8, LOW); 
} 

void startTime() { 
    startTimeKeeper = millis(); 
} 

void stopTime() { 
    endTimeKeeper = millis();`enter code here` 
    elapsedTime = endTimeKeeper - startTimeKeeper; 
    Serial.print(elapsedTime); 
} 

回答

0

我會建議使用interrupts,特別是因爲萊昂納多支持觸發您的兩個選擇引腳的狀態變化中斷。

如果我正確理解問題的核心,您希望從引腳2上的按鈕上的下降沿(高到低)到引腳7上的上升沿(低到高)之間所經過的時間。如果我誤解了這一點,並且你的按鈕實際上是高電平有效的,只需將attachInterrupt(interrupt, ISR, mode)的最後一個參數更改爲RISING即可。

這些設置完成後,我們指定的中斷服務例程(ISR)函數將在指定的狀態或狀態發生變化時被調用。我們希望在這些ISR中做最少的工作,因爲在運行時不會觸發其他ISR。記錄開始或停止時間將會很好。

但是,中斷不能直接使用millis()micros(),因爲這些函數本身使用中斷。爲了解決這個約束,我們將在每個ISR中切換一個簡單的標誌 - 指示它被觸發 - 然後在主循環中輪詢該標誌值,在那裏我們將執行定時器啓動/停止動作。爲了獲得更好的準確性,我在micros()中進行了調整,因爲按鈕按下和接收到的信號之間的時間應該很小(不管怎樣,從來都不是幾分鐘)。

#define ULONG_MAX 0xFFFFFFFFUL 

unsigned long startTimeKeeper, stopTimeKeeper, elapsedTime; 
volatile boolean buttonFlag = false, signalFlag = false; 

void setup() { 
    Serial.begin(9600); 

    pinMode(2, INPUT); 
    pinMode(7, INPUT); 
    pinMode(13, OUTPUT); 
    pinMode(8, OUTPUT); 

    // Int.2 corresponds to pin 2 
    attachInterrupt(2, buttonPressed, FALLING); 
    // Int.4 corresponds to pin 7 
    attachInterrupt(4, signalReceived, RISING); 
} 

void loop() { 
    // Loop until the buttonPressed ISR sets this flag 
    if (buttonFlag) { 
    // Record the start time 
    startTimeKeeper = micros(); 

    // Do nothing until the signal flag is set by the ISR 
    while (!signalFlag); 

    // Record the end time 
    stopTimeKeeper = micros(); 

    // Normal case - stop time is apparently after start time 
    if (stopTimeKeeper > startTimeKeeper) 
     elapsedTime = stopTimeKeeper - startTimeKeeper; 
    // Overflow case - stop time is apparently before start time 
    else 
     elapsedTime = stopTimeKeeper + (ULONG_MAX - startTimeKeeper); 

    Serial.print(elapsedTime); 

    signalFlag = buttonFlag = false; 
    } 
} 

// Very lightweight ISRs 
void buttonPressed() { 
    buttonFlag = true; 
} 

void signalReceived() { 
    signalFlag = true; 
} 

因爲我們馬上開始等待signalReceived() ISR激活signalFlag我們註冊一個按下按鈕後,我們不必擔心在這種情況下,去抖動開關太多。

一般情況下,您需要使用物理電路或軟件計數器來消除您的開關。查看this tutorial以開始使用軟件,或者查看here瞭解有關建築物去抖電路的信息。