Forum: Mikrocontroller und Digitale Elektronik Toggle OC1B bei Vergleichswert in OCR1B ohne Interrupt


von Sebastian S. (dualsbiker)


Lesenswert?

Hallo,

ich versuche gerade den Pin OC1B am MEGA328 zu bei einem Vergleichswert 
in OCR1B zu togglen. Aber ohne Interrupt.
Der Pin macht auch was er soll, nur leider wird nicht auf OCR1B 
reagiert. Egal welchen Wert ich einstelle, die Frequenz bleibt immer 
dieselbe.

Folgendes habe ich geschrieben:

DDRB |= (1<<PB2);
OCR1B = 0x00FF;
TCCR1B |= (1<<WGM12);
TCCR1B |= (1<<CS12);
TCCR1A |= (1<<COM1B0);

Wie gesagt, der Pin togglet, nur leider unabhängig von OC1B.
Geht es doch nicht ohne Interrupt ?

von TM F. (p_richner)


Lesenswert?

Könntest du mal das ganze Programm reinstellen, so dass man etwas sieht 
und versteht?

Und warum ohne Interrupt?

von S. Landolt (Gast)


Lesenswert?

> Wie gesagt, der Pin togglet, nur leider unabhängig von OC1B.

?
OC1B ist der Pin.

Mit
> TCCR1B |= (1<<WGM12);
wird CTC mit TOP=OCR1A gewählt, also bestimmte OCR1A die Frequenz, wenn 
es denn gesetzt wäre; OCR1B legt das Tastverhältnis fest.

von S. Landolt (Gast)


Lesenswert?

> OCR1B legt das Tastverhältnis fest
Das war ein Irrtum von mir, das Tastverhältnis ist ja immer 50 %, der 
Wert von OCR1B spielt in diesem Fall eigentlich gar keine Rolle, OCR1A 
muss gesetzt werden.

von Sebastian S. (dualsbiker)


Angehängte Dateien:

Lesenswert?

Ich hab es jetzt hinbekommen. Ich musste noch das OCIE1B Bit in TIMSK1 
setzen. Und OC1B reagiert wirklich auf OCR1B. Das ist auch in der Grafik 
im Anhang gut zu erkennen.

von Peter D. (peda)


Lesenswert?

Sebastian S. schrieb:
> Aber ohne Interrupt.

Sebastian S. schrieb:
> Ich musste noch das OCIE1B Bit in TIMSK1
> setzen.

Also nun doch mit Interrupt.

von Sebastian S. (dualsbiker)


Lesenswert?

Na geht es denn nicht ohne ? Ich musste auch keine ISR schreiben bzw. 
die globalen Interrupts aktivieren.

von S. Landolt (Gast)


Lesenswert?

Da gibt es doch einige Ungereimtheiten:
1. Mit dem eingangs gezeigten Programmteil tut sich an OC1B nichts, "der 
Pin togglet" eben nicht
2. Was sollte ein gesetztes OCIE1B bewirken ohne globale 
Interruptfreigabe?
3. Im Falle einer solchen Freigabe fehlte dann die ISR ("musste auch 
keine ISR schreiben"!?)
4. Wenn es sich noch immer um den eingangs gewählten Modus 4 sowie 
gesetztes COM1B0 handelt, dann bewirkt ein Ändern von OCR1B nur ein 
totales Ein- oder Ausschalten des Signals an OC1B, je nachdem, ob OCR1B 
größer oder kleinergleich OCR1A ist.

Handelt es sich vielleicht um eine Arduinoumgebung?

von M. K. (sylaina)


Lesenswert?

Sebastian S. schrieb:
> Ich musste auch keine ISR schreiben bzw.
> die globalen Interrupts aktivieren.

Muss man für Interrupts auch nicht.

Aber gehen wir mal durch
1
DDRB |= (1 << PB2);
Hiermit schaltest du den OC1B auf Ausgang.
1
OCR1B = 0x00ff;
Hier setzt du den Registerwert auf 255, auch OK.
1
TCR1B |= (1 << WGM12);
Hiermit setzt du den CTC-Mode mit OCR1A als Top-Value...da aber OCR1A 
nicht gesetzt wird ist das immer 0, OCR1B wird also nie erreicht.
1
TCCR1B |= (1<<CS12);
Vorteiler des Timers auf 256...ist das auch so gewollt? Immerhin läuft 
der Timer damit.
1
TCCR1A |= (1<<COM1B0);
Und damit aktiviert man den Compare Output Mode, in diesem Falle das 
Togglen von OC1B, also eigentlich das, was du möchtest.
Aber wie schon gesagt, da OCR1A nicht gesetzt ist ist das 0 
(Initialisierungswert) womit OCR1B mit 255 nie erreicht wird, also wirst 
du an OC1B auch keinen Effekt sehen.
Du hast auch dann keinen Effekt an OC1B selbst wenn du OCIE1B in TIMSK1 
setzen würdest, denn OCR1B ist ja immer noch kleiner als OCR1A womit 
OCR1B immer noch nie erreicht wird. Wenn das bei dir jetzt doch einen 
Effekt hat, dann nur weil du noch Code bei dir im Quelltext hast, den du 
nicht angegeben hast.

von Korrupter Interrupter (Gast)


Lesenswert?

M.Köhler schrub:
> Du hast auch dann keinen Effekt an OC1B selbst wenn du OCIE1B in TIMSK1
> setzen würdest, denn OCR1B ist ja immer noch kleiner als OCR1A womit
> OCR1B immer noch nie erreicht wird.

Wenn OCR1A nicht angerührt wird, steht da "Null" drin. Da aber mit TCNT 
verglichen wird, ist bei jedem Überlauf von TCNT und Neubeginn bei Null 
die Bedingung erfüllt, daß beide Register gleich sind und OC1A würde 
umschalten.

Aber: Die Erfahrung lehrt: Das kann funktionieren, muß aber nicht. 
Timereinstellungen sind ein beliebtes Würfelspiel.

von Peter D. (peda)


Lesenswert?

Korrupter Interrupter schrieb:
> Timereinstellungen sind ein beliebtes Würfelspiel.

Aber nur, wenn man nicht im Datenblatt lesen mag.
Wenn man nach Datenblatt programmiert, dann macht der Timer auch genau 
das, was er soll.

von Sebastian S. (dualsbiker)


Lesenswert?

Ich hab wirklich nicht mehr Code. Ich habe selbst beim Setzen von OCR1A 
keinen Effekt auf OC1B wenn das OCIE1B nicht gesetzt ist. Und in der 
Grafik im Anhang ist auch ersichtlich, dass OC1B beim Vergleich mit 
OCR1B geschaltet wird. Ich habe selbst an OC1A keinen Effekt wenn ich 
alles darauf einstelle.

von Peter D. (peda)


Lesenswert?

Sebastian S. schrieb:
> Egal welchen Wert ich einstelle, die Frequenz bleibt immer
> dieselbe.

Das muß auch so sein, denn OCR1B bestimmt nicht den TOP-Wert des Timers, 
sondern nur den Zeitpunkt der Flanke.
Im Datenblatt ist doch einen schöne Tabelle, in welchem Mode welcher 
TOP-Wert gültig ist, OCR1B steht da nirgends.

Nur mit Interrupt kann man Perioden erzeugen, die kleiner als der 
TOP-Wert sind.

von Korrupter Interrupter (Gast)


Lesenswert?

Peter D. schrieb:
> Korrupter Interrupter schrieb:
>> Timereinstellungen sind ein beliebtes Würfelspiel.
>
> Aber nur, wenn man nicht im Datenblatt lesen mag.
> Wenn man nach Datenblatt programmiert, dann macht der Timer auch genau
> das, was er soll.

Das ist doch nicht wahr. Laut oben angeführter Zeichnung aus dem 
Datenblatt verhält es sich genau so, wie ich oben schrieb:
Da aber mit TCNT
verglichen wird, ist bei jedem Überlauf von TCNT und Neubeginn bei Null
die Bedingung erfüllt, daß beide Register gleich sind und OC1A würde
umschalten.

Du siehst also: Auch das Lesen des Datenblatts nützt Nichts, wenn sich 
Zeichnungen und Tabellen widersprechen.

Die Erfahrung des TO spricht auch dafür.

von S. Landolt (Gast)


Lesenswert?

Vielleicht ist Sebastian Schulz mit einem kleinen Muster gedient:
1
 int main(void)
2
 {
3
  DDRB = (1<<PB2);
4
  OCR1B = 0;
5
  TIMSK1= 0;
6
  TCCR1A = (1<<COM1B0);
7
  TCCR1B = (1<<WGM12) | (1<<CS12);
8
9
  OCR1A = 50;    // hier die gewuenschte Frequenz an OC1B==B2 einstellen
10
11
 while(1){
12
 }
13
 }

von Sebastian S. (dualsbiker)


Lesenswert?

Habt ihr das auch ausprobiert ?

von S. Landolt (Gast)


Lesenswert?

Ja.

von S. Landolt (Gast)


Lesenswert?

Umgekehrt gefragt: Sie haben doch sicher mein Muster ausprobiert, was 
kam denn dabei heraus?

von M. K. (sylaina)


Lesenswert?

Korrupter Interrupter schrieb:
> Wenn OCR1A nicht angerührt wird, steht da "Null" drin. Da aber mit TCNT
> verglichen wird, ist bei jedem Überlauf von TCNT und Neubeginn bei Null
> die Bedingung erfüllt, daß beide Register gleich sind und OC1A würde
> umschalten.
Hier gehts aber nicht um OC1A sondern um OC1B ;)
Peter D. schrieb:
> Nur mit Interrupt kann man Perioden erzeugen, die kleiner als der
> TOP-Wert sind.
So schauts aus, das steht auch im Datenblatt, bzw. da steht, dass ohne 
Interrupt OCR1A für die Periodendauer verantwortlich ist (vgl. Page 164 
ff., Datasheet ATmega328/P)
Korrupter Interrupter schrieb:
> Du siehst also: Auch das Lesen des Datenblatts nützt Nichts, wenn sich
> Zeichnungen und Tabellen widersprechen.
Wo genau widerspricht sich Zeichnung, Tabelle und Text? Bitte mit 
Referenz auf das aktuelle Datenblatt des ATmega328/P. Da könnte man ja 
Mikrochip einen Tipp geben ;)

von Korrupter Interrupter (Gast)


Angehängte Dateien:

Lesenswert?

M. K. schrieb:
> Korrupter Interrupter schrieb:
>> Wenn OCR1A nicht angerührt wird, steht da "Null" drin. Da aber mit TCNT
>> verglichen wird, ist bei jedem Überlauf von TCNT und Neubeginn bei Null
>> die Bedingung erfüllt, daß beide Register gleich sind und OC1A würde
>> umschalten.
> Hier gehts aber nicht um OC1A sondern um OC1B ;)


das ist bei OCR1A oder B das Gleiche, wie man in dem angefügten 
Bildausschnitt sehen kann: Beide können den Inhalt von TCNT mit ihrem 
Inhalt vergleichen und dann das (interne) Bit oder (wenn gesetzt) den 
physischen Ausgang schalten.

> Wo genau widerspricht sich Zeichnung, Tabelle und Text? Bitte mit
> Referenz auf das aktuelle Datenblatt des ATmega328/P. Da könnte man ja
> Mikrochip einen Tipp geben ;)

Siehe oben.

von Peter D. (peda)


Lesenswert?

Korrupter Interrupter schrieb:
> Siehe oben.

Was gefällt Dir an dem Bild nicht?
Es stimmt doch alles.

von Korrupter Interrupter (Gast)


Lesenswert?

Peter D. schrieb:
> Korrupter Interrupter schrieb:
>> Siehe oben.
>
> Was gefällt Dir an dem Bild nicht?
> Es stimmt doch alles.

Du mußt Dir schon mal die Mühe machen, ALLES zu lesen -nicht nur 
selektiv das, was Dir schön erscheint.

Es geht nicht darum, was mir an dem Bild nicht gefällt. Das Bild 
stimmt nämlich mit der Realität überein.

Im Gegensatz zu dem hier:

>> Peter D. schrieb:
>  Nur mit Interrupt kann man Perioden erzeugen, die kleiner als der
>  TOP-Wert sind.
>> So schauts aus, das steht auch im Datenblatt, bzw. da steht, dass ohne
>> Interrupt OCR1A für die Periodendauer verantwortlich ist (vgl. Page 164
>> ff., Datasheet ATmega328/P)

Das ist nicht richtig -und das wiederspricht auch der Zeichnung.

von M. K. (sylaina)


Lesenswert?

Korrupter Interrupter schrieb:
> Das ist nicht richtig -und das wiederspricht auch der Zeichnung.

Was stimmt denn daran nicht?
Im CTC-Modus zählt der Timer bis OCR1A (Waveform-Generation Mode 4). Ich 
sehe nicht, was da nicht stimmen soll.

von M. K. (sylaina)


Angehängte Dateien:

Lesenswert?

Ich hab grad mal was runter getippt:
1
int main(void){
2
    DDRB |= (1 << PB2);
3
    OCR1B = 0xff;
4
    OCR1A = 0xffff;
5
    TCCR1A |= (1 << COM1B0);
6
    TCCR1B |= (1 << WGM12)|(1 << CS10);
7
    for(;;){
8
        
9
    }
10
    return 0;
11
}

An OC1B hat man dann das Signal (ATmega328/P mit 16 MHz Resonator), das 
im Anhang gezeigt ist.

Und wie schon gesagt, wenn OCR1B größer OCR1A ist dann tut sich auch an 
OC1B nix da ja OCR1B nie erreicht wird. Und das steht auch so im 
Datenblatt, ich seh einfach nicht, was da im Datenblatt nicht stimmen 
soll.

von Korrupter Interrupter (Gast)


Lesenswert?

M.Köhler schrieb:
>Und wie schon gesagt, wenn OCR1B größer OCR1A ist dann tut sich auch an
>OC1B nix da ja OCR1B nie erreicht wird. Und das steht auch so im
>Datenblatt, ich seh einfach nicht, was da im Datenblatt nicht stimmen
>soll.

Doch, tut sich. Wenn man sich das Ganze als Ring vorstellt, dann kommt 
OCR1A irgendwann an OCR1B "vorbei", selbst wenn eines davon auf Null 
steht.

Auf diese Weise kann man z.B. ein Signal in der Art eines Servotesters 
erzeugen, ohne Interrupt und ohne den Kontroller mit irgendwelchen 
Rechnereien zu belasten.

Dadurch erklärt sich auch, was der TO selbst feststellte:

> Ich hab wirklich nicht mehr Code. Ich habe selbst beim Setzen von OCR1A
> keinen Effekt auf OC1B wenn das OCIE1B nicht gesetzt ist. Und in der
> Grafik im Anhang ist auch ersichtlich, dass OC1B beim Vergleich mit
> OCR1B geschaltet wird. Ich habe selbst an OC1A keinen Effekt wenn ich
> alles darauf einstelle.

Ich belasse es nun dabei. Jeder muß da seine eigenen Erfahrungen 
sammeln.

von M. K. (sylaina)


Lesenswert?

Korrupter Interrupter schrieb:
> Doch, tut sich. Wenn man sich das Ganze als Ring vorstellt, dann kommt
> OCR1A irgendwann an OCR1B "vorbei", selbst wenn eines davon auf Null
> steht.

Nein, eben nicht. Wenn OCR1A < OCR1B ist und man den CTC-Modus mit OCR1A 
als Top-Value einstellt dann wird OCR1B nie erreicht wenn OCR1B > OCR1A 
ist weil ja der TCNT ständig auf 0 gesetzt wird wenn OCR1A erreicht 
wird. Das ist doch der Witz am CTC-Modus: Man muss sich nicht mehr drum 
kümmern, dass der Counter zurückgestellt wird.

von Peter D. (peda)


Lesenswert?

Korrupter Interrupter schrieb:
> Jeder muß da seine eigenen Erfahrungen
> sammeln.

Mein Erfahrungen sind, wenn man nach Datenblatt programmiert, 
funktioniert es sofort.
Und auch die TOP-Werte für alle 16 Modi stimmen in der Tabelle:
Table 20-6. Waveform Generation Mode Bit Description

von TM F. (p_richner)


Lesenswert?

M. K. schrieb:
>> Doch, tut sich. Wenn man sich das Ganze als Ring vorstellt, dann kommt
>> OCR1A irgendwann an OCR1B "vorbei", selbst wenn eines davon auf Null
>> steht.
>
> Nein, eben nicht. Wenn OCR1A < OCR1B ist und man den CTC-Modus mit OCR1A
> als Top-Value einstellt dann wird OCR1B nie erreicht wenn OCR1B > OCR1A
> ist weil ja der TCNT ständig auf 0 gesetzt wird wenn OCR1A erreicht
> wird. Das ist doch der Witz am CTC-Modus: Man muss sich nicht mehr drum
> kümmern, dass der Counter zurückgestellt wird.

Ihr habt beide Recht. Nur sprecht ihr nicht vom selben.

Der obere Threat entspricht dann, wenn TOP 255 (8bit) ist.

Der untere Threat entspricht dann, wenn TOP OCR0A ist, d.h., einen Wert 
zwischen 0 und 255.

Aber solange TOP auf 255 gesetzt ist, erreicht der Counter IMMER OCR0A 
UND OCR0B.

Hoffe das klärt es.

von M. K. (sylaina)


Lesenswert?

TM F. schrieb:
> Aber solange TOP auf 255 gesetzt ist, erreicht der Counter IMMER OCR0A
> UND OCR0B.

Richtig, aber der TE hatte ja den Mode 4 gewählt ganz oben und da wird 
halt nur bis OCR1A gezählt und wenn OCR1B dann größer OCR1A ist tut sich 
halt an OC1B auch nix. Ich bin halt immer noch vom Problem des TEs 
ausgegangen.

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.