2015-09-06 132 views
1

我想測量脈衝持續時間,但我需要測量4個信號,所以我不能使用定時器捕獲中斷,因爲只有1個引腳ICP1提供該選項(或可以)。所以我嘗試實現像arduino pulseIn這樣的區別,我使用定時器(arduino有一些其他實現,但非常相似)。脈衝寬度測量

實際的問題是pulseIn沒有返回任何東西,只是繼續在無限循環中工作。

使用ATmega16。 現在只在PB2上測試。

unsigned long pulseIn() 
{ 
    unsigned long duration = 0; 
    DDRB = 0x00; 

    /* Initiate timer and wait for the end of previous pulse*/ 
    initTime1(); 
    while(getPortBPin(2) == 1); 

    /* Wait for current pulse begin */ 
    while(getPortBPin(2) != 1); 

    /* Time before previous pulse ended */ 
    TCNT1 = 0; 
    overflowCounter = 0; 

    /* Wait for current pulse end */ 
    while(getPortBPin(2) == 1); 

    /* Closk freq is 2 MHz = 1/2 us per tick */ 
    duration = (TCNT1+overflowCounter*65536)/2; 
    overflowCounter = 0; 
    stopTimer1(); 

    return duration; 
} 

void initTime1() 
{ 
    /* Noise filtering */ 
    TCCR1B = (1 << ICNC1); 

    /* Set prescaling factor to 8 */ 
    TCCR1B |= (1 << CS11); 

    /* Enable overflow interruption */ 
    TIMSK = (1 << TOIE1); 

    /* Clear counter */ 
    TCNT1 = 0; 
} 

void stopTimer1() 
{ 
    TCCR1B = 0; 
    TIMSK = 0; 
    TCNT1 = 0; 
} 


uint8_t getPortBPin(uint8_t pin) 
{ 
    if(pin < 0 || pin > 8) 
    { 
     return 0; 
    }  

    return (uint8_t)((PINB >> pin) & 0x01); 
} 

UPDATE

這是我的變形方案。信號來自發生器。頻率爲1kHz,寬度爲50%。電壓是5伏。 Proteus scheme

UPDATE

對不起,那是一個愚蠢的錯誤。它工作正常。調試我沒有按預期的方式工作。

回答

1

我找不到代碼中的問題。但這裏有一些我可以遵循的調試步驟:

1)引腳總是讀什麼?邏輯10,可能脈衝電壓不夠高,AVR無法感測到。

2)duration = (TCNT1+overflowCounter*65536 - timestamp)/2;中的乘法花費了很多CPU時間,可能需要更多時間才能使脈衝在AVR進入最後的while循環之前變低。當然,依賴於脈衝是連續的還是隻有一個脈衝。我也不知道你爲什麼使用timestamp,因爲你已經清除overflowcounter。我認爲這行應該刪除。

UPDATE

要測量四個信號脈衝,我建議使用平變化中斷,中斷的時候發生,你可以屏蔽端口,看看哪些信號已經改變,並計算它的持續時間。

+0

謝謝。你是對的,我應該清除時間befire獲得新的信號。在我的帖子中查看更新。 –

+0

@LongSmith檢查更新 – Nasr

+0

是的,看到它。我只是無法找到任何關於atmega16引腳更改iterruption(是否?)的信息。找到一些mcs寄存器PCMSK和PCINT。但對我來說沒有什麼。認爲它不支持。 –