Forum: Mikrocontroller und Digitale Elektronik AVR 16Bit Vergleich


von Dennis H. (t1w2i3s4t5e6r)


Lesenswert?

Hallo!

Ich bastel gerade an einer DCF Routine. Ich weis, das es dafür schon 
fertige Routinen hier im Forum gibt, nur ist es eben schöner, wenn man 
es selbst hinbekommen hat.

Ich nutze als Empfangsteil den Empfänger von Reichelt. Empfang ist 
wunderbar und um das Signal auszuwerten nutze ich den Input Capture 
Interrupt. Sozusagen setze ich bei steigender Flanke den Zähler auf Null 
und bei fallender Flanke versuche ich gerade den zählerstand 
auszuwerten. Ich habe mir als erstes über UART über eine Minute die 
zählerstände zum Rechner geschickt und mit HTerm angezeigt. Bei den 
jeweiligen zählerständen ist eindeutig zu erkennen, was eine logische 
eins und eine logische Null sein soll. sozusagen funktioniert mein Code 
bis zu dem Punkt ganz gut.

Ich scheitere an dem Punkt, diese 16 Bit großen Zählerstände mit einer 
Konstanten zu vergleichen, um festzustellen, ob jetzt eine logische Null 
oder logische Eins gesendet wurde.

Sozusagen möchte ich als erstes ein Signal, welches kürzer als 80ms ist, 
verwerfen, weil es offensichtlich nicht richtig empfangen wurde. Als 
nächstes möchte ich überprüfen, ob das Signal länger als 120ms war, dann 
ist es entweder ne logische eins, oder ein schlecht empfangenes Signal, 
und so weiter...

mein erster Versuch sah so aus:
1
in temp1, ICR1L
2
in temp2, ICR1H
3
cpi temp2, HIGH(1000)
4
brlo falsch
5
cpi temp1, LOW(1000)
6
brlo falsch
7
.
8
.
9
.

Dieser Code ist eine Katastrophe und funktioniert überhaupt nicht.

Jetzt habe ich hier in einem Tutorial eine bessere Lösung gefunden, die 
ich aber rein gar nicht kapiere. Ich schreibs einfach nochmal wie oben 
hin, mit den anderen Befehlen.
1
in temp1, ICR1L
2
in temp2, ICR1H
3
ldi temp3, LOW(1000)
4
ldi temp4, HIGH(1000)
5
cp temp1, temp3
6
cpc temp2, temp4
7
brlo falsch
8
.
9
.
10
.

Meine erste Frage dazu ist, warum ich zuerst das LOW-Byte vergleiche, 
weil das kann doch durchaus kleiner sein, als das LOW-Byte von 1000, 
obwohl die gesamte 16Bit Zahl vielleicht größer ist, als 1000.

Und meine zweite Frage wäre, wie spielt das Carry-Flag da mit rein. Ich 
denke fast, wenn ich das mit dem Carry Flag verstanden hab, kapiere ich 
meine andere Frage auch von selbst, nur irgendwie erschließt es sich mir 
einfach nicht.

Ich hoffe ihr könnt mir ein wenig helfen, und es ist nicht zuviel Text.



MfG Dennis

von Karl H. (kbuchegg)


Lesenswert?

Dennis H. schrieb:

>
1
> in temp1, ICR1L
2
> in temp2, ICR1H
3
> ldi temp3, LOW(1000)
4
> ldi temp4, HIGH(1000)
5
> cp temp1, temp3
6
> cpc temp2, temp4
7
> brlo falsch
8
> .
9
> .
10
> .
11
>
>
> Meine erste Frage dazu ist, warum ich zuerst das LOW-Byte vergleiche,
> weil das kann doch durchaus kleiner sein, als das LOW-Byte von 1000,
> obwohl die gesamte 16Bit Zahl vielleicht größer ist, als 1000.

Weil es 2 verschiedene Befehle sind. Das eine ist CP und das andere CPC. 
Der CPC berücksichtigt das Ergebnis des CP (in Form der Flags) in der 
Art, dass man das auf beliebige Bytezahlen erweitern kann. Einfach mal 
in der Doku den CPC Befehl genau studieren und mit ein paar Beispielen 
durchspielen.

von Karl H. (kbuchegg)


Lesenswert?

> Und meine zweite Frage wäre, wie spielt das Carry-Flag da mit rein.

Ein Compare macht nichts anderes als eine Subtraktion. Die beiden zu 
vergleichenden Werte werden miteiander verglichen (CP  a, b) indem b von 
a subtrahiert wird. Das Rechenergebnis ist dabei uninteressant und wird 
verworfen, lediglich die Flags (Carry, Overflow etc.) bleiben erhalten. 
Wenn du dich also fragst, wie das Carry Flag in einem CP reinspielt, 
musst du dich fragen, was das Carry Flag bei einer Subtraktion macht 
bzw. aussagt.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> Ein Compare macht nichts anderes als eine Subtraktion.
Ohne die Werte aber tatsächlich zu ändern.
> Das Rechenergebnis ist dabei uninteressant und wird verworfen
Bei der Subtraktion dagegen wird das Ergebnis (Differenz) an den 
Minuenden zugewiesen.

von Rainer S. (rsonline)


Lesenswert?

Ich würde die 16 Bit so verkleinern, dass es dann 8 bit werden.
Durch shift operation oder einfach nur das high Byte nehmen.
Dann ist das auch mit dem Vergleichen einfacher.

von Dennis H. (t1w2i3s4t5e6r)


Lesenswert?

Okay, vielen Dank euch für eure echt hilfreichen Tipps, ich hab 
inzwischen die Befehle mal so mit eingearbeitet, und siehe da, der Code 
funktioniert auf einmal, dafür hab ich mir jetzt ein Bier verdient :-)

Ich glaub, ich werde einfach mal ein ganz einfaches Programm schreiben, 
und da mal so einen 16 Bit Vergleich simulieren, und da werde ich ja 
dann sehen, was so die Flags machen, und wie sich das auswirkt, aber 
heute nicht mehr.

Echt nochmal vielen Dank für eure Erklärungen


dennis

von Karl H. (kbuchegg)


Lesenswert?

> mein erster Versuch sah so aus:
> in temp1, ICR1L
> in temp2, ICR1H
> cpi temp2, HIGH(1000)
> brlo falsch
> cpi temp1, LOW(1000)
> brlo falsch
> .
> .
> .
>
> Dieser Code ist eine Katastrophe und funktioniert überhaupt nicht.

Ist dir klar, warum das nicht funktioniert?

Nenn die Dinge nicht High und Low sondern Minuten und Sekunden.

Und dann wende mal deine Vorschrift auf die Vergleiche

     2 Minuten 38 Sekunden    und   1 Minute  58 Sekunden
bzw. 2 Minuten 38 Sekunden    und   2 Minuten 12 Sekunden
bzw. 2 Minuten 38 Sekunden    und   3 Minuten 12 Sekunden

an. Das 3.te Beispiel zeigt dir (hoffentlich) wo du deinen Denkfehler 
gemacht hast. (12 ist zwar kleiner als 38, das spielt aber keine Rolle, 
weil 3 Minuten schon mal mehr sind als 2 Minuten. Die Sekunden sind nur 
dann interessant, wenn beide Minutenzahlen gleich sind)

von Dennis H. (t1w2i3s4t5e6r)


Lesenswert?

Ich glaube, jetzt habe ich zumindest den Befehl cpc verstanden, 
sozusagen vergleicht dieser Befehl erstmal die beiden Bytes, und wenn 
diese gleich sind wird das Carry noch mit einbezogen, welches von dem 
vorherigen cp-Befehl beeinflusst wurde, um zu klären, welcher WErt nun 
wirklich größer oder kleiner ist, ich glaube, so langsam komme ich 
hinter die einzelnen Flags im Sreg, die haben echt haufen einfluss und 
man kann viele schöne Sachen mit denen anstellen :-)


Dennis

von Ralf2008 (Gast)


Lesenswert?

Ein kompletter Vergleich zweier 16bit Zahlen sieht normalerweise so aus:
1
CPI      ZH,QH   ; Vergleich der high bytes
2
BRLO     Z_KA_Q  ; Z kleiner als Q -> Vergleich beendet
3
BRNE     Z_GA_Q  ; Z größer als Q -> Vergleich beendet
4
CPI      ZL,QL   ; Vergleich der low bytes
5
BRLO     Z_KA_Q  ; Z kleiner als Q
6
BRNE     Z_GA_Q  ; Z größer als Q
7
Z_EQ_Q:          ; Z=Q

Ralf2008

von spess53 (Gast)


Lesenswert?

Hi

>Ich glaube, jetzt habe ich zumindest den Befehl cpc verstanden,
>sozusagen vergleicht dieser Befehl erstmal die beiden Bytes, und wenn
>diese gleich sind wird das Carry noch mit einbezogen,...

Nicht ganz. Das Carry-Flag wird generell einbezogen. Ein 'cp(i)' ist, 
wie schon gesagt, wie eine Subtraktion. Und das Carry-Flag ist der 
Übertrag, wenn der Subtrahend der ersten Subtraktion (Low-Werte) gößer 
als der Minuend ist.

MfG Spess

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.