Forum: Mikrocontroller und Digitale Elektronik ATMega128 CMP Interrupt Problem, PWM


von Dave P. (dave01)


Lesenswert?

Nabend,

meine Absicht ist es ein PWM-Signal mit dem Timer 1 zu erzeugen.
Zur Überprüfung habe ich ein Voltmeter an PB5, sowie GND angeschlossen.
Zu sehen ist ein Abfall der Spannung auf 0V und dann wieder ein Anstieg 
auf ca. 5V, danach bleibt der Pegel aber bei 5V und geht nicht, wie 
erwartet, auf 0V.

Meine Vermutung ist, dass die ISR einmal ausgeführt wird und das wars 
bzw. der Timer nach dem Interrupt nicht mehr hochzählt.


Hier mein Quellcode, vielleicht findet ihr ja meinen Fehler:

ISR:
1
ISR(TIMER1_COMPA_vect)
2
{
3
//Startwert neusetzen
4
   TCNT1 |= 0xBDC;                  
5
}
Timer_io_Init :
1
//Fast-PWM-Mode mit OCR1A TOP (Nr. 15 in Tabelle), sowie Clear on Match - Set on BOTTOM
2
TCCR1A |= (1<<WGM11) | (1<<WGM10) | (1<<COM1A1) | (0<<COM1A0);
3
TCCR1B |= (1<<WGM13) | (1<<WGM12);
4
5
//CMP Interrupt Enable, (Overflow Interrupt Enable)
6
TIMSK |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B);
7
8
//Prescaler auf 256, Startwert: 3036 --> Takt: 16MHz --> Overflow jede Sekunde
9
TCCR1B |= (1<<CS12) | (0<<CS11) | (0<<CS10);
10
TCNT1 |= 0xBDC;
11
12
//Vergleichsregister auf 0xFFFF (65535)  
13
OCR1A |= 0xFFFF;

Main:
1
//PortB auf Ausgang und Pins mit High-Pegel (zur besseren Visualisierung auf Voltmeter)
2
DDRB |= 0xFF;
3
PORTB |= 0xFF;
4
5
//Timer initialisieren
6
Timer_io_Init();
7
8
//Interrupts Global enablen  
9
sei();
10
11
while(1);

von spess53 (Gast)


Lesenswert?

Hi

>//Vergleichsregister auf 0xFFFF (65535)
>OCR1A |= 0xFFFF;

OCR1A ist bei deinem PWM-Mode(15) kein Vergleichsregister, sondern das 
Register, das bestimmt wie weit der Timer zählt, bevor er wieder von 
Null anfängt. OCR1A steht dir damit auch nicht als PWM-Kanal zur 
Verfügung. Das erklärt auch deine Messung.

>//Startwert neusetzen
>   TCNT1 |= 0xBDC;

Lass diesen Blödsinn. Dein AVR kann die PWM ohne dieses unsinnige 
Vorladen erzeugen.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

1
TIMSK |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B);

Du hast hoffentlich auch die zugehörigen ISR zu diesen freigegebenen 
Interrupts?
Ein freigegebener Interrupt ohne ISR wird vom gcc mit dem Reset des µC 
bestraft.

von Dave P. (dave01)


Lesenswert?

Karl Heinz Buchegger schrieb:
>
1
> TIMSK |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B);
2
>
>
> Du hast hoffentlich auch die zugehörigen ISR zu diesen freigegebenen
> Interrupts?
> Ein freigegebener Interrupt ohne ISR wird vom gcc mit dem Reset des µC
> bestraft.

Ne habe ich nicht. Habe nur die compa ISR eingebettet.
Habe es gestern noch hin bekommen. Bin jetzt auf nr . 14 umgestiegen. 
Also fast pwm mit icr1 als top.

Danke für die Informationen :) im nachhinein ist man bekanntlich immer 
schlauer :)

von Oliver S. (oliverso)


Lesenswert?

Dave Pr schrieb:
> TCNT1 |= 0xBDC;

Sowas ist nicht wirklich sinvoll. Wenn du einem Register einen Wert 
zuweisen willst, dann tu das auch:

TCNT1 = 0xBDC;

Ansonsten kommt da alles mögliche raus, nur nicht das, was du willst.

Oliver

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.