Forum: Mikrocontroller und Digitale Elektronik OCR1A lässt sich nur 1x ändern


von Marcel K. (viewer)


Angehängte Dateien:

Lesenswert?

Hallo Forumgemeinde,

ich habe das Problem, dass sich das OCR1A- Register nur 1x ändern lässt.
Ich verwende den ATMega168 im debug-wire Mode. Ich habe den Code auf das
Minimum reduziert und auf das wesentliche begrenzt (siehe Anhang). Ich
verwende den Timer 1 im phase correct Mode (10). Das heißt, ich laden
den ICR1 mit einem Wert der den TOP- Wert des Timers sein soll.
Zusätzlich wird der OCR1A mit einem Wert geladen der den Pin schalten
soll. Es wird auch ein Interrupt zum OCR1A und ICR1 (TOP) generiert.
Dann ist es mein Ziel, wenn der TOP- Wert erreicht wird, möchte ich in
der ISR einen neuen OCR1A Wert schreiben. Der soll etwas höher vom
Zählerwert sein, wie der alte. Also nicht mehr symmetrisch.   Da ist
dann das Problem, dass das Register einfach nicht mehr überschrieben
werden kann. Ich habe schon versucht sowohl direkt in des Register zu
schreiben (16bit) aber auch über das high Byte und dann das low- Byte.
Das hatte alles keinen Effekt. Ich habe das Gefühl als wäre das
schreiben in den OCR1A- Register irgendwie gesperrt. Kann das denn
möglich sein? Hat jemand von Euch eine Idee wieso ich nicht das Register
ändern kann? Das ganze klappt übrigens auch nicht, wenn ich das Ganze im
Studio 6.1 simuliere. Liegt es vielleicht am Studio 6.1?
Viele Grüße,
Marcel

von Karl H. (kbuchegg)


Lesenswert?

Hast du auch lange genug gewartet?
In einigen PWM-Modi wird die Zuweisung an OCR1A zwischengespeichert und 
erst wenn der Timer seinen Top-Wert erreicht, erfolgt dann die 
eigentliche Zuweisung an das echte Register.


>
1
>    sreg = SREG;
2
>

lass das SREG in Ruhe! Diese Register gehen dich alle nichts an. Die 
stehen unter Kontrolle des COmpilers. Wenn du ihm da reinpfuscht, 
gewinnst du im besten Fall nichts, im schlimmsten Fall zerstörst du dir 
alles.

von Karl H. (kbuchegg)


Lesenswert?

>
1
> SIGNAL(TIMER1_CAPT_vect)
2
> {
3
>    //WriteOCR1A(SYNC_PULSE - LOW_PULSE);
4
>    WriteOCR1A(0x2600);
5
> ...
6
> 
7
> 
8
> void WriteOCR1A(unsigned int value)
9
> {
10
>    /* Disable interrupts */
11
>    cli();
12
> ....
13
>    sei();
14
> }
15
>

und halt dich auch aus dem cli()/sei() raus!
Wenn WriteOCR1A aufgerufen wird, sind die Interrupts sowieso gesperrt, 
weil der Aufruf aus einer ISR heraus erfolgt!
Auch hier wieder: wenn du dich da einmischt, zerstörst du dir im 
schlechtesten Fall alles, weil der abschliessende sei() zu früh erfolgt.

von Marcel K. (viewer)


Lesenswert?

Hallo Karl Heinz Buchegger,

also die Fkt. WriteOCR1A stammt aus dem Datenblatt von Atmel!

Aber Du hast Recht. Wenn ich das Schreiben in das OCR1A Register bereits 
in der OCR1A ISR mache, folgt darauf der ICR1 Interrupt und dann steht 
der neue Wert im OCR1A- Register. Dann löst die OCR1A- ISR an der 
richtigen Stelle aus.
SUPER, das war's, vielen Dank ;o)

Schönen Abend noch...

Marcel (",)

von Marcel K. (viewer)


Lesenswert?

Wie gesagt, das stammt von Atmel. Ich hätte eine direkt, 16bit Zuweisung 
gemacht.

Grüße..

von Justus S. (jussa)


Lesenswert?

da steht die Funktion aber nicht in einer Interrupt-Routine...

von Marcel K. (viewer)


Lesenswert?

Hallo noch Mal,

ich muss das Thema noch Mal hoch hohlen da es doch nicht richtig klappt.

Ich habe die Zuweisung des OCR1A jetzt in dessen ISR gemacht. Also so:

---------------------------------------------------------
1
SIGNAL(TIMER1_COMPA_vect)
2
{
3
   switch(count_state)
4
   {
5
      case COUNT_UP:
6
      OCR1AH = 0x25;
7
      OCR1AL = 0x00;
8
      count_state = COUNT_DOWN;
9
      break;
10
      
11
      case COUNT_DOWN:
12
      OCR1AH = 0x08;
13
      OCR1AL = 0x00;
14
      count_state = COUNT_UP;
15
      break;
16
   }
17
   set_output_pin();
18
}   
19
20
21
SIGNAL(TIMER1_CAPT_vect)
22
{
23
   clr_output_pin();
24
}
25
26
27
SIGNAL(TIMER1_OVF_vect)
28
{
29
   clr_output_pin();
30
   toggle_oszi_pin();   // Als Trigger- Signal für's Oszi
31
}
---------------------------------------------------------

Ich habe es im Datenblatt gelesen, dass der OCR1A immer entweder bei TOP 
oder BOTTOM aus dem Puffer in das Register "geupdated" wird. Das 
passiert allerdings nicht :.(
ALso wenn der Timer hoch zählt und dann in die OCR1A- ISR kommt, wird 
das OCR1A Register beschrieben und dann wir der Wert sobald die IRC1- 
ISR erreicht wird (TOP) auch reingeschrieben. Dann folgt beim runter 
zählen wieder die OCR1A- ISR mit neuem Capture- Wert. Der Wert der dann 
in das OCR1A- Register geschrieben wird, wurde nicht übernommen. Ich 
hätte erwarte, dass der Wert dann in der Overflow- ISR übernommen wird.

Hat noch jemand eine hilfreiche Idee?

Grüße,
Marcel (",)

von Marcel K. (viewer)


Lesenswert?

Hallo,

hat keiner noch einen Tip für mich?

Ich habe alles Mögliche schon probiert. Ich komme nicht weiter. Ist es 
denn sicher, dass das Register an TOP und an BOTTOM aktuallisiert wird?

Schönene Sonntag noch,

Marcel

von Wolfe (Gast)


Lesenswert?

Marcel K. schrieb:
> Ich habe alles Mögliche schon probiert. Ich komme nicht weiter. Ist es
> denn sicher, dass das Register an TOP und an BOTTOM aktuallisiert wird?

Nein. Das OCR1A Register wird im Phase Correct Modus NUR bei TOP 
aktualisiert. Kann man dem Datenblatt Seite 132, Table 16-4 bei Mode 10 
entnehmen.

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.