簡體   English   中英

TIMER1 用於測量 avr atmega328p 中的延遲精度?

[英]TIMER1 to measure the delay accurracy in avr atmega328p?

unsigned long slptime=0;
unsigned long wdttime_count = 0;


void timer1_init()
{
    //TCNT1=0xFF4E;//16ms
    TCNT1=0xFFF5;//1ms
    // TCNT1=0xFF9B; //10ms
    TIMSK1=0x01;
    TCCR1A &= ~(1<<WGM10); // RV09_H, Date: 05-May-2022, set Normal mode operation
    TCCR1A &= ~(1<<WGM11);
    TCCR1B &= ~(1<<WGM13);
    TCCR1B &= ~(1<<WGM12);
    TCCR1B |= (1<<CS12) | (1<<CS10); //1024 prescalar; fosc=11059200hz; freq=fosc/1024 = 10800hz; t=0.092ms;
}

void timer1_stop()
{
    TCCR1B = 0x00;
    TIMSK1 = 0x00;
}
ISR(TIMER1_OVF_vect)
{
    //TCNT1=0xFF4E;//16ms
    TCNT1=0xFFF5;
    //TCNT1=0xFF9B;
    wdttime_count=wdttime_count+1;
}

void main()
{
    timer1_init();
    _delay_ms(250);
    timer1_stop();
    sendtimediff((wdttime_count*1000)/1080);
}

timer1 通過在 10800hz 下計數到 10 來配置為 1080Hz。 我只是在檢查計時器的准確性,但上面的代碼返回 227 毫秒而不是 250 毫秒。

我缺少什么? 或者 _delay_ms() 導致錯誤?

  1. 當您將計時器值設置為0xFFF5時,它會在溢出前遞增 11 次。

11059200 / 1024 / 11 = 981,8 赫茲 == 1,0185 毫秒。

它計數了 245 次。

245 * 1000 / 1080 = 227

您可能希望將值設置為0xFFF6

  1. 無需在每次中斷時都設置定時器。 相反,您可以使用 CTC 模式,強制計時器從零計數到OCR1A (模式 4)ICR1 (模式 12)中的值。 例如:
void timer1_init()
{
    TCNT1=0;
    OCR1A = 9; // from 0 to 9 == 10 timer (prescaled) clock cycles

    TIMSK1 = (1 << OCIE1A); // Use Output Compare interrupt
    TCCR1A &= ~(1<<WGM10); // Set Mode 4 (CTC)
    TCCR1A &= ~(1<<WGM11);
    TCCR1B &= ~(1<<WGM13);
    TCCR1B |= (1<<WGM12);
    TCCR1B |= (1<<CS12) | (1<<CS10); //1024 prescalar; fosc=11059200hz; freq=fosc/1024 = 10800hz; t=0.092ms;
}

ISR(TIMER1_COMPA_vect) // use Output Compare A vector, instead of Overflow
{
    // No need to reset the timer
    wdttime_count=wdttime_count+1;
}

...
  1. 請記住_delay_ms宏只計算 CPU 周期,因此如果在延遲期間發生中斷,延遲可能需要更長的時間。 _delay_ms_delay_us宏正在生成普通的 CPU 循環,它可以精確地計算到單個 CPU 時鍾周期,但前提是循環本身沒有被中斷。

  2. 沒有必要將_delay_ms與從與 CPU 本身相同的主時鍾計時的定時器進行比較。 無論實際 CPU 速度如何,比較結果總是相同的。

自由運行定時器的經典錯誤, TCNT1=interval; 在 ISR 中是行不通的。 它需要是這樣的:

volatile uint16_t next_TCNT1 = TCNT1;
next_TCNT1 += interval;
TCNT1 = next_TCNT1;

這樣做的原因是:您已將中斷設置為在定時器比較達到某個值時觸發。 那是設置定時器標志的時間點,但是從發生這種情況到到達 ISR 中的實際代碼,已經過去了很多時間,中斷延遲 這在各種舊的、垃圾的架構 8 位上尤其令人討厭。

因此,當您更新定時器計數器時,它不會處於“間隔”,而是處於“間隔加上中斷延遲加上執行開銷”,這意味着下一個中斷將比預期來得早得多。

通過讀取 ISR 中的當前值並向其添加定時器間隔,您可以補償中斷延遲。 現在您唯一的實時延遲是 ISR 中的那幾行,它們可能可以忽略不計。

暫無
暫無

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

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