PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit Timerinterrupt



U001
30.10.2016, 00:19
Liebe Forengemeinde,

nachdem ich mehrere Abende vergeblich versucht habe, den Fehler in meinem Programm zu finden, bitte ich ergebenst um Hilfe:
(ich bin Anfänger beim Mikroprozessor-Programmieren)

Ich verwende einen Arduino mit Atmega328P und das AtmelStudio 7 zum Programmieren.

Mit dem Timer1 möchte ich ein PWM-Signal erzeugen mit 500ms Taktzeit. Am PortB Pin1 soll 25% rauskommen und am PortB Pin2 75% Tastverhältnis. Um das Arbeiten des OCIE1A-Interrupts zu testen, will ich zusätzlich am PortB Pin4 eine LED im gleichen Takt wie am PortB Pin2 blinken lassen.

Das Programm sieht so aus:

# define F_CPU 16000000UL //CPU-Frequenz
#define PRESCALER 256
#define MS500 F_CPU/PRESCALER/1000 * 500

void INITialisierung(void)
{
//Wir verwenden den Timer1, der auf die Pins 9 und 10 des Arduino geht
DDRB |= (1<<DDB1) |(1<<DDB2)|(1 << DDB4);
// PB1, PB2 and PB4 are now output
// Entspricht PIN9, 10 und 12 am Arduino
ICR1 = MS500;
// set MAX auf 500ms
OCR1A = MS500/5;
// set PWM for 20% duty cycle @ 16bit
OCR1B = MS500/4*3;
// set PWM for 75% duty cycle @ 16bit

// Setzen Modus 14... Fast PWM mit Timerruecksetzen bei OCR1A-Vergleich und ICR1 als MAXwert)
TCCR1A |= (1<<WGM11)|(1 << COM1A1)|(1 << COM1B1);
TCCR1B |= (1<<WGM12)|(1<<WGM13);

TIMSK1 |= (1<<OCIE1A); //enable Interrupt bei OCR1A-Vergleich

TCCR1B |= (1<<CS12);
// START the timer with prescaler 256
// Ein Timertick ist dann 16 µs

sei();

}

ISR(TIMER1_COMPA_vect)
{
PORTB ^= (1 << PB4); //Pin12 Togglen
}

int main(void)
{
INITialisierung();
while (1){}
}

Das Programm funktioniert insoweit, als am Pin 1 und 2 des PortB die richtigen Signale ankommen.
Am Pin4 des PortB entsteht jedoch ein PWM-Signal mit 500ms High und 500ms Low. D.h. die ISR wird nicht beim Compare-Match aufgerufen, sondern beim Rücksetzen des Timers beim Erreichen des ICR1-Registerwertes.

Hat jemand eine Erklärung für dieses Verhalten?

Das Programm hier ist nur ein Testprogramm, später möchte ich in der ISR das Register OCR1A beschreiben und so die Pulsweite des PWM-Signals aktualisieren.

Danke schon mal...

Gruß Alfred

Peter(TOO)
30.10.2016, 01:28
Hallo Alfred,

Das Programm funktioniert insoweit, als am Pin 1 und 2 des PortB die richtigen Signale ankommen.
Am Pin4 des PortB entsteht jedoch ein PWM-Signal mit 500ms High und 500ms Low. D.h. die ISR wird nicht beim Compare-Match aufgerufen, sondern beim Rücksetzen des Timers beim Erreichen des ICR1-Registerwertes.

Hat jemand eine Erklärung für dieses Verhalten?
Ja, du machst einen Denkfehler.
Die ISR wird aufgerufen und toggelt dann Pin 12. Also beim ersten Aufrufen geht der Pin von 0 auf 1.
500ms später ist dann der nächste ISR Aufruf und Pin 12 geht von 1 auf 0.

Pin 1 und 2 werden beim Compare-Match verändert UND wenn der Timer zurückgesetzt wird.

MfG Peter(TOO)

U001
30.10.2016, 11:01
Oh Mann,

da hatte ich echt ein Brett vor'm Hirn.

Ganz herzlichen Dank!

Gruß Alfred

Peter(TOO)
30.10.2016, 12:30
Hallo Alfred,

da hatte ich echt ein Brett vor'm Hirn.
Der nächste Winter kommt bestimmt, da kann ein Brett mollig warm geben :-)

MfG Peter(TOO)