Compare Match in Software (kein PWM)

Gast #1677742
Lesenswert?

Hallo!

Ich suche nach einem Tipp wie ich bei einem durchlaufenden 16-bit Timer 
eine "Compare Match" Einheit in Software nachbilden kann. Damit soll 
eine variable Frequenz generiert werden. Der Timer darf nicht verändert 
werden.

Wäre eine (Hardware-) Compare Match Einheit frei würde man immer im 
OC-Interrupt die nächste Periode auf den alten OCR-Wert aufaddieren und 
ins OCR schreiben.

In Software kann man nicht davon ausgehen genau zu "treffen" (Counter == 
Compare Value), sondern muss (Counter >= Compare Value) prüfen. Das 
funktioniert solange gut bis der Counter rumläuft und wieder bei 0 
startet. Um das zu merken muss ich den Overflow auswerten.

Pseudocode:
1
CNT = 13543
2
OC = 32000
3

4
if ((CNT >= OC) || (OVF))   // erste Bedingung wahr
5
{
6
[CNT == 34674]
7
OC = OC + 32000 = 64000
8
OVF = false
9
...
10
}
11

12
if ((CNT >= OC) || (OVF))   // zweite Bedingung wahr
13
{
14
[CNT == 367]
15
OC = OC + 32000 = 64000
16
OVF = false
17
...
18
}

Problemfall:
1
CNT = 61543
2
OC = OC + x = 32000
3

4
sofort:
5

6
if ((CNT >= OC) || (OVF))   // erste Bedingung wahr -> FALSCH
7

8
nach Überlauf:
9

10
if ((CNT >= OC) || (OVF))   // zweite Bedingung wahr -> FALSCH

Hat jemand eine Idee das ganze EFFIZIENT zu implementieren. Das ist doch 
bestimmt mit nem guten Trick einfach möglich...

Grüße
Robert
#1677754
Lesenswert?

Ich würde einfach vom Counter den Compare-Wert abziehen, und die 
Differenz dann auf kleiner einer Konstante testen. Der Vergleich liefert 
dir dann die Info, ob sich der Counter innerhalb des Fensters OC - 
OC+Konstante befindet. Und das ganz ohne sich Gedanken um Überläufe 
machen zu müssen.
Gast #1677778
Lesenswert?

Hallo Stefan,

das kann imho nicht funktionieren da ich bei der Differenzbildung (was 
auch ein Vergleich ist) nicht unterscheiden kann zwischen "Counter ist 
zwar größer aber muss noch einmal rum" und "Counter ist größer und hat 
den OC-Wert passiert".

Grüße
Robert
#1677799
Lesenswert?

Robert schrieb:
> das kann imho nicht funktionieren da ich bei der Differenzbildung (was
> auch ein Vergleich ist) nicht unterscheiden kann zwischen "Counter ist
> zwar größer aber muss noch einmal rum" und "Counter ist größer und hat
> den OC-Wert passiert".

Das kommt ganz darauf an, mit was für Perioden du überhaupt konkret 
arbeitest. Das funktioniert nur dann nicht, wenn nach dem Aufaddieren 
der neue Compare-Wert wieder im Bereich des alten Compare-Wertes liegt 
(bzw. genauer: wenn der neue Wert im Bereich Counter-Konstante - Counter 
liegt).
#1677919
Lesenswert?

Robert schrieb:

> das kann imho nicht funktionieren da ich bei der Differenzbildung (was
> auch ein Vergleich ist) nicht unterscheiden kann zwischen "Counter ist
> zwar größer aber muss noch einmal rum" und "Counter ist größer und hat
> den OC-Wert passiert".

Es funktioniert schon, aber du darfst dir nicht den neuen OCR Wert nach 
dem Muster

   nächster_OCR = ZyklusStart + OCR_Delta

ausrechnen.
Statt dessen musst du vergleichen

   if( aktueller_Timer - ZyklusStart > OCR_Delta )
     // OCR wurde überschritten

aber wie bereits angesprochen: das funktioniert solange, solange du 
nicht einen kompletten Timer_einmal_rum verpasst.

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