wie aktiviere 16bit timer auf dem AVR-Programmierung
Habe ich einen atmega168a-chip. Ich benutze Counter 0
Umschalten PORTC
mithilfe ISR(TIMER0_COMPA_vect)
und ISR(TIMERB_COMPA_vect)
interrupt-sub-Routine. Ich möchte zum aktivieren der 16-bit timer
wenn if
Bedingung wahr ist. Also, ich benutze TIMSK1 = (1<<OCIE1A)
, aber diese Zeile ruft ISR(TIMER1_COMPA_vect)
unterbrechen sofort, wo ich möchte 16-bit-timer werden nur unterbrochen, wenn der Zähler reaches
zu OCR1A
Wert. Wie kann ich aktivieren Sie die 16-bit-timer, der Laufzeit, ohne dass eine sofortige unterbrechen?
hier ist mein code:
#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)
}
hier ist ein Oszilloskop-Ausgang, die zeigt, warum ich nicht wollen, dass der interrupt festgelegt werden sofort, weil es das signal 0 sofort.
InformationsquelleAutor johan | 2013-03-09
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich denke, das problem könnte sein, dass im CTC-Modus, interrupt wird generiert, wenn
OCF1A
- flag gesetzt ist (inTIFR
). Da dein timer läuft immer, nur nicht die Erzeugung unterbricht, setzt esOCF1A
Flagge, die wird nie gelöscht. Auf Seite 142 im Datenblatt heißt es:Dies bedeutet, dass wenn Sie eingerichtet timer 1, Sie müssen auch klar
OCF1A
:Allerdings denke ich, dass Sie es besser machen können. Sie konnte nur halten Sie die Stoppuhr an, wenn Sie nicht benötigt, und starten Sie es, wenn Sie, statt von Anpassungen die
TIMSK
und timer 1 laufen immer. Wenn SieTCCR1B
auf null, löschtCS12
,CS11
, undCS10
, die, laut Datenblatt bedeutet "Timer gestoppt." Dann, wenn Ihre Zähler erreicht 4 können Sie auf timer1, wie Sie es oben:Wenn Sie dies tun, sollten Sie nicht brauchen, um den timer-1-interrupts an und ausschalten: legen Sie Sie einfach auf, und nur die zählen auf, wenn Sie es brauchen.
Außerdem Frage ich mich, ob es tatsächlich notwendig ist, das Feuer aus zwei interrupts zum Umschalten der pins auf
PORTC
? Bist du nicht mit PWM, weil es nicht geben Ihnen die Pulslängen genau genug?Ausgezeichnet. Froh, dass es jetzt funktioniert.
InformationsquelleAutor angelatlarge