Forum: Mikrocontroller und Digitale Elektronik Interrupt Unterschiede beim 8-Bit Timer vom Atmega 128


von Luke (Gast)


Lesenswert?

Hallo allerseits,

ich bin ein Neuling im Bereich Mikrocontroller und habe eine Frage zum 
Timer.

Der Timer0 vom Atmega 128 funktioniert ja indem er in dem Register TCNT0 
Register hoch zaehlt bis maximal 255. Die Frequenz mit der hoch gezaehlt 
wird kann mit einem Prescaler reduziert werden.
Nun kann man den Wert von TCNT0 mit einem Vergleichsregister OCR0 
vergleichen. In dieses OCR0 Register kann ich einen beliebigen Wert von 
0-255 eintragen. Bis zu diesem Wert wird gezaehlt!.

Der Timer kann im Interruptbetrieb durch zwei Unterschiedliche 
Interrupts unterbrochen werden:

• Bit 1 – OCIE0: Timer/Counter0 Output Compare Match Interrupt Enable 
When the OCIE0 bit is written to one, and the I-bit in the Status 
Register is set (one), the Timer/Counter0 Compare Match interrupt is 
enabled. The corresponding interrupt is executed if a compare match in 
Timer/Counter0 occurs, i.e., when the OCF0 bit is set in the 
Timer/Counter Interrupt Flag Register – TIFR.

• Bit 0 – TOIE0: Timer/Counter0 Overflow Interrupt Enable When the TOIE0 
bit is written to one, and the I-bit in the Status Register is set 
(one), the Timer/Counter0 Overflow interrupt is enabled. The 
corresponding interrupt is executed if an overflow in Timer/Counter0 
occurs, i.e., when the TOV0 bit is set in the Timer/Counter Interrupt 
Flag Register – TIFR.


OCIE0 wartet also bis OCF0 gesetzt ist (der Timerwert identisch ist mit 
dem vorgegebenen Wert, OCR0=TCNT0)

TOIE0 wartet also bis TOV0 gesetzt ist (der Timerwert TCNT0 einen 
hoeheren Wert als 255 hat und das Register "ueberlaeuft" ?)

OCIE0 verstehe ich. Macht Sinn einen Interrupt zu haben der ausloest 
wenn ein "Match" stattfindet. Was aber hat es mit diesem TOIE0 auf sich? 
Und wann kommt er zum Einsatz ?

Danke schonmal im Voraus.

VG Luke.

von Falk B. (falk)


Lesenswert?

@ Luke (Gast)

>vergleichen. In dieses OCR0 Register kann ich einen beliebigen Wert von
>0-255 eintragen. Bis zu diesem Wert wird gezaehlt!.

Wenn man den CTC-Modus oder einen ähnlichen Modus eingestellt hat. Im 
Normalmodus zählt der immer bis 255.

>Der Timer kann im Interruptbetrieb durch zwei Unterschiedliche
>Interrupts unterbrochen werden:

Nicht der Timer wird unterbrochen sondern es wird ein Interrupt 
ausgelöst. Der Timer läuft normal weiter. Wenn die Interupts 
freigeschaltet sind, wird der Programmablauf der CPU unterbrochen, siehe 
Interrupt.

>• Bit 1 – OCIE0: Timer/Counter0 Output Compare Match Interrupt Enable

TCNT0 == OCRA0

>• Bit 0 – TOIE0: Timer/Counter0 Overflow Interrupt Enable When the TOIE0

TCNT0 geht von 255 auf 0

>OCIE0 wartet also bis OCF0 gesetzt ist (der Timerwert identisch ist mit
>dem vorgegebenen Wert, OCR0=TCNT0)

Ja.

>TOIE0 wartet also bis TOV0 gesetzt ist (der Timerwert TCNT0 einen
>hoeheren Wert als 255 hat

Hat er nie.

> und das Register "ueberlaeuft" ?)

Das schon eher.

>OCIE0 verstehe ich. Macht Sinn einen Interrupt zu haben der ausloest
>wenn ein "Match" stattfindet.

Kommt auf die Anwendung an.

> Was aber hat es mit diesem TOIE0 auf sich?
>Und wann kommt er zum Einsatz ?

Viel öfter. Nämlich dann, wenn man einen periodischen Interrupt haben 
möchte, mit dem periodisch in gleichbleibenden Abständen Dinge erledigt 
werden sollen. Interne Uhr, Tasten abfragen, Signale generieren, State 
Machines abarbeiten etc.

von Luke (Gast)


Lesenswert?

Falk Brunner

Gebt diesem user einen award.

Danke vielmals. Sehr kompakt und verständlich erklärt.

LG Luke.

von Luke (Gast)


Lesenswert?

Eine Frage hat sich im Nachhinein doch noch ergeben.

So wie du er erklärt hast ist TOIE0 ein Sepzialfall von OCIE0 !


Bei OCIE0  wird ein Interrupt ausglöst sobald der von mir eingestellte 
Wert erreicht wurde (Vergleich mit Compare-register).


Bei TOIE0  wird er immer bei 255 ausgelöst. Denn ein Überlauf findet ja 
nur statt wenn er auf 255 noch 1 dazuzählt.


Wenn ich also im Compare-register 255 (max) stehen habe ist das 
Verhalten dieser beiden Interrupts identisch ???

Danke im Voraus.

LG Luke

von Falk B. (falk)


Lesenswert?

ja

von Jacko (Gast)


Lesenswert?

Ja,
einmal bekommst du einen Interrupt, wenn der Zählerstand
TCNT0 gerade gleich OCR0 ist: COMPARE-MATCH-INTERRUPT,

oder wenn der Zähler "überläuft": OVERFLOW-INTERRUPT.

Im Normal-Mode erscheinen beide Interrupts (wenn auch
verschoben) im selben Zeitabstand:
Meist nicht sehr interessant...

Interessant wird es doch eher, wenn du den Timer
im CTC-Mode nicht bis 255 zählen lässt, sondern nur
bis zu einer gewüschten Zahl in OCR0 - dann gibt es aber
keinen Überlauf-Interrupt: Die 255 wird nie erreicht.

Bei passender Wahl für den Wert von OCR0 kannst du aber
die gewünschte Wiederholfrequenz recht genau einstellen!
Und mit Hilfe des OCR0-Interrupts z.B eine Stoppuhr mit
1/100 s Auflösung verwirklichen...

von Luke (Gast)


Lesenswert?

Hi Jakob,

danke für deinen Input.

Eine Frage noch zu deinem letzen Abschnitt.

Wird das OCR0 nach einem "match" geleert ?
Oder bleibt der Wert erhalten und triggert das Compare-Interrupt 
zyklisch immer wieder auf den voreingestellten Wert ?
Falls dem so ist, verstehe ich ehrlich gesagt den Sinn des Overflow 
Interupts nicht. Er erscheint sinnlos.


Noch eine super dumme Frage für die ich auf keinen Fall ein neues Topic 
eröffnen kann:

Die folgenden Statements machen alle dasselbe in C oder ?

unsigned char byte = 0x00;

byte = 0x03;

byte = 3;

byte |= (1<<1)|(1<<2);

byte = 0b00000011

Vielen Dank schonmal!

LG Luke

von Zweifler (Gast)


Lesenswert?

Luke schrieb:
> byte |= (1<<1)|(1<<2);

Bist Du hier sicher?

von Falk B. (falk)


Lesenswert?

@ Luke (Gast)

>Wird das OCR0 nach einem "match" geleert ?

Nein!

>Oder bleibt der Wert erhalten und triggert das Compare-Interrupt
>zyklisch immer wieder auf den voreingestellten Wert ?

JA!

>Falls dem so ist, verstehe ich ehrlich gesagt den Sinn des Overflow
>Interupts nicht. Er erscheint sinnlos.

Nein, er hat schon seine Funktion. Mach dir mal nicht zuviele Gedanken.

>Die folgenden Statements machen alle dasselbe in C oder ?

Sicher, es sind nur andere Zahlensysteme und Bitmanipulation.

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi
Luke schrieb:
> unsigned char byte = 0x00;
Ne, setzt byte auf Null

Luke schrieb:
> byte |= (1<<1)|(1<<2);
Je nachdem, was vorher in byte stand, kann Da dann auch mehr als 3 drin 
sein.

MfG

EDIT
Zweifler schrieb:
> Bist Du hier sicher?

Oha, da steht ja <<1 und <<2 ... neee, das gibt auf jeden Fall eine 
schöne 6 (eine 1 ist 1<<0, also 1 um 0 Bit verschoben)

: Bearbeitet durch User
von Zweifler (Gast)


Lesenswert?

Patrick J. schrieb:
> Je nachdem, was vorher in byte stand, kann Da dann auch mehr als 3 drin
> sein.

Patrick J. schrieb:
> Oha, da steht ja <<1 und <<2 ... neee, das gibt auf jeden Fall eine
> schöne 6 (eine 1 ist 1<<0, also 1 um 0 Bit verschoben)

Ja, ich empfehle: 
https://www.mikrocontroller.net/articles/Bitmanipulation

von Luke (Gast)


Lesenswert?

Ahaaa.

Also steht bei dem Ausdruck (1<<x) bei x nicht um wie viel stellen es 
rein geschoben wird sondern an welche stelle es geschoben wird!!!!

Richtig wäre also:


byte |= (1<<0)|(1<<1);

damit eine dezimale 3 rauskommt.

Ich bin mir bewusst darüber das die anderen Bits unverändert bleiben, 
weshalb ich das ganze Byte anfangs auf 0 gesetzt hab.


Und ja, diese Info hätte ich auch schnell "ergooglen" können :)
Aber ich hab es einfach mal hier gefragt da ich ja eh schon am "Hilfe 
erbeten" war.

Danke an alle für eure zahlreichen Kommentare.

@Zweifler, du machst deinem Namen alle Ehre, haha.

Viel Grüße und einen sonnigen Sonntag wünsche ich.

Luke

von Zweifler (Gast)


Lesenswert?

Luke schrieb:
> Also steht bei dem Ausdruck (1<<x) bei x nicht um wie viel stellen es
> rein geschoben wird sondern an welche stelle es geschoben wird!!!!

Bist Du Dir da sicher?

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

Du kannst auch komplexere Bitgebilde (aka Zahlen) shiften.
Dabei gibt die hintere Zahl an, um wie viele Stellen die Zahl verschoben 
wird, also ein <<0 verschiebt um keine Stelle - man könnte sich Das 
theoretisch auch sparen, da die Zahl sie selber bleibt - in der Praxis 
ist die hintere Zahl aber eine Konstante der Innereien eines µC.
Und wenn ich die Taktrate des Timer 0 'komfortabel' im Listing 
einstellen können will, schreibe ich
ldi r16,(0<<CS13)|(1<<CS12)|(0<<CS11)|(0<<CS10)
Um das Bitmuster 0100 an die entsprechenden Stellen zu schieben.
Dabei ist CS10 wohl in so ziemlich jedem AVR eine Null, wenn aber nicht, 
funktioniert die Zeile immer noch - kostet nur Rechenzeit beim 
Compiler/Assembler, lässt sich leicht lesen und funktioniert bestens.

Du kannst damit auch Zahlen verdoppeln (auch mehrfach), so macht ein 
Shiften um 2 das Gleiche, wie die Multiplikation mit 4 (2x2).

Nur aufpassen, daß 'links' Nichts raus fällt ;)

MfG

von Luke (Gast)


Lesenswert?

Jap absolut.

Steht hier auf der Seite unter Bitmanipulation:
Beispiel:


ldi temp, (1<<3) | (1<<1) | (1<<2) | (1<<0)
entspricht:


ldi temp, 8 | 2 | 4 | 1



Es wird jeweils eine logische 1 an die Stelle 0,1,2 und 3 geschrieben.

Patrick, danke für die Info!

LG Luke

von Zweifler (Gast)


Lesenswert?

Luke schrieb:
> Jap absolut.
>
> Steht hier auf der Seite unter Bitmanipulation:

> Es wird jeweils eine logische 1 an die Stelle 0,1,2 und 3 geschrieben.

Im Ergebnis, ja. Aber: 1<<0 bedeutet, die 1 wird null mal geschoben.

Zitat aus meinem Link:
<< = Links schieben (Bsp: a<<b ist das gleiche wie a * 2^b; bzw. bei 
1<<3 wird die 1 um drei Stellen nach links geschoben)

(Ok, das ist Krümelk....)

von Luke (Gast)


Lesenswert?

ouhhhh,
jetzt verstehe ich es.


also genau gesehen wird nur im Bezug aufs Ergebniss der Wert an die 
Stelle x geschrieben. Ansonsten heißt dieses x : schiebe 00000001 um x 
stellen nach links !!!!!!

Danke das du so lange, tapfer gezweifelt hast Zweifler ! ^^

LG Luqman

von Zweifler (Gast)


Lesenswert?

Luke schrieb:
> Danke das du so lange, tapfer gezweifelt hast Zweifler ! ^^

Jetzt nicht frech werden ... ;-)

Viel Erfolg weiterhin!

von Carl D. (jcw2)


Lesenswert?

Patrick J. schrieb:
> Hi
>
> Du kannst auch komplexere Bitgebilde (aka Zahlen) shiften.
> Dabei gibt die hintere Zahl an, um wie viele Stellen die Zahl verschoben
> wird, also ein <<0 verschiebt um keine Stelle - man könnte sich Das
> theoretisch auch sparen, da die Zahl sie selber bleibt - in der Praxis
> ist die hintere Zahl aber eine Konstante der Innereien eines µC.
> Und wenn ich die Taktrate des Timer 0 'komfortabel' im Listing
> einstellen können will, schreibe ich
> ldi r16,(0<<CS13)|(1<<CS12)|(0<<CS11)|(0<<CS10)
> Um das Bitmuster 0100 an die entsprechenden Stellen zu schieben.

Lesbarer finde ich:
1
ldi r16,(0b0100<<CS10)
denn dann steht genau die CD-Konstante aus dem Datenblatt da.
(wenn ich das auch sonst immer in C* schreibe)

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Carl D. schrieb:

> Lesbarer finde ich:
>
1
ldi r16,(0b0100<<CS10)
> denn dann steht genau die CD-Konstante aus dem Datenblatt da.

Das funktioniert aber nur dann, wenn die CSnx-Bits wohlgeordnet sind. 
Zwar ist das wohl bei allen AVR8 der Fall, aber zwingend ist es nicht, 
zumindest theoretisch könnten die Bits auch völlig irregulär angeordnet 
im Register liegen, Atmel hat sich diese Option dadurch offen gehalten, 
dass eben jedes einzelne Bit seinen eigenen symbolischen Namen hat.

Und die lange Variante würde eben auch diesen Fall problemlos abdecken, 
deine hingegen würde dann Mist bauen.

von Carl D. (jcw2)


Lesenswert?

c-hater schrieb:
> Carl D. schrieb:
>
>> Lesbarer finde ich:
>>
1
ldi r16,(0b0100<<CS10)
>> denn dann steht genau die CD-Konstante aus dem Datenblatt da.
>
> Das funktioniert aber nur dann, wenn die CSnx-Bits wohlgeordnet sind.
> Zwar ist das wohl bei allen AVR8 der Fall, aber zwingend ist es nicht,
> zumindest theoretisch könnten die Bits auch völlig irregulär angeordnet
> im Register liegen, Atmel hat sich diese Option dadurch offen gehalten,
> dass eben jedes einzelne Bit seinen eigenen symbolischen Namen hat.
>
> Und die lange Variante würde eben auch diesen Fall problemlos abdecken,
> deine hingegen würde dann Mist bauen.

Ja, das ist mir bekannt. Dafür verwende ich dann die mehrfach gehatete 
Sprache, die es erlaubt WGM0..3 auch auf 2 verschieden HW-Register 
verteilt am Stück anzusprechen und sogar nur erlaubte Werte aus einem 
enum zuweisen zu lassen.
Böse Abstraktion, die am Ende genau die beiden Register füllt, je ein 
ldi und ein std. Sogar wenn auch die anderen Bits dieser Register 
angesprochen werden.

BTW, bitweise muß man natürlich auch wissen, in welchem Register die 
jeweils liegen.

: Bearbeitet durch User
von Uwe (Gast)


Lesenswert?

Hi,
>verstehe ich ehrlich gesagt den Sinn des Overflow
>Interupts nicht. Er erscheint sinnlos.
Lasse den Timer normal laufen und du hast 2 Int. zb. für Tasten (FF>00)
und OC0 in der Hälfte für... LCDtakt oder eben 2x LCD und 1x Tasten.

viel Erfolg, Uwe

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.