Mit folgendem Code probiere ich eine Serielle Datenübertragung.
Schon mit 115'000 Baud gibt es beim Einlesen ab und zu einen Abreisser,
schreiben geht fehlerfrei. Aber will ich mit 1'000'000Bad übertragen,
scheint es gar nicht zu funktionieren.
Dann klappt die Übertragung fehlerfrei.
Was mache ich mit den direkten Registerbefehlen falsch ?
Ich wies nicht ob es relevant ist, der I²C-Bus wird auch benutzt.
Jim M. schrieb:> Deine Baudratenberechnung stimmt nicht. Mit U2X0=0 ist der Teiler> 16 und> nicht 2, d.h. UBRR0L und UBRR0H sind jeweils im Ergebnis null.
Und was muss ich das ändern ?
Nico W. schrieb:> Mathias schrieb:>>> Mit U2X0=0 ist der Teiler 16 und>>> nicht 2, d.h. UBRR0L und UBRR0H sind jeweils im Ergebnis null.>> Und was muss ich das ändern ?>> Hat er direkt geschrieben. UBRR0L/H = 0>> Und eben auch UCSR0A = 0.>> Kannst dir den Zauber auch hier mal ansehen.> https://github.com/Traumflug/Teacup_Firmware/blob/...
Ich habe nun folgendes probiert, geht aber nicht, auch nicht mit 115200
Baud.
1
voidInit_UART(unsignedlongbaud){
2
3
UCSR0A=(1<<U2X0);
4
UBRR0=(((F_CPU/8)/baud)-0.5);
5
6
UCSR0B=(1<<RXEN0)|(1<<TXEN0);
7
UCSR0C=(1<<UCSZ01)|(1<<UCSZ00);
8
9
UCSR0B|=(1<<RXCIE0)|(1<<UDRIE0);
10
}
>Mathias schrieb:>> Aber will ich mit 1'000'000Bad übertragen,>>Bei 16 MeV wird das nichts im Bad.>>Mal sehen
Irgendwie muss es gehen, ansonsten würde es mit den Arduino-Befehlen
Serial.begin auch nicht gehen.
Hi
>Irgendwie muss es gehen, ansonsten würde es mit den Arduino-Befehlen>Serial.begin auch nicht gehen.
Ich würde einfach mal das Datenblatt vom ATMega lesen. Da steht alles
drin.
MfG Spess
Da sind sowohl BAUD als auch F_CPU direkte numerische Konstanten, die
per #define im Präprozessor ersetzt werden. Damit wird die Konstante für
UBRR0 zur Compilezeit berechnet, nicht zur Laufzeit. Das macht den
Unterschied.
C sollte man schon können.
fchk
Frank K. schrieb:> C sollte man schon können.
Datenblatt lesen kann auch helfen. Da steht immerhin auch drin wie man
den UART für 1 Mbps einstellen muss bei 16 MHz Systemtakt ;)
Rene K. schrieb:> M. K. schrieb:>> den UART für 1 Mbps einstellen>> Nur so als Hinweis: die richtige Definition ist: 1 MBd :-)
Nur so als Hinweis: Hab ich "Baud" gemeint oder "bits per second"? ;)
M. K. schrieb:> Nur so als Hinweis: Hab ich "Baud" gemeint oder "bits per second"? ;)
Na eine Datenübertragung über eine Modulation gibt man ja in den
seltensten Fällen als "bits per second" an ;-) Das ist sehr untypisch.
Und wenn dann wenigstens als "bMbps".
Frank K. schrieb:> ...>> UBRR0 = (((F_CPU / 8) / BAUD) - 0.5);> ...> Da sind sowohl BAUD als auch F_CPU direkte numerische Konstanten, die> per #define im Präprozessor ersetzt werden. Damit wird die Konstante für> UBRR0 zur Compilezeit berechnet, nicht zur Laufzeit. Das macht den> Unterschied.
Mich würde schon diese Float-Konstante mitten in der Ganzzahl-Rechnung
stutzig machen.
> Die hat mich auch etwas verwundert, dies habe ich beim obige, Link> https://github.com/Traumflug/Teacup_Firmware/blob/master/serial-avr.c> abgeguckt.
Was erwartest du - ...\Traumflug\... eben ...
Rene K. schrieb:> M. K. schrieb:>> Nur so als Hinweis: Hab ich "Baud" gemeint oder "bits per second"? ;)>> Na eine Datenübertragung über eine Modulation gibt man ja in den> seltensten Fällen als "bits per second" an ;-) Das ist sehr untypisch.> Und wenn dann wenigstens als "bMbps".
Noch ein Hinweis: Schau ins Datenblatt eines AVRs, z.B. dem vom
Atemga328p ;)
Übrigens: Mein LAN-Port hier am Rechner wird auch mit 1 Gbps angegeben.
Bei meinem DSL heißt es auch "bits per second". Soso selten erscheint
mir die Angabe also mal überhaupt nicht. ;)
Ganz Zahl schrieb:> Mich würde schon diese Float-Konstante mitten in der Ganzzahl-Rechnung> stutzig machen.
Ich glaub, die ist nur fürs Runden drin damit der "Fehler" später unter
ein Prozent oder so bleibt. Ich kenn das aber auch gesamt nur als
Makro-Funktion welche später in einen Error läuft wenn der Fehler auf
über ein Prozent ansteigt.
Mathias schrieb:> UBRR0 = (((F_CPU / 8) / baud) - 0.5);
Der Compiler rechnet mit Integer, wenn er keine andere Anweisung
bekommt. Zwinge ihn, mit long zu rechnen und lass die 0.5 weg.
Beispiel: (F_CPU/(baud*8l)-1)
Mathias schrieb:> Schon mit 115'000 Baud gibt es beim Einlesen ab und zu einen Abreisser
In welcher Form? Keine Zeichen, zu wenige, falsche?
> Ich wies nicht ob es relevant ist, der I²C-Bus wird auch benutzt.
Aber nicht im geposteten Programm...
Mach doch einfach mal einen Drei nur mit der seriellen Schnitte. Wenn
das auch nicht geht, dann hast du einen Fehler dort drin. Wenn es dann
aber geht, dann hast du einen Fehler anderswo...
Ich nehme an, dass das Programm Timing-Probleme hat. Bei 16MHz und
1MBit/s hat man nur 160 Takte pro Zeichen. Da muss man die
Einlese-Routine gut optimieren, sonst geht's nicht. Interrupts in der
Zeit sind auch tabu.
Mathias schrieb:> Nehme ich aber die original Arduino Befehle> ...> Dann klappt die Übertragung fehlerfrei.> Was mache ich mit den direkten Registerbefehlen falsch ?
Könnte es sein, daß die Arduino-Variante interruptgesteuert arbeitet?
Deine "direkten Registerbefehle" arbeiten mit polling, d.h. Du musst
ständig aktiv nachsehen, ob Zeichen gekommen sind.
>Könnte es sein, daß die Arduino-Variante interruptgesteuert arbeitet?
Sieht fast so aus. Wen ich die Source von Arduino angucke, steht immer
was von Puffer, einen Ausschnitt von HardwareSerial.cpp.
1
intHardwareSerial::read(void)
2
{
3
// if the head isn't ahead of the tail, we don't have any characters
Lothar M. schrieb:> Mathias schrieb:>> Schon mit 115'000 Baud gibt es beim Einlesen ab und zu einen Abreisser> In welcher Form? Keine Zeichen, zu wenige, falsche?
Schreiben geht, aber beim Lesen gibt es Fehler (falsche Werte).
>> Ich wies nicht ob es relevant ist, der I²C-Bus wird auch benutzt.> Aber nicht im geposteten Programm...> Mach doch einfach mal einen Drei nur mit der seriellen Schnitte. Wenn> das auch nicht geht, dann hast du einen Fehler dort drin. Wenn es dann> aber geht, dann hast du einen Fehler anderswo...
Dies müsste ich mal probieren.
Mathias schrieb:>>> Ich wies nicht ob es relevant ist, der I²C-Bus wird auch benutzt.>> Aber nicht im geposteten Programm...>> Mach doch einfach mal einen Drei nur mit der seriellen Schnitte. Wenn>> das auch nicht geht, dann hast du einen Fehler dort drin. Wenn es dann>> aber geht, dann hast du einen Fehler anderswo...> Dies müsste ich mal probieren.
Habe dies unterdessen probiert, aber geholfen hat es nicht.
Mathias schrieb:> Habe dies unterdessen probiert, aber geholfen hat es nicht.
Mit welchem Programm hast du es probiert? Was hast du probiert? Was hast
du dabei erwartet und was ist stattdessen passiert?
Mathias schrieb:> Schreiben geht, aber beim Lesen gibt es Fehler (falsche Werte).
Von Anfang an jedes Zeichen falsch?
Welche Zeichen erhältst du statt welcher Zeichen?
Was passiert, wenn du einmal oder dauernd 'a' an den µC schickst?
Bekommst du dann dauernd das selbe falsche Zeichen? Wenn ja welches?
Was, wenn du dauernd 'b' sendest?
Was bei 'c', was bei 'z'?
Wie sendest du die Zeichen an den µC? Als einzelne Zeichen mit einem
Terminalprogramm über die Tastatur? Oder als String mit 20 Zeichen
direkt hintereinander?
BTW: hast du ein Oszilloskop um mal die Bitdauer auszumessen?
Mathias schrieb:>> Könnte es sein, daß die Arduino-Variante interruptgesteuert arbeitet?>> Sieht fast so aus.
Na, das zusammen mit
> Schreiben geht, aber beim Lesen gibt es Fehler (falsche Werte).
sollte doch Klarheit bringen.
Du kannst nur Zeichen empfangen, solange Du Deine Read_UART-Funktion
aufrufst. Da Du aber noch anderes machst, bist Du in dieser Zwischenzeit
"taub". Ein zwischenzeitlich ankommendes Zeichen wird noch von der
UART-Hardware entgegengenommen, jedes weitere verschwindet aber im
Orkus.
Du müsstest also Deine zwischen den Read_UART-Aufrufen unternommenen
Aktivitäven massiv verkürzen, oder die Funktion ständig und immer wieder
aufrufen (nur was machst Du dann mit den Zeichen, die Du in diesem
Moment gar nicht gebrauchen kannst?).
Prinzipiell ist zwar Dein Programm schnell genug, aber die Datenrate,
mit der es empfangen kann, schwankt während der Laufzeit sehr stark, und
dadurch gehen Daten verloren.
Der interruptgesteuerte Empfang nimmt Dir dieses Problem ab. Der kann
quasiautark solange Zeichen empfangen, bis der Empfangspuffer voll ist.
Und Du kannst die aufgelaufenen Daten verarbeiten, ohne Dich um den
gleichzeitig stattfindenden Empfang weiterer Daten kümmern zu müssen.
Probleme gibt es nur dann, wenn Dein Programm insgesamt zu langsam wird,
d.h. wenn ein Auswertungsvorgang eines Datenblocks/Telegramms/Befehls
länger dauert als der zeitliche Abstand zweier aufeinanderfolgender
Datenblöcke/Telegramme/Befehle.
M. K. schrieb:> Noch ein Hinweis: Schau ins Datenblatt eines AVRs, z.B. dem vom> Atemga328p ;)
Unabhängig davon was darin steht, ist 1MBd/s die richtige Einheit.
Übertragen werden tatsächlich nur max. 800kb/s.
> Übrigens: Mein LAN-Port hier am Rechner wird auch mit 1 Gbps angegeben.
Weil hier die Datenrate abgegeben wird und eben nicht die Symbolrate.
Die liegt nämlich bei Gigabit Ethernet (so wie übrigens auch bei fast
Ethernet) bei 125MBd/s.
avr schrieb:> Unabhängig davon was darin steht, ist 1MBd/s die richtige Einheit.
Nö, Baud enthält schon "pro Sekunde".
1 MBd/s wäre die Beschleunigung einer Datenrate ...
avr schrieb:> Unabhängig davon was darin steht, ist 1MBd/s die richtige Einheit.> Übertragen werden tatsächlich nur max. 800kb/s.
Da beim Atmega die Symbolrate == Datenübertragungsrate ist, kann man 1
MBd schreiben oder eben 1 Mbps. Da gibts eben nicht "die richtige
Einheit".
Und wie kommst du denn auf die maximal 800 kb/s? Das wäre jetzt mal
spannend.
avr schrieb:> Weil hier die Datenrate abgegeben wird und eben nicht die Symbolrate.
Das ist mir bewusst. Preisfrage: Was hatte ich angegeben? ;)
> Die liegt nämlich bei Gigabit Ethernet (so wie übrigens auch bei fast> Ethernet) bei 125MBd/s.
Wie kommst du denn jetzt darauf? Fast Ethernet hat eine
Datenübertragungsrate von 100 Mbps, Gigabit Ethernet hat eine
Datenübertragungsrate von 1000 Mbps. Hätten beide dieselbe Symbolrate,
warum hätte man denn da 1000 Mbps erfinden sollen? Oder anders gefragt:
Warum sollte beim Gigabit-Ethernet Symbole 10 mal mehr an Bits benötigen
als beim Fast-Ethernet? Oder mixt du jetzt hier verschieden Symbole und
vergleichst dann?
M. K. schrieb:> Und wie kommst du denn auf die maximal 800 kb/s? Das wäre jetzt mal> spannend.
Was sind Start- und Stopbits, und welchen Rolle spielen sie bei einer
asynchronen seriellen Datenübertragung?
Rufus Τ. F. schrieb:> Was sind Start- und Stopbits, und welchen Rolle spielen sie bei einer> asynchronen seriellen Datenübertragung?
Start- & und Stoppbits gehören zur Datenübertragung, auch wenn sie zur
Information, die übertragen werden soll, keine Rolle spielen, zur
Datenübertragungsrate gehören sie.
Na, dann hast Du Dir Deine Frage ja schon selbst beantwortet.
Eine mit 1 MBaud betriebene UART überträgt maximal 800 kByte/sec an
Nutzdaten. Bei der asynchronen Datenübertragung mit UARTs werden
Start-/Stop- und auch weitere Bits (Parity) bei Bit- und
Baudratenbetrachtungen mitgezählt. Bei 8n1 werden für jedes Nutzbyte
also 10 Bit übertragen.
Rufus Τ. F. schrieb:> Eine mit 1 MBaud betriebene UART überträgt maximal 800 kByte/sec an> Nutzdaten.
Wir reden hier die ganze Zeit von der Datenübertragungsrate des UART,
von der Nutzdatenrate war bisher nie die Rede. In der Regel meint man
beim UART auch nie die Nutzdatenrate wenn man von der Datenrate des UART
spricht. Das sollte man dann vielleicht dazu sagen ;)
M. K. schrieb:> Fast Ethernet hat eine> Datenübertragungsrate von 100 Mbps, Gigabit Ethernet hat eine> Datenübertragungsrate von 1000 Mbps.
Ja.
> Hätten beide dieselbe Symbolrate,
Gigabit Ethernet: 125 MBaud, 2 Bit pro Symbol, 4 Adernpaare
(bidirektional genutzt).
Fast Ethernet: 125 MBaud, 4 Bit pro 5 Symbole, 1 Adernpaar (pro
Richtung).
Rufus Τ. F. schrieb:> Eine mit 1 MBaud betriebene UART überträgt maximal 800 kByte/sec an> Nutzdaten.
Ich komme bei 8N1 auf maximal 100 kByte/s.
Wie auch immer: 1 MBd zu empfangen ist für einen AVR grenzwertig hoch.
Da sind unter realen Bedingungen (weitere aktive ISRs)
Übertragungsfehler vorprogrammiert - egal welche Schreibweise man
vorzieht ;-)
M. K. schrieb:> Wir reden hier die ganze Zeit von der Datenübertragungsrate des UART,> von der Nutzdatenrate war bisher nie die Rede.
Natürlich war davon die Rede:
M. K. schrieb:> avr schrieb:>> Übertragen werden tatsächlich nur max. 800kb/s.>> Und wie kommst du denn auf die maximal 800 kb/s? Das wäre jetzt mal> spannend.
Rufus Τ. F. schrieb:> Natürlich war davon die Rede:
Die 800 kb/s hat heute mittag erst air ins Rennen gebracht, davor hat
die keiner erwähnt. Da wurde ständig von der Datenübertragungsrate
gesprochen und nie von der Nutzdatenrate. Die ist in diesem Fall ja auch
maximal uninteressant.
M. K. schrieb:> Die 800 kb/s hat heute mittag erst air ins Rennen gebracht, davor hat> die keiner erwähnt. Da wurde ständig von der Datenübertragungsrate> gesprochen und nie von der Nutzdatenrate. Die ist in diesem Fall ja auch> maximal uninteressant.
Ich wollte dich eigentlich darauf hinweisen, dass du Begriffe und
Einheiten verwechselst, bzw. falsch verwendest.
Die Datenübertragungsrate bei einem 1MBd Uart beträgt max. 800kb/s.
Start- und Stopp-Bits sind, auch wenn sie leider so genannt werden,
keine richtigen Bits. Sie enthalten keinerlei Information. Du kannst mit
einem 1MBd Uart eben keine 1Mb/s übertragen.
Wenn du von den 8 Datenbits/UART-Frame eines als Parity-Bit nutzt, dann
überträgst du immernoch 800kbit/s. Die Nutzdatenrate beträgt aber nur
noch 700kbit/s.
Was dich interessiert, ist die Symbolrate - also wie viele Symbole pro
Sekunde übertragen werden. Beim UART gibt es nur 2 Symbole, welche
Datenbits, Start oder Stopp-Bits sein können. Genau die Symbolrate musst
du durch die Register einstellen. Und die Einheit der Symbolrate ist
nunmal Baud.
avr schrieb:> Die Datenübertragungsrate bei einem 1MBd Uart beträgt max. 800kb/s.> Start- und Stopp-Bits sind, auch wenn sie leider so genannt werden,> keine richtigen Bits. Sie enthalten keinerlei Information. Du kannst mit> einem 1MBd Uart eben keine 1Mb/s übertragen.
Ich versuch das mal aufzudröseln: 1 MBd sind 1 Million Zeichen pro
Sekunde. Damit sind dann nur 800 kb/s möglich. OK. Jetzt spanne ich nur
mal den Bogen zurück zum Beginn der Diskussion: Im Datenblatt steht aber
nicht 800 kb/s und auch nicht 1 MBd. Nein, da stehen 1 Mbps. Nichts mit
Baud oder ähnlichem. Rechnen wir das auf Baud um sind wir hier bei 1.2
MBd.
Falsch ist das aber immer noch.
Die Baudrate, oder auch Symbolrate, gibt per Definition an, wie oft sich
auf einem Kanal in einer Sekunde, der Zustand ändern kann.
Die Bitrate, oder auch Datenübertragungsrate, gibt an, wie viele Bits
(ganz egal ob Overhead ist oder Nutzdaten) in einer Sekunde auf einem
Kanal übertragen werden können.
Auch wenns nicht gefällt, auch ein Start- und Stoppbit müssen übertragen
werden, diese auszusparen ist schlichtweg falsch. Daher ist beim Uart
der Sonderfall, dass Baud- und Bitrate identisch ist. Und das kann man
auch überall im Netz bzw. in entsprechender Literatur nachlesen wenn man
ambitioniert ist. Zum Beispiel hier, was wohl zu den ersten Treffern bei
Google gehören dürfte:
https://de.wikipedia.org/wiki/Universal_Asynchronous_Receiver_Transmitter
Rufus Τ. F. schrieb:> Eine mit 1 MBaud betriebene UART überträgt maximal 800 kByte/sec an> Nutzdaten.
Ich muss mich korrigieren. Es sind natürlich nicht 800 kByte/sec,
sondern es sind 80 kByte/sec.