簡體   English   中英

AVR CTC模式下的16位計時器

[英]16-bit timer in AVR CTC mode

我正在嘗試使用Arduino Uno開發板( ATmega328,16 MHz)實現這一目標。 因此,我在Internet上進行搜索,然后想到了以下內容:

unsigned long Time=0;

int main (void)
{
  Serial.begin(9600);

  cli();

  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;

  OCR1A = 15999; // Compare value

  TCCR1B |= (1 << WGM12)| (1 << CS10); // Prescaler
  TIMSK1 |= (1 << OCIE1A); // Enable timer compare interrupt

  sei();

  while(1) {

    Serial.println(TCNT1);
  }

  return 0;
}


ISR(TIMER1_COMPA_vect)
{
  Time++;
  Serial.println(Time);
}

我正在嘗試達到1 kHz的頻率,因此我將能夠創建幾毫秒長的間隔。

這就是為什么我將比較值選擇為15999(即16000-1),並將預分頻器選擇為1的原因,所以我得到了(至少我認為是正確的計算結果):

Frequency = 16.000.000 MHz/16000 = 1000 Hz = 1 kHz

現在的問題是,即使Serial.println(TCNT1)向我顯示的數字最多計數為16000,回零,最多16000,返回零,..., Serial.println(Time)最多計數為8 ,盡管TCNT1仍在計數,但它只是停止計數。

我想到某處有某種溢出,但我想不到哪里。 我唯一想到的是比較值可能太大了-正如我認為-顯然不是這樣,因為2^16 -1=65.535>15999

例如,如果我將預分頻器設為64,並保留比較值,則Time按預期計數。 所以我想知道:為什么ISR()停止以值8調用,而在調高預分頻器時起作用?

我不確定,但是根據您使用的Arduino版本,println調用將被阻塞。 如果調用它的速度超出了在ISR中完成的速度,則堆棧將溢出。

如果您想要更高分辨率的計時,則可以嘗試在Loop()對getMicroseconds結果進行差分。 您在Loop()Loop()速度應遠遠超過每毫秒一次。

如果要每毫秒執行一次操作,請捕獲一個開始的微秒,然后在Loop()函數的條件中從當前的微秒中減去它。 當您看到1000多個任務時...

對於我的Arduino Uno(16 MHz)而言,計時器的分辨率似乎過高。 選擇較低的分辨率(即較高的比較值)可以解決我的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM