C51-Frage
-
Hallo,
ich arbeite derzeit an automatischer Baudratenerkennung auf der seriellen Schnittstelle eines µC. Dazu habe ich ein schönes Beispiel gefunden, was ich zu 98% nachvollziehen kann. Der Code läuft sinngemäß so ab:
* Variablen deklarieren, interne Timer initialisieren
* Überwachen der RxD-Leitung - warten auf Startbit (eines definierten Zeichens)
* mehrmalige Prüfung auf Startbit-Signalpegel, um Störungen zu Filtern
* warten auf Pegel f. 1. Datenbit
* wenn Pegeländerung, Timer starten
* wenn 2. Pegeländerung, Timer in Variablen speichern und weiterlaufen lassen
* wenn 3. Pegeländerung, Timer stoppen
* Dauer 1. Datenbit aus Variablen in Integer speichern (Timer-Low- und -High-Byte)
* aufrunden des Timer-Wertes
* Dauer der 2 Datenbits in Integer speichern und halbieren
* Differenz beider Integer bewerten (müssten fast gleich sein - Differenz gering)
* Bewertung und Rundung der Werte - Errechnung der BaudrateZu dem fetten geschrieben Punkt habe ich eine Frage - hier noch der Codeauszug:
... uiMesswert1 = ACC; // Low-Byte des Timer f. 1. Datenbit aus temporärer Variable in Integer uiMesswert1 += B * 256; // High-Byte des Timer f. 1.DB aus temporärer Variable bewertet & in Integer TL0++; // --> Aufrunden des 2. Messergebnisses ???? Wozu??? uiMesswert2 = TL0; // Low-Byte des Timer f. 2 Datenbits in Integer uiMesswert2 += TH0 * 256; // High-Byte des Timer f. 2 DBs bewertet & in Integer uiMesswert2 >>= 1; // Messwert2 halbiert ...Warum wird der 2. Messwert vor der weiteren Verarbeitung aufgerundet? Kann man sich das nicht sparen oder hat es einen tieferen Sinn?
Wäre schön, wenn jemand was damit anfangen kann.
MfG
-
vielleicht wird hochgezählt, weil danach durch 2 geteilt wird? dann wird nämlich aus einer 1 keine 0. ausserdem scheint ein bug drin zu sein - was ist, wenn beim hochzählen TL0 überläuft?

-
Undertaker schrieb:
ausserdem scheint ein bug drin zu sein - was ist, wenn beim hochzählen TL0 überläuft?

Capture reload?
-
Hmmm.. ich weiß zwar nicht was "capture reload" in diesem Zshg bedeutet, aber ich bin der Meinung, wenn TL0 überläuft wird TH0 um 1 erhöht. Egal, ob das "per Hand" gemacht wird, oder nicht. Der Timer läuft im 16bit-Mode(!).
Aber den Sinn von TL0++; habe ich noch nicht verstanden. Ich hab's mir mal auf dem Papier mit einem 8bit-Wert durchgerechnet:
mit TL0++; : Ausgangswert inkrementiert halbiert (Ergebnis) 0110.1110b ++ => 0110.1111b >>1 => 0011.0111b [b]110d[/b] => 111d => [b]55d[/b] 0110.1111b ++ => 0111.0000b >>1 => 0011.1000b [b]111d [/b] => 112d => [b]56d[/b] 0111.0000b ++ => 0111.0001b >>1 => 0011.1000b [b]112d [/b] => 113d => [b]56d[/b] 0111.0001b ++ => 0111.0010b >>1 => 0011.1001b [b]113d [/b] => 114d => [b]57d[/b] 0111.0010b ++ => 0111.0011b >>1 => 0011.1001b [b]114d [/b] => 115d => [b]57d[/b] 0111.0011b ++ => 0111.0100b >>1 => 0011.1010b [b]115d [/b] => 116d => [b]58d[/b]Folglich wird indirekt jeder unrunde Wert aufgerundet, wie am Ergebnis zu sehen ist. Was passiert jetzt, wenn ich TL0++; weglasse? Ohne die Tabelle erstellen zu müssen ist mir klar, dass dann indirekt jeder unrunde Wert abgerundet wird. Bedeutet doch, jeder 2. Wert wird verfälscht - genau wie bei der Methode mit TL0++; .

Warum spare ich mir den Befehl dann nicht einfach? Ich gehe ja davon aus, der Autor des Beispiels hätte sich etwas dabei gedacht das Beispiel so zu gestalten... Da er Bücher über C51 geschrieben hat, nehme ich auch an er hat ein bißchen Ahnung von der Materie! Das ist eigentlich der Hauptgrund, warum mich dieses Problem beschäftigt.
-
Ich denke das Rätsel ist gelöst:
Wie vermutet, hat sich der Autor des Beispiels tatsächlich etwas bei TL0++; gedacht. Beim Bilden der Differenz der 2 Timerwerte (siehe Ablauf im Eröffnungs-Post) wird die Dauer des 1. Datenbit von einer errechneten Dauer des 2. Datenbit abgezogen. Die errechnete Dauer des 2. Datenbit entsteht durch das vorhergehende Halbieren des Messwertes für 2 Bitzeiten. Durch das Halbieren kann der 2. Wert kleiner sein als die Dauer des 1. Datenbit. Da unsigned integer verwendet werden, würde eine Differenz von z.B. 65535 statt -1 entstehen. Der anschließende Vergleich würde den Abbruch der Baudratenermittlung herbeiführen, obwohl Wert 1 und Wert 2 nahezu gleich groß sind:
... if((uiDauerDatenbit2 - uiDauerDatenbit1) > 3) return (0); else {...Errechnen der Baudrate...} ...Durch das Aufrunden mit TL0++; wird also vermieden, dass trotz nahezu gleicher Bitdauer die Baudratenerkennung abgebrochen wird.
Soviel dazu.PS: Inzwischen kann ich auch schon mit Capture / (Auto-)Reload ein klein wenig was anfangen.