Toggle OC1B bei Vergleichswert in OCR1B ohne Interrupt

OP #5344927
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 ?
Gast #5344953
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.
Gast #5344988
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.
Gast #5348380
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?
#5348444
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.
Gast #5348463
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.
OP #5348633
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.
#5348640
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.
Gast #5348674
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.
Gast #5348678
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
 }
#5349609
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 ;)
Gast #5349623
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.
Angehängte Dateien:
Gast #5349668
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.
#5349761
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.
Angehängte Dateien:
Gast #5349784
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.
#5349789
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.
#5349933
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren