![](/img/trans.png)
[英]Creating a 10 second delay using ISR in TIMER1 of 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() 導致錯誤?
0xFFF5
時,它會在溢出前遞增 11 次。11059200 / 1024 / 11 = 981,8 赫茲 == 1,0185 毫秒。
它計數了 245 次。
245 * 1000 / 1080 = 227
您可能希望將值設置為0xFFF6
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;
}
...
請記住_delay_ms
宏只計算 CPU 周期,因此如果在延遲期間發生中斷,延遲可能需要更長的時間。 _delay_ms
和_delay_us
宏正在生成普通的 CPU 循環,它可以精確地計算到單個 CPU 時鍾周期,但前提是循環本身沒有被中斷。
沒有必要將_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.