Forum: Mikrocontroller und Digitale Elektronik ATMega3250 Timer1 Overflow nicht bei 0


von Sepp (Gast)


Lesenswert?

Hallo zusammen,

hab hier ein Problem mit dem Timer1 dessen Verhalten ich mir einfach 
nicht erklären kann. Vielleicht weiß ja jemand von euch an was es liegt.

Umgebung:
- AVR Studio 6.2
- ATMEGA3250P
- Debugging/Programmieren mit Atmel ICE

Nachdem das ganze in einem größeren Programm für Schwierigkeiten gesorgt 
hat, hab ich alles aufs Minimum reduziert um möglichst viel 
auszuschließen:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#define PWM_ON_TIME 50 
5
#define PWM PINB5
6
7
ISR(TIMER1_OVF_vect) {
8
  PORTE &= ~(1 << PE0);
9
}
10
11
int main(void)
12
{
13
  DDRE |= (1<<PE0);
14
  DDRB |= (1<<PWM);
15
  TCCR1A =  (1<<WGM10) | (1<<WGM11) | (1<<COM1A1);
16
  TCCR1B =   (1<<CS11) | (1<<CS10);
17
  TCCR1C = 0;
18
  // Set the output compare register to defined on time
19
  OCR1AH = 0;
20
  OCR1AL = PWM_ON_TIME;
21
  TIMSK1 = (1<<TOIE1);
22
  
23
  sei();
24
  
25
    while(1)
26
    {
27
  PORTE |= (1<<PE0);  
28
    }
29
}

Ziel ist es, Timer1 im 10-bit "Phase Correct PWM Mode" zu betreiben und 
beim Überlauf des Timers bei 0 etwas zu tun. Beim Debuggen im Simulator 
ist alles wie erwartet, bei einem Breakpoint in der ISR ist das 
Zählregister TCNT1 auf 1 oder max. 3, also kurz nachdem der Zähler auf 0 
war.
Sobald ich das aber auf der HW laufen lasse, ist TCNT1 in der ISR 
scheinbar auf einen Zufallswert irgendwo zwischen 0 und TOP.
Was das alles noch interessanter macht: das TOV1 Flag ist auf 1, also 
nicht gelöscht wie es m.M.n. in der ISR sein sollte.
Das globale I Flag hingegen funktioniert wie erwartet, in der ISR 0, in 
main 1.
Hab das ganze auch ohne Debugger laufen lassen und darauf hin getestet 
mit keiner Besserung.

Nun meine Fragen:
Habe ich hier etwas Grundsätzliches im Zusammenhang mit 
Timerkonfiguration oder Interrupts übersehen?
Kann man im AVR Studio irgendwelche Debugeinstellunen die Timer 
betreffend vornehmen?

Vielen Dank vorab und liebe Grüße,

Sepp

von lander (Gast)


Lesenswert?

Scheint mir alles richtig eingestellt zu sein, aber wozu dient hier das 
Setzten von PE0, das ja auch in der ISR verändert wird.

Sepp schrieb:
>
1
>     while(1)
2
>     {
3
>   PORTE |= (1<<PE0);
4
>     }
5
>

von Sepp (Gast)


Lesenswert?

Um wenigstens eine Anweisung in main und der ISR zu haben, bei der HW 
ist an diesem Pin eine LED angeschlossen. Sollte eigentlich 
nebensächlich sein.

von Dieter F. (Gast)


Lesenswert?

Hallo,

Du hast WGM13 nicht gesetzt - brauchst Du, wenn Du mit OCR1A vergleichen 
willst -> Mode 11 (Datenblatt S. 130 :-) ).

Ach ja - und bedenke, dass jede Interrupt-Routine einen Prolog und 
Epilog hat, in welcher Register gesichert werden etc. Außerdem braucht 
der Sprung zur Routine auch Taktzyklen. Du wirst also in der ISR nicht 
so einfach bei Timerstand = 0 irgendwelchen Code ausführen können.

Ggf. müsstest Du Dich über einen Compare-Interrupt mit entsprechendem 
Vorlauf vor dem Overflow-Interrupt heranhangeln - ggf. sogar über eine 
eigengestrickte ISR, damit der Compiler da nicht zwischnfunkt und 
optimiert. Da bin ich aber auf sehr dünnem Eis ...

Gruß
Dieter

von Sepp (Gast)


Lesenswert?

Hallo Dieter,

Danke für die Tipps, leider weiß ich trotzdem nicht worans liegt...
WGM13 muss ich m.M.n. nicht setzen, da ich den Mode 7 (DB 
2570N–AVR–05/11 s. 125 Table 17-5) für den für mich passenden halte. Mit 
OCR1A wird da trotzdem verglichen und OC1A entsprechend gesetzt, das 
funktioniert auch wie gewünscht, hab ich mit dem Oszi überprüft.

Weiters will ich ja nicht bei Timerstand 0 in der ISR beginnen, 
irgendwas unter 5 (1MHz Takt, Prescaler 64 => < 320 Takte) reicht mir 
vollkommen. In 320 Takten sollte die CPU doch in die ISR finden...

Zudem erklärt so eine Zeitverzögerung auch nicht warum das TOV1 Flag 
nicht richtig gesetzt ist.

von Sepp (Gast)


Lesenswert?

Sorry, ich meinte natürlich Mode 3 "PWM, Phase Correct, 10-bit"

von Dieter F. (Gast)


Lesenswert?

Sepp schrieb:
> Ziel ist es, Timer1 im 10-bit "Phase Correct PWM Mode" zu betreiben und
> beim Überlauf des Timers bei 0 etwas zu tun.

Sepp schrieb:
> WGM13 muss ich m.M.n. nicht setzen, da ich den Mode 7 (DB
> 2570N–AVR–05/11 s. 125 Table 17-5) für den für mich passenden halte.

Sepp schrieb:
> Sorry, ich meinte natürlich Mode 3 "PWM, Phase Correct, 10-bit"

Hallo Sepp,

ja - was denn nun?


Du setzt OCR1A als Top-Wert - das zielt auf Phase Correct PWM mit OCR1A 
als Top-Wert (Mode 11). Fast PWM mit 0x3FFF als Top-Wert (Mode 7) ist 
deutlich anders. Aktuell hast Du Mode 3 eingestellt - da bringt die 
OCR1A-Einstellung rein gar nichts.

Im 2. Fall müsstest Du auch WGM12 setzen, was Du nicht gemacht hast.



Hast Du Dir die Tabelle 17-5 mal genau angeschaut? Ich schätze, da musst 
Du doch die Brille aufsetzen :-)

Sepp schrieb:
> Zudem erklärt so eine Zeitverzögerung auch nicht warum das TOV1 Flag
> nicht richtig gesetzt ist.

Sepp schrieb:
> Was das alles noch interessanter macht: das TOV1 Flag ist auf 1, also
> nicht gelöscht wie es m.M.n. in der ISR sein sollte.

In der letzten Spalte ist definiert, wann das TOV1-Flag gesetzt wird - 
nämlich im Mode 3 auf BOTTOM.



Willst Du PWM überhaupt nutzen? Oder willst lediglich in definierten 
Zeitabständen irgendwelchen Code ausführen?

Gruß
Dieter

von Sepp (Gast)


Lesenswert?

Ok, gebe zu dass meine Erklärungen wohl etwas verwirrend waren. Deshalb 
nun ein neuer Versuch:

Ich möchte gern mit Timer1 ein PWM Signal auf dem OC1A pin erzeugen, an 
dem eine Lichtschranke angeschlossen ist. In der Mitte des periodisch 
auftretenden Highpulses soll der Zustand des Phototransistors der 
Schranke eingelesen werden. Das ganze ist mir mit dem gleichen Code 
bereits auf einem Steckbrett und einem ATMega32 gelungen. Mit dem 
ATMega3250 plötzlich nicht mehr.

Nun zu meinen Überlegungen im Detail:
Der "Phase Correct PWM Mode" erschien mir passend:

DB Kap. 17.9.4:
"The counter counts repeatedly from BOTTOM (0x0000) to TOP and then from
TOP to BOTTOM. In non-inverting Compare Output mode, the Output Compare 
(OC1x) is cleared on the compare match between TCNT1 and OCR1x while 
counting up, and set on the compare match while counting down."

Tabelle 17.4: "Compare Output Mode, Phase Correct and Phase and 
Frequency Correct PWM"

COM1A1 = 1, COM1A0 = 0

"Clear OC1A/OC1B on Compare Match when upcounting. Set OC1A/OC1B on 
Compare Match when counting down."

Setz ich also OCR1A auf z.B. 50 entsteht also rund um den 0-Zählerstand 
ein Highpuls.

Weiters steht da geschrieben:

"The Timer/Counter Overflow Flag (TOV1) is set each time the counter 
reaches BOTTOM."

Wenn ich jetzt auf dieses Flag mit einem Interrupt reagiere, kann ich 
kurz nach Zählerstand 0 den Input einlesen.

Tabelle 17-5.

WGM13 = 0, WGM12 = 0, WGM11 = 1, WGM10 = 1
 => Mode 3 PWM, Phase Correct, 10-bit, TOP = 0x03FF
TOV1 Flag Set on BOTTOM.

So, und genau das passiert nicht, TOV1 wird scheinbar IRGENDWANN 
gesetzt.
Warum nur?

LG

Sepp

von Dieter F. (Gast)


Lesenswert?

Sepp schrieb:
> Ich möchte gern mit Timer1 ein PWM Signal auf dem OC1A pin erzeugen, an
> dem eine Lichtschranke angeschlossen ist. In der Mitte des periodisch
> auftretenden Highpulses soll der Zustand des Phototransistors der
> Schranke eingelesen werden.

O.K. - in welchem zeitlichen Abstand?

Sepp schrieb:
> In non-inverting Compare Output mode, the Output Compare
> (OC1x) is cleared on the compare match between TCNT1 and OCR1x while
> counting up, and set on the compare match while counting down."

Das Wörtchen "compare" hast Du wahrgenommen?

Wie Zeitkritisch ist das Ganze denn? Willst Du Energie sparen, weil Du 
die Lichtschranke nur "ab und an" einschaltest?

Also mit aktuellem Kenntnisstand würde ich mit Mode 11 arbeiten parallel 
den Compare Interrupt (mit entsprechender Einstellung) aktivieren. Also 
per Hardware die Lichtschranke ein/ ausschalten lassen und per 
"compare-Interrupt" die Lichtschranke auswerten.

Das "warum" erschließt sich mir leider immer noch nicht - es gibt 
"normale" Lichtschranken in allen möglichen Formaten ...

Gruß
Dieter

von lander (Gast)


Lesenswert?

Dieter Frohnapfel schrieb:
> Das "warum" erschließt sich mir leider immer noch nicht - es gibt
> "normale" Lichtschranken in allen möglichen Formaten ...

Warum wird der Overflow Interrupt von Timer1 scheinbar bei verschiedenen 
TCNT1 Ständen ausgeführt und nicht immer bei Stand 0.  Es ist die Frage 
und wenn sie sich dir nicht erschließt ...

@Sepp
Wie stellst du das fest? Wie mißt du das? Wie läßt du dir den 
Zählerstand ausgeben? Vielleicht Meßfehler?

von Dieter F. (Gast)


Angehängte Dateien:

Lesenswert?

Dieter Frohnapfel schrieb:
> In der letzten Spalte ist definiert, wann das TOV1-Flag gesetzt wird -
> nämlich im Mode 3 auf BOTTOM

Das muss ich zurücknehmen ... ist zwar lt. Tabelle so, aber die Realität 
sieht anders aus ... .

Ich habe das Ganze mal auf einen ATMega32 portiert und (mit 16 MHz Takt) 
laufen lassen.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#define PWM_ON_TIME 50
5
#define PWM PIND5
6
7
ISR(TIMER1_OVF_vect) {
8
  PORTA &= ~(1 << PA0);
9
}
10
11
int main(void)
12
{
13
  DDRA |= (1<<PA0);
14
  DDRD |= (1<<PWM);
15
  TCCR1A =  (1<<WGM10) | (1<<WGM11) | (1<<COM1A1);
16
  TCCR1B =   (1<<CS11) | (1<<CS10);
17
//  TCCR1C = 0;
18
  // Set the output compare register to defined on time
19
  OCR1AH = 0;
20
  OCR1AL = PWM_ON_TIME;
21
  TIMSK  = (1<<TOIE1);
22
  
23
  sei();
24
  
25
  while(1)
26
  {
27
    PORTA |= (1<<PA0);
28
  }
29
}

Sieht alles einwandfrei und regelmässig aus - Hardcopys der 
Oszilloskop-Ansichten habe ich beigefügt. Gelb = PWM-Pin und Blau = 
ISR-Pin. Daher vermute ich auch, Du misst Mist :-)

Gruß
Dieter

von Paul B. (paul_baumann)


Lesenswert?

Dieter Frohnapfel schrieb:
>> In der letzten Spalte ist definiert, wann das TOV1-Flag gesetzt wird -
>> nämlich im Mode 3 auf BOTTOM
>
> Das muss ich zurücknehmen ... ist zwar lt. Tabelle so, aber die Realität
> sieht anders aus ... .

Das zu: "Lies das Datenblatt" -Ratschlägen.

MfG Paul

von Dieter F. (Gast)


Lesenswert?

Paul Baumann schrieb:
> Das zu: "Lies das Datenblatt" -Ratschlägen.

Hallo Paul,

durch Deine Antwort konnte ich nicht mehr korrigieren ... :-(

Das Datenblatt ist korrekt - meine Interpretation nicht ...

"In non-inverting Compare Output mode, the Output Compare (OC1x)
is cleared on the compare match between TCNT1 and OCR1x while 
upcounting, and set on the compare match while downcounting."

Das heisst, nach 50 Zählern wir der Pin auf GND gesetzt (und es wird bis 
TOP = 0x03FF weitergezählt) und beim herunterzählen wird der Pin ab 
Zählerstand 50 auf high gesetzt. Genau auf Bottom (Zählerstand = 0) wird 
der Interrupt ausgelöst. Das ist in der Oszilloskop-Ansicht auch gut zu 
sehen.

Es ist (zumindest für mich) halt auf Anhieb nicht so einfach zu 
verstehen ...

Fazit: Datenblatt lesen und richtig interpretieren :-)


Vielleicht kann der Moderator ja diesen Satz

"Das muss ich zurücknehmen ... ist zwar lt. Tabelle so, aber die 
Realität
sieht anders aus ... ."

aus meinem vorigen Posting entfernen - bitte!

Gruß
Dieter

von c-hater (Gast)


Lesenswert?

lander schrieb:

> Warum wird der Overflow Interrupt von Timer1 scheinbar bei verschiedenen
> TCNT1 Ständen ausgeführt und nicht immer bei Stand 0.

Ausgelöst wird der Interupt garantiert bei 0 (im konkreten Fall).

Ausgeführt wird die zugehörige ISR hingegen erst, wenn Zeit dazu ist. 
Und Zeit dazu ist, wenn die globalen Interrupts erlaubt sind, der 
Overflow-Interupt selber erlaubt ist und nicht noch ein Interupt 
höherer Priorität auf Ausführung wartet.

Da sind eine ganze Menge Ansatzpunkte, um eine Situation herzustellen, 
in der erstens die Overflow-ISR zu einem (virtuell) zufälligen Zeitpunkt 
ausgeführt wird und zweitens auch, um das TOVF-Bit gesetzt zu sehen.

Man muß einfach nur hinreichend wenig Ahnung vom korrekten Programmieren 
haben, dann klappt das von ganz alleine irgendwann...

von Dieter F. (Gast)


Lesenswert?

c-hater schrieb:
> Man muß einfach nur hinreichend wenig Ahnung vom korrekten Programmieren
> haben, dann klappt das von ganz alleine irgendwann...

Der Satz kommt in mein kleines schwarzes Merkbuch - das mit den 
Passwörtern, wichtigen Programmen, etc. :-)

c-hater schrieb:
> Da sind eine ganze Menge Ansatzpunkte, um eine Situation herzustellen,
> in der erstens die Overflow-ISR zu einem (virtuell) zufälligen Zeitpunkt
> ausgeführt wird und zweitens auch, um das TOVF-Bit gesetzt zu sehen

Im konkreten Fall (s.o.) gibt es aber nur eine ISR, für die ausreichend 
Zeit bleibt -> Messfehler ...

von lander (Gast)


Lesenswert?

c-hater schrieb:
> lander schrieb:
>
>> Warum wird der Overflow Interrupt von Timer1 scheinbar bei verschiedenen
>> TCNT1 Ständen ausgeführt und nicht immer bei Stand 0.
>
> Ausgelöst wird der Interupt garantiert bei 0 (im konkreten Fall).

Das weiß ich.

> Ausgeführt wird die zugehörige ISR hingegen erst, wenn Zeit dazu ist.
> Und Zeit dazu ist, wenn die globalen Interrupts erlaubt sind, der
> Overflow-Interupt selber erlaubt ist und nicht noch ein Interupt
> höherer Priorität auf Ausführung wartet.

Das weiß ich auch.

> Da sind eine ganze Menge Ansatzpunkte, um eine Situation herzustellen,
> in der erstens die Overflow-ISR zu einem (virtuell) zufälligen Zeitpunkt
> ausgeführt wird und zweitens auch, um das TOVF-Bit gesetzt zu sehen.

Na klar.

> Man muß einfach nur hinreichend wenig Ahnung vom korrekten Programmieren
> haben, dann klappt das von ganz alleine irgendwann...

Irgendwas Neues?

von Dieter F. (Gast)


Lesenswert?

lander schrieb:
> Irgendwas Neues?

Von Dir zumindest nicht ...

von lander (Gast)


Lesenswert?

Dieter Frohnapfel schrieb:
> lander schrieb:
>> Irgendwas Neues?
>
> Von Dir zumindest nicht ...

rofl. In diesem Haifischbecken ist ja gar nichts sicher. rofl.

von Sepp (Gast)


Lesenswert?

Good news everyone,

hab das/die Probleme gelöst. Zwei Dinge waren dazu nötig:
1. Bei den Tool-Einstellungen für den JTAG Atmel ICE Debugger das 
Häckchen bei "Keep timers running in stop mode" weggeben. Ich war der 
Meinung, dass der Code beim On-Chip Debuggen wenigstens bis zum 
Breakpoint mit der normalen Geschwindigkeit läuft, dem ist aber nicht 
so. Deswegen war der Counter im I/O View schon viel weiter als 0 
gelaufen bis das Programm wirklich angehalten war. Das gleiche mit dem 
TOV1 Flag.
Das erklärt aber immer noch nicht, warum das ganze nicht ohne Debugger 
geklappt hat, was ich ja ebenso getestet habe.

2. Update von Atmel Studio auf die neueste Version (6.2.1563 - Service 
Pack 2).
An was es jetzt konkret gelegen hat oder ob ich vielleicht doch noch 
irgendwo einen Auswerefehler gemacht hab kann ich nicht sagen, mir fehlt 
auch die Zeit/Nerven um den ganz auf den Grund zu gehen.
Jedenfalls klappt jetzt alles wie erwartet.

Danke für eure Unterstützung und das heitere Klima in diesem Forum! :-)

von Dieter F. (Gast)


Lesenswert?

Na prima, weder 1.) noch 2.) scheinen mir verursachend - aber wenn es 
jetzt läuft - prima, viel Spaß weiterhin ...

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.