[英]how to activate 16bit timer on AVR programming
我有一個atmega168a芯片。 我使用Counter 0
通過使用ISR(TIMER0_COMPA_vect)
和ISR(TIMERB_COMPA_vect)
中斷子程序來切換PORTC
。 if
條件為真,我想激活16-bit timer
。 因此,我使用TIMSK1 = (1<<OCIE1A)
,但此行立即調用ISR(TIMER1_COMPA_vect)
中斷,我希望只有當計數器reaches
OCR1A
值時才會中斷16位定時器。 如何在運行時激活16位定時器而不會導致瞬間中斷?
這是我的代碼:
#define F_CPU 8000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
volatile uint8_t counter;
int main (void){
DDRC = 0xFF; //sets PORTC as output
PORTC = 0xFF; //initial output value
/*COUNTER0 settings*/
TIMSK0 = ((1<<OCIE0A) | (1<<OCIE0B)); // Enable Interrupt TimerCounter0 Compare Match A & B
TCCR0A = (1<<WGM01); // Mode = CTC
TCCR0B = (1<<CS01) | (1<<CS00); // Clock/64, 1/(8000000/64)= 0.000008 seconds per tick
OCR0A = 200; // 0.000008 *230 = 1.6 ms
OCR0B = 100; // 0.8 ms
/*16bit timer - counter1 settings*/
TIMSK1 &= ~(1<<OCIE1A); // Disable Interrupt Counter 1, output compare A (TIMER1_CMPA_vect)
TCCR1B = ((1<<CS12) | (1<<CS10) | (1<<WGM12)); // Clock/1024, 1/(8000000/1024) = 0.000128 seconds per tick, Mode=CTC
OCR1A = 40; // 0.000128*40 ~= 5.12 milliseconds
sei(); //interrupts are globally switched on
counter =0;
while(1){
if(counter >= 4){
TCNT1 = 0; // clear the counter 1
TIMSK1 = (1<<OCIE1A);// Enables the interrupt for Counter 1,(TIMER1_CMPA_vect)
TIMSK0 &= ~((1<<OCIE0A) | (1<<OCIE0B)); //disables the Counter 0's interrupts
counter = 0;
}
}
return 0;
}
ISR(TIMER0_COMPA_vect){ //1.6ms
PORTC = 0xFF;
counter++;
}
ISR(TIMER0_COMPB_vect){ //0.8 ms
PORTC = ~PORTC;
}
ISR(TIMER1_COMPA_vect){ // 5.2 milisecond interrupt
PORTC = 0x00;
TCNT0 = 0; //clear the counter of counter0
// TIMSK0 = ((1<<OCIE0A) | (1<<OCIE0B)); //Enable the Counter 0 interrupts
// TIMSK1 &= ~(1<<OCIE1A);// Disable Interrupt Counter 1, output compare A (TIMER1_CMPA_vect)
}
這是一個示波器輸出,顯示為什么我不希望立即設置中斷,因為它立即設置信號0。
我認為問題可能是在CTC模式下,當設置OCF1A
標志時(在TIFR
)會產生中斷。 由於您的定時器始終在運行,只是沒有產生中斷,因此它會設置OCF1A
標志,該標志永遠不會被清除。 在數據表的第142頁上,它說:
執行輸出比較匹配B中斷向量時,OCF1B自動清零。 或者,可以通過將邏輯1寫入其位位置來清除OCF1B。
這意味着當您設置計時器1時,您還需要清除OCF1A
:
TIFR1 &= ~(1<<OCF1A)
但是,我認為你可以做得更好。 您可以在不需要時停止計時器,並在執行時啟動計時器,而不是整理TIMSK
並始終運行計時器1。 如果將TCCR1B
設置為零,則清除CS12
, CS11
和CS10
,根據數據表顯示“定時器已停止”。 然后,當你的計數器達到4時,你可以打開上面的計時器1:
TCCR1B = ((1<<CS12) | (1<<CS10) | (1<<WGM12));
如果這樣做,你不需要打開和關閉定時器1中斷:只需打開它們,只在你需要時打開計數器。
另外,我想知道是否真的有必要在PORTC
上觸發兩個中斷來切換引腳? 你沒有使用PWM,因為它沒有給你足夠的脈沖長度嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.