Ich meine es sollte möglich sein, die Baudrate auf der Controllerseite anhand der Emfangenen Bytes nachzuregeln. Speziell in meinem Fall: An der Gegenstelle sind 9600 ,8,n,1 fest vorgegeben. Es kommen nur Druckbare Zeichen in Frage. Ein Kommando (Payload) besteht aus einem Buchstaben und zwei Ziffern, wobei ich Große oder kleine Buchstaben festlegen könnte. Überlegung: Wenn nicht mehr als die untersten 6 bits (zB. Ziffern'0'-'9') benötigt würden, könnte man einfach das 7. und 8. Bit testen: if ( 8.bit gesetzt ) //Stopbit als 8. Bit erkannt Baudrate ++ else if (7.bit gesetzt) // 6. Bit (der Ziffer) als 7. Bit erkannt Baudraute -- Speziell bei mir (zwei Ziffern, ein Buchstabe) dann so: if ( 8.bit gesetzt ) //Stopbit als 8. Bit erkannt Baudrate ++ else if (7.bit mind. 2 x hintereinander gesetzt) // 6. Bit als 7. Bit erkannt Baudraute -- Für einen Atmega8 mit 8MHz und PC Terminal bei ~20° habe ich einfach mal verschiedene VCC von 2,8 V bis 5,5V durchprobiert und konnte durch (hardkodierte) Variation von BAUD_DELTA (-1 .. +1 ) immer stabil kommunizieren: #define BAUD 9600 #define BAUD_DELTA (-1) #define MYUBRR (F_CPU/16/BAUD-1 + BAUD_DELTA) void Init_USART( ) { UBRRH = (unsigned char)(MYUBRR>>8); UBRRL = (unsigned char) MYUBRR ; Liege ich da falsch mit meinen Überlegungen? Wie würdet ihr Nachregeln? OSCCAL ändern? (Oscillator Calib Value) UBRRH UBRRL ändern? (Baudrate) Noch andere Ideen? Wie kann man am sichersten sein, überhaupt die Bytes zu bekommen, also nicht eventuell vom UART verworfen werden? Schiko
Hmm ..... Ich würde mir einen LogigAnalyser, oder Ossi, oder Frequenzzähler schnappen und anhand dessen den Takt kalibrieren. (wenn es denn unbedingt nötig ist) Fertig.
1. Ist ein externer "Baudratenquarz" zu teuer? 2. Es gibt Controller deren interne Taktquelle hinreichen exakt für UART sind.
Coder schrieb: > 1. Ist ein externer "Baudratenquarz" zu teuer? Wenn man ihn x-fach an gegebenen fertigen Platinen an MLF-Pads flicken müsste, ja. Und Platz ist Geld
Ulrich F. schrieb: > Ich würde mir einen LogigAnalyser, oder Ossi, oder Frequenzzähler > schnappen und anhand dessen den Takt kalibrieren. > (wenn es denn unbedingt nötig ist) Mir geht es nicht um eine Kommunikation unter Laborbedingungen, sondern darum, ob ein automatisches nachstellen des Taktes/Baudrate möglich ist.
Michael Schikora schrieb: > Wie würdet ihr Nachregeln? > OSCCAL ändern? (Oscillator Calib Value) VUSB regelt z.B. OSCCAL nach, um ein eigenes Quarz zu sparen. Klappt recht gut. Man könnte auch drüber nachdenken, den Kalibrierungswert anschließend ins EEPROM zu schreiben, damit man eine weitere Kalibrierung nur dann durchführen muss, wenn sich die Oszillatorfrequenz deutlich geändert hat.
Michael Schikora schrieb: > Wenn nicht mehr als die untersten 6 bits (zB. Ziffern'0'-'9') > benötigt würden, könnte man einfach das 7. und 8. Bit testen: Wenn die Signale sehr sauber sind (Flanken-Jitter deutlich unter ca. 1/16 Bit-Zeit) mag das funktionieren.
Michael Schikora schrieb: > Ich meine es sollte möglich sein, die Baudrate auf der > Controllerseite anhand der Emfangenen Bytes nachzuregeln Grundsätzlich eine nette Idee, aber du merkst eine Abweichung erst bei mehr als 5% (ein halbes Bit von ca. 10 Bit). Das scheint mir etwas grob und der Sicherheitsabstand bis zu falschen Datenbits ist minimal. > Wie würdet ihr Nachregeln? > OSCCAL ändern? (Oscillator Calib Value) > UBRRH > UBRRL ändern? (Baudrate) Natürlich OSCCAL, dafür ist das doch da, oder? Damit hättest du auch gleich genauere Frequenzen für Timer o.ä. und nicht nur für ein UART. > Noch andere Ideen? * Wenn sowieso zyklisch Daten ausgetauscht werden (also Timer-gesteuert), könnte man Nachrichten-Takt statt Bit-Takt verwenden. * Auf einem STM32 trimme ich den Oszillator mit dem 1Hz-Takt aus einem RTC-Chip. * Mit CAN geht es auf den ersten Blick garnicht, andererseits gibt es "Time-triggered communication". Was ist das? Würde es damit gehen? > Wie kann man am sichersten sein, überhaupt die Bytes zu bekommen, > also nicht eventuell vom UART verworfen werden? Solange die Baudraten nominell gleich sind, verwirft ein normales UART keine Daten. Ab mehr als der doppelten Sende-Baudrate kann das Startbit kürzer als ein halbes Bit erscheinen. Dann würde der Empfänger alle Bytes ignorieren, die als LSB eine 1 und nur einzelne 0-Bits haben. Aber selbst dann setzt ein gutes UART noch ein "Noise Flag". Zwei aufeinander folgende Nullen werden wieder als Startbit interpretiert. Coder schrieb: > Ist ein externer "Baudratenquarz" zu teuer? Erstens das, zweitens mechanisch empfindlich, drittens ein unnötiger Sender, viertens schlecht lötbar (oder zu groß). Es gibt aber inzwischen Keramik-Resonatoren mit 0.3% Gesamtfehler bis 125⁰C. Evt. sogar besser als 0.1% im Büro-Temperaturbereich.
Michael Schikora schrieb: > Wie kann man am sichersten sein, überhaupt die Bytes zu bekommen, > also nicht eventuell vom UART verworfen werden? Per soft-UART empfangen und bei Flankenwechsel (nach-)synchronisieren. Oder mit 8-facher Überabtastung RxD einlesen, speichern und anschließend auswerten.
Schaulus Tiger schrieb: > Solange die Baudraten nominell gleich sind, verwirft ein normales UART > keine Daten. ... Das ist hilfreich! > VUSB regelt z.B. OSCCAL nach, um ein eigenes Quarz zu sparen. Klappt recht gut. das macht auch Mut! "quasi" zyklisches Senden ist möglich. Ich vergaß: Soft-UART oder Flankenwechsel-Zeitmessungen kommen nicht in Betracht, da die Timer schon belegt sind. Danke zusammen!
Mechanisch empfindlich auch nicht schlecht LOL
Coder schrieb: > Mechanisch empfindlich auch nicht schlecht LOL Wieso Lol? Das ist ein bekanntes Problem in mobilen Geräten, denn ein Quarz ist nun mal ein mechanisches Gebilde. Wenn der runterfällt und einige g aufnehmen muss, geht er kaputt. Nicht umsonst geben Quarzhersteller maximale Beschleunigungen an, denen man ihr Produkt aussetzen kann. Hatte ich schon sehr oft in Fernbedienungen und portablen Funkgeräten als Fehler. Resonatoren, Quarzfilter und Quarze gehen durchaus kaputt.
Also zumindest ein einmaliges Justieren muss sein, denn auch wenn der µC erst mal scheinbar einwandfrei läuft, so kann die Temperaturdrift den leicht aus dem Toleranzbereich bringen. Ich würde das über die Framing-Fehler machen. Die sagen Dir schon ob Dein Byte "richtig" lang war oder nicht. Oder, wenn das das Gesamtkonzept das her gibt, übertrage regelmäßig eine Zeit. Lass dann lokal auf dem µC auch eine Uhr mit laufen, und regle durch den Zeitunterschied die Frequenz nach.
Michael Schikora schrieb: > Ich meine es sollte möglich sein, die Baudrate auf der > Controllerseite anhand der Emfangenen Bytes nachzuregeln. Ist es definitiv. > Speziell in meinem Fall: > > An der Gegenstelle sind > 9600 ,8,n,1 > fest vorgegeben. Dann ist es ganz besonders simpel. Es geht aber auch autobaud und autotune kombiniert. Dann ist allerdings für eine schnelle und wirklich zuverlässige Erkennung die Mitarbeit des Senders gefragt, der muss eine Weile ein brauchbares Sync-Muster aussenden. Aber wie schon gesagt: dein Fall mit bekannter Senderbitrate und ebenfalls bekanntem Frameformat ist vergleichsweise simpel zu lösen. > Es kommen nur Druckbare Zeichen in Frage. Damit wird es nochmal merklich einfacher. > Überlegung: [...] Ungünstig, denn da schlägt Shannon/Nyquist gnadenlos zu. Zum Messen mußt du mindestens doppelt so schnell abtasten wie das Signal ist. Natürlich kann man das Schieberegister der UART auch zum Messen gebrauchen, aber nicht so, wie du dir das vorstellst. > Wie würdet ihr Nachregeln? > OSCCAL ändern? (Oscillator Calib Value) Natürlich. > UBRRH > UBRRL ändern? (Baudrate) Nicht, wenn (wie in deinem Fall) von vornherein bekannt ist, was zu empfangen sein sollte. > Wie kann man am sichersten sein, überhaupt die Bytes zu bekommen, > also nicht eventuell vom UART verworfen werden? Die UART-Hardware ist stockedoof, die verwirft garnix. Auch wenn das Statusregister FE (oder ggf. auch UPE) meldet: UDR liefert trotzdem getreulich die Signal-Aufzeichnung des Schieberegisters.
Ich habe einfach mal OSCCAL durchincrementiert und bei jeder Spannung zwischen 3V und 5V5 immer einen Bereich von ca. 20 OSCCAL-Werten gehabt, bei denen die Kommunikation stabil war. AB ursprünglich ab Werk 9E..B3 bei 5v5 AC..BF bei 3v6 B0..C4 bei 3v0
1 | uint8_t g_nLastSerIn = 0; |
2 | void CheckBaudAndCorrectIt( uint8_t ch ) |
3 | {
|
4 | if( ch & 0x80 ) //Bit 7 muss 0 sein |
5 | IncOSCCAL(); |
6 | else if( (ch & 0x40) && (g_nLastSerIn & 0x40) )// 2 x keine Ziffer |
7 | DecOSCCAL(); |
8 | g_nLastSerIn = ch; |
9 | }
|
Inc/DecOSCAL ändert daher gleich 10 Schritte (max. +/-20 vom Startwert) Lässt sich schön testen und verstellen mit dem Terminal. Spätestens bei der zweiten Ziffer ist die Kommunikation wieder OK :) Damit kann ich wohl gut leben. Danke für die Hints! Schiko
Hallo! Siehe ATMEL Application Note: "AVR054: Run-time calibration of the internal RC oscillator"
Route 66 schrieb: > Hallo! > Siehe ATMEL Application Note: > "AVR054: Run-time calibration of the internal RC > oscillator" Das ist nicht schlecht beschrieben! Danke ..kommt nur bei mir nicht zum Einsatz, da alle Timer belegt sind. Da wird es ja fast schon generell überflüssig, für Frequenzen bis ~8MHz einen Quarz einzuplanen, wenn er nur wegen des UART Not täte.
Michael Schikora schrieb: > Ich habe einfach mal OSCCAL durchincrementiert und bei jeder > Spannung zwischen 3V und 5V5 immer einen Bereich von ca. 20 > OSCCAL-Werten gehabt, bei denen die Kommunikation stabil war. nicht übersehen: über die Spannung ändert sich die Frequenz bedeutend weniger als über die Temperatur
ohne Worte schrieb: > Michael Schikora schrieb: >> Ich habe einfach mal OSCCAL durchincrementiert und bei jeder >> Spannung zwischen 3V und 5V5 immer einen Bereich von ca. 20 >> OSCCAL-Werten gehabt, bei denen die Kommunikation stabil war. > > nicht übersehen: über die Spannung ändert sich die Frequenz bedeutend > weniger als über die Temperatur Lt. Datenblatt Mega8A für 8Mhz genau andersrum: ..zumindest wo es für mich interessant ist: 20°: bei 3V bis 5,5V => 7,3 bis 8,1 MHz 5V : bei 85°bis-40° => 7,7 bis 8,2 MHz Ich benötige normal 10°-30° max "nur" ~0° bis 50°, passt. Ich habe mich vorher mit OSCCAL nicht mehr beschäftigt, als dass ich wusste, dass es die Möglichkeit des Takt-Tunens gibt. Sehr "cool" finde ich, dass man den Takt ohne ext. Quarz bis auf 12MHz tunen kann. (hierzu finde ich nichts, was das verbietet)
> (hierzu finde ich nichts, was das verbietet)
Ich aber!
EEPROM und Flash schreiben wird/kann scheitern.
10% Abweichung sind erlaubt
12MHz sind ca 50% Abweichung (bei ursprünglichen 8MHz)
Schiko schrieb: > Lt. Datenblatt Mega8A für 8Mhz genau andersrum: > ..zumindest wo es für mich interessant ist: > 20°: bei 3V bis 5,5V => 7,3 bis 8,1 MHz > 5V : bei 85°bis-40° => 7,7 bis 8,2 MHz da muss man wohl für jeden Prozessor extra nachschauen: beim Mega88 z.B. > 20°: bei 3V bis 5V => 7,95 bis 8,08 MHz > 5V : bei 85°bis-40° => 7,8 bis 8,3 MHz die Temperaturabhängigkeit ist ähnlich, die Spannungsabhängigkeit ist hier aber deutlich kleiner
> da muss man wohl für jeden Prozessor extra nachschauen: [..]
jupp, ich denke, das ist immer so:
Vom Prinzip her ist immer alles erstaunlicherweise exakt gleich,
bis auf die Kleinigkeit, bei der man sich wirklich gaaaanz sicher ist
;-)
Folgende Lösung hab ich mal implementiert: Eine separate PC-Software nur für diesen Zweck sendet alle x millisekunden das Byte 0x80 an der serielen Schnittstelle, das gibt genau ein Rechteck mit 8 bit Länge. Das Gerät, unmittelbar nach dem Einschalten, überprüft für eine kurze Zeit ob an rx etwas anliegt das sich nur durch Vorhandensein obigen Signals erklären lässt, also eins von diesen: 0b00000000 0b10000000 0b11000000 0b11100000 0b11110000 0b11111000 etc.. Dann fährt es OSCCAL vom kleinsten bis zum grössten wert (Vorsicht, es gibt 2 Bereiche), notiert sich OSCCAL-Wert wenn zum ersten Mal statt 0b11000000 (wir sind noch zu langsam) ein 0b10000000 (wir sind richtig) empfangen wird, dann erhöht es OSCCAL weiter bis zum ersten mal statt 0b10000000 ein 0b00000000 (jetzt sind wir zu schnell) empfangen wird und bildet dann den Mittelwert. Das wird dann ins OSCCAL geschrieben und auch im EEPROM gespeichert. Wenn beim Einschalten nicht nach ein paar dutzend Millisekunden das obige Kalibriersignal erkannt wird dann wird der Wert aus dem EEPROM ins OSCCAL geschrieben und das Gerät startet normal. So musste ich nicht das Protokoll ändern, hab keine abenteuerliche Autobaud-Erkennung die zur Laufzeit komische Sachen machen könnte, brauch keine spezielle Hardware zum Kalibrieren, es wird nur einmal durchgeführt ganz am Anfang nachdem das Gerät das Licht der Welt erblickt hat und dann nie wieder, es sei denn man hat den vagen Verdacht es wäre nicht ordentlich kalibriert, dann wirds nochmal da drangehängt und einmal kurz aus- und eingeschaltet.
:
Bearbeitet durch User
Schiko schrieb: > ..kommt nur bei mir nicht zum Einsatz, da alle Timer belegt sind. Natürlich hast du zumindest insofern Recht: Das Problem erfordert überhaupt keinen zusätzlichen Timer. Die wegen der Baudraten-Abweichung sowieso disfunktionale UART kann aber nicht nur Messungen machen, sondern auch als Timer dienen und sie kann das beides sogar gleichzeitig leisten. Es bedarf nur eines kompetenten Programmierers, der diese latenten UART-Fähigkeiten dazu nutzt, den eingehenden Scheiß zu vermessen und den Systemtakt per OSCCAL-Manipulation soweit anzupassen, daß die UART wieder so genutzt werden kann, wie Gott/Atmel es eigentlich beabsichtigt hat... Die Fähigkeit, sowas umzusetzen, ist wohl genau das, was C&P-"Programmierer" von denen unterscheidet, die das Attribut "Programmierer" wirklich verdienen...
Ulrich F. schrieb: >> (hierzu finde ich nichts, was das verbietet) > Ich aber! > EEPROM und Flash schreiben wird/kann scheitern. > 10% Abweichung sind erlaubt > > 12MHz sind ca 50% Abweichung (bei ursprünglichen 8MHz) Ei der Daus! Beim Nachlesen gleich noch ein Fehler meiner Überlegung gefunden: Es wird ja IMMER in OSCCAL der Wert für 1 MHz geladen, egal was man in den Fuses für einen Takt eingestellt hat! Die vorgeschlagene Prozedur um an die Kalibrierwerte für 2,4 u. 8 MHz zu kommen, ist ja fürchterlich. (Per Programmer lesen, dann ins Flash oder EEPROM schreiben..)
Bernd K. schrieb: > Folgende Lösung hab ich mal implementiert: > Eine separate PC-Software nur für diesen Zweck sendet alle x > millisekunden das Byte 0x80 an der serielen Schnittstelle [..] ..die Idee finde ich auch nicht schlecht. Hmm.. für Codepage-Unabhängigkeit mit 'nem Terminal könnte man auch das '?' nehmen das Bit 0 und 7 ignorieren und für die Auswertung die beiden Übergänge beim Wechsel zwischen den 3 hohen Bits nehmen. 1. Übergang von (0x7E & UBR) == 0x1E --> (0x7E & UBR) == 0x3E 2. Übergang von (0x7E & UBR) == 0x3E --> (0x7E & UBR) == 0x7E Wenn ansonsten '~' '>' und 0x1E nicht im Protokoll vorkommen, könnte jederzeit mit dem Finger auf '?' "nachgetunet" werden.
c-hater schrieb: > Schiko schrieb: > >> ..kommt nur bei mir nicht zum Einsatz, da alle Timer belegt sind. > > Natürlich hast du zumindest insofern Recht: Das Problem erfordert > überhaupt keinen zusätzlichen Timer. > > Die [..] UART kann aber > nicht nur Messungen machen, sondern auch als Timer dienen sogar ohne Gegenstelle bei Verwendung des Transmit-Complete-Interrupts :) > Die Fähigkeit, sowas umzusetzen, ist wohl genau das, was > C&P-"Programmierer" von denen unterscheidet, die das Attribut > "Programmierer" wirklich verdienen... Bei sowas bin ich vorsichtig. "Gut" Kopiert ist schließlich besser, als ein krummes Rad neu zu erfinden. Man muss nur genau wissen, was man kopiert.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.