2014-08-27 173 views
2

我想知道是否有一種方法可以在沒有實現中斷程序的情況下對Arduino上的數字脈衝進行計數。Arduino - 沒有中斷的計數脈衝

更多描述:我有一個傳感器,可以輸出與我想要計算的一些測量值成比例的數字脈衝。

+0

是的,您可以通過輪詢來完成此操作,但是這會使處理器處於繁忙狀態,並且您應該知道,可能會丟失比輪詢間隔更少的時間的任何狀態。 – 2014-08-27 19:50:28

+0

在沒有ISR的情況下對脈衝進行計數的方法是使用硬件計數器,通過週期性地處理它們的狀態並設置它們的計數限制來避免溢出。 – manatttta 2014-09-10 12:14:01

回答

3

您不僅可以在沒有中斷處理程序的情況下執行此操作,還可以在很少或沒有軟件的情況下執行此操作,並可以通過軟件輪詢或中斷計數處理更快的脈衝速率。

大多數Arduinos都基於的Atmel AVR具有計數/計時器硬件,可直接對輸入引腳進行脈衝計數。您只需配置硬件以進行計數器操作並讀取計數器寄存器。 8位器件上的16位計數器的複雜性很小,但這很容易克服。 Arduino爲默認PWM操作配置定時器,但可以按照描述here(詳情請參閱AVR用戶手冊)覆蓋 - 您需要在CTC模式下使用定時器/計數器。

基於ARM的Arduninos和幾乎任何其他微控制器都將具有類似的硬件設施;有些引腳可以用於硬件計數,具有更大的靈活性。

在AVR上有8位和16位計數器,如果你需要更大的計數,你可能需要處理溢出中斷。如果您要定期輪詢計數器,您甚至可以在沒有中斷的情況下處理該事件,同時能夠以比輸入脈衝的速率低得多且可能非週期的速率進行輪詢,只需在下次溢出之前輪詢溢出標誌即可。

對於您的情況,您可能需要在一個常規週期內讀取脈衝計數,該週期比計數器以最大預期脈衝速率溢出的時間短。例如,如果您使用的是8位計數器並且最大脈衝頻率爲1KHz,則您需要輪詢每256/1000秒或更短,但通過儘可能延長週期來提供最大的精度。因此,例如,你可能會有諸如以下的(這不是真正的代碼,並且只有一個片段):

for(;;) 
{ 
    delayMS(250) ; 
    frequency = 4 * readCounter() ; 
} 

,將得到更好的線性響應,但不確定性讀出另一種方法是輪詢溢出標誌,然後測量計數固定脈衝數所用的時間,因此從固定計數的時間而不是固定時間的計數確定測量。

for(;;) 
{ 
    int start = getMillisec() ; 

    while(!counterOVF()) 
    { 
     // Do nothing (or something useful but quick) 
    } 

    int t = getMillisec() - start ; 
    frequency = 256 * t/1000 ; 
} 
+0

非常感謝您的提問。如果我理解正確,你的第一個想法就是由硬件指示脈衝,而第二個想法是讓處理器一直處於忙碌狀態。問題是我的微控制器是完全加載的(這就是爲什麼一個簡單的ISR遞增計數變量將不起作用),並且不能輪詢,因爲它需要執行其他任務。此外,我沒有更多的硬件計數器可用。還有其他的選擇嗎?我聽說可以使用模擬端口(依靠與PWM的相似性)。非常感謝 – manatttta 2014-08-28 08:16:36

+0

在這兩種情況下,硬件計數器都在計數,在第二種情況下,我的例子是輪詢溢出標誌,但這只是爲了說明原理,它不是根本的解決方案;它可能同樣是一箇中斷處理程序 - 其優點是每256個脈衝(假設是8位計數器)而不是每個脈衝都有一箇中斷,所以中斷開銷要低得多。 – Clifford 2014-08-28 11:10:07

+0

只有當傳感器輸出是一個固定頻率的PWM(並且您添加了合適的模擬濾波器,截止頻率稍低於該頻率)時,您纔可以使用模擬輸入,但是您的問題意味着它是一個可變頻率而不是PWM(否則如何會計數脈衝有幫助嗎?)。 – Clifford 2014-08-28 11:12:52

1

你可以使用模擬器,在它前面有一點數字。 如果您的輸入最大頻率爲1kHz,使用此信號觸發脈衝輸出爲1ms(1/fmax)的單穩態(邊沿觸發)。然後低通濾波器(R串聯,C接地並重復多極),最後讀取最後一個電容上的模擬電壓。如果R * C相對較小,則模擬信號將快速反應,但會產生波紋。如果它很大,反應時間會受影響,但信號會更穩定。