Hallo! Ich habe vor Messwerte vom Mikrocontroller (STM32) über die USB 2.0 Schnittstelle an den PC zu senden. So weit funktioniert auch alles, aber nun versuche die Geschwindigkeit etwas zu erhöhen. Der Sendecode sieht zur Zeit so aus: SendByte(b); b++; waitMs(1000); Es werden also zyklisch die Zahlen von 0 bis 255 an den PC gesendet, jeweils im Sekundentakt. Empfangen wird das ganze über ein Terminal Programm (Stichwort virtueller COM Port). Wenn ich nun die Sendegeschwindigkeit erhöhe, kann ich bis zu 1ms delay runtergehen. Kleinere Werte sorgen dann dafür, dass nicht mehr alle Zahlen ankommen (es fehlen zwischendurch einfach welche). Nun mein Frage: Woran könnte das liegen? Es kann ja nicht sein, dass ein USB 2.0 nur 1000 Byte pro Sekunde schafft, oder? Das Ding ist ja eigentlich bis 480 MBit spezifiziert, wenn ich mich recht erinnere... Gruß, Boris
Ich kenne deinen Mikrocontroller jetzt nicht genau, aber die 450 MBit sind lediglich die theoretisch höchste Datenrate, die mit USB 2.0 erreicht werden kann. Das heißt jedoch nicht, dass dein Mikrocontroller diese Geschwindigkeit auch wirklich erreichen kann! Mal als Anregung (ich bin mir nicht ganz sicher, ob das geht): Vielleicht kannst anstatt immer genau eine festgelegte Zeit zu warten, solange warten, wie der Mikrocontroller zum übertragen eines Bytes benötigt. Evtl. wird bei deinem Mikrocontroller dann ein Flag gesetzt, das anzeigt, ob er noch am senden ist. Das müsste man allerdings im Datenblatt mal recherchieren.
Meines Wissens nach ist es ziemlich unsinnig per USB einzelne Bytes zu übertragen. Der STM müsste eigentlich intern einen Buffer haben (512 Byte?). Es sollte sinnvoller sein erst diesen Buffer zu füllen und dann am Stück zu senden
Aber USB ist doch eine serielle Schnittstelle. Da sollte es doch keinen unterschied machen, ob die Daten aus dem Buffer seriell weggesendet werden, oder ob ich manuell in meiner Schleife seriell sende?
Boris B. schrieb: > Woran könnte das liegen? Es kann ja nicht sein, dass ein USB 2.0 nur > 1000 Byte pro Sekunde schafft, oder? Das Ding ist ja eigentlich bis 480 > MBit spezifiziert, wenn ich mich recht erinnere... USB 2.0 kann 480MBit. Das heisst aber nicht das das Gerät das auch macht. Ich bin zwar kein Experte für die STM32, aber soweit ich weiss kann der (wie glaub ich alle Cortex M3) nur Full-Speed, also 12 MBit.
Außerdem ist das Protokoll bei USB paket-orientiert. Wenn du nur ein Byte schickst, ist das total ineffizient. Sinnvollerweise sollte man einen ganzen Block in der Größe des Endpoint Buffers schicken. Bei USB 2.0 HighSpeed erreicht man die maximale Geschwindigkeit von etwa 40MB/s im BULK Modus nur, wenn man immer die Pakete voll ausnutzt (512 Byte) und so schnell anliefern kann, dass der Controller einen Microframe mit 10 bis 11 vollen Paketen voll packen kann. Bei 10 Paketen zu je 512 Byte pro MicroFrame erreicht man 512 x 10 x 8000 = 40960000 Byte/s Datendurchsatz. Mit schnellen Controllern wie z.B. dem Cypress FX2 ist das zu schaffen. Der FT2232H kann das wohl mit aktuellem Treiber mittlerweile auch.
> Außerdem ist das Protokoll bei USB paket-orientiert. Wenn du nur ein > > Byte schickst, ist das total ineffizient. Genau so schaut es aus, was du zur Zeit machst ist für jedes einzelne Byte ein eigenes Datenpaket zu schnüren mit entsprechendem overhead! Du solltest die Größe deines Endpoint-Buffers ausnutzen und dann erst senden. Aber warum verwendest du überhaupt ein Delay? Frage doch die entsprechenden Flags ab oder nutze wenn es das gibt entsprechende Interrupts, wenn die Buffer wieder frei sind. Damit bist du auch an der max. Geschwindigkeit und musst nicht ausprobieren wie weit du mit deinem Delay runter kannst.
USB ist nicht einfach eine serielle Schnittstelle. USB ist ein Bus mit vielen Teilnehmern und einem komplizierten Protokoll, das in 1-ms-Intervallen abläuft. Genau diese Intervallfrequenz hast Du soeben entdeckt (1 kHz). In diesem Abstand pollt, vereinfacht gesagt, der USB-Host seine Teilnehmer. Haben die dann nur 1 Byte abzuliefern, wird in einem Intervall nur dieses übertragen. Du hast noch ein Problem: Du sendest fortlaufende Byte-Werte und schreibst, dass bei Überschreitung der 1 kHz welche fehlen. In diesem Fall müsste aber Deine Senderoutine blockieren, bis sie ihr Byte losgeworden ist (und so den Durchsatz beschränken). Dass Werte verloren gehen, weil sie zu schnell kommen, darf in einer sauberen Senderoutine nicht passieren. Sie muss den Flaschenhals nach hinten durchreichen. Idealerweise würde die Senderoutine, wenn ein Byte noch nicht abgesendet ist und ein neues kommt, das Paket vergrößern. Kann sie das nicht, muss sie blockieren, um Datenverlust wie Deinen zu verhindern.
auf welche Geschwindigkeit hast Du denn überhaupt deinen COM Port eingestellt?
Danke für den vielen Input :-) Ihr habt da einige wichtige Aspekte aufgezeigt, die mir bisher nicht bewusst waren. Ich werde dann mal versuchen zu puffern und größere Pakete zu versenden. Warum die Senderoutine nicht blockiert, werde ich mir auch mal anschauen. @Michael: Der COM-Port steht momentan auf 115200 Baud. Das müsste ja eigentlich schnell genug sein... (~14.000 Byte/s?)
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.