Forum: Mikrocontroller und Digitale Elektronik STM32F103 Daten über CDC Device senden


von Sebastian V. (sebi_s)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche gerade auf meinem eigenen Board mit STM32F103C8 ein CDC 
Device ans laufen zu kriegen, um Daten mit dem PC auszutauschen. Nachdem 
ich mit den Dateien aus dem Beispielprojekt fürs STM3210E_EVAL Boards 
nichts geworden bin (Windows hat ein Virtual COM Port erkannt, aber die 
Treiberinstallation hing irgendwie in einer Endlosschleife fest) habe 
ich mit STMCube ein CDC Projekt erstellt und damit wird nun auch der 
Treiber richtig installiert. Mein Board wird nun als COM10 gelistet und 
ich kann das Device auch mit Putty öffnen.

Aber nun stellt sich mir die Frage wie ich nun Daten vom µc aus senden 
kann. Ich habe alle Header abgesucht aber keine passende Funktion 
gefunden. Ich glaube fast die ist noch nicht mal implementiert. Das 
einzige was nach was aussieht wäre vielleicht CDC_Transmit_FS aber die 
Implementierung ist selten dämlich:
1
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
2
{
3
  uint8_t result = USBD_OK;
4
  /* USER CODE BEGIN 8 */ 
5
  USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, Len);   
6
  result = USBD_CDC_TransmitPacket(hUsbDevice_0);
7
  /* USER CODE END 8 */ 
8
  return result;
9
}
Die Buf Variable wird dort überhaupt nicht benutzt! Ich habe mal 
UserTxBufferFS durch Buf ersetzt und versucht irgendwas zu senden aber 
wenn ich das mache dann wird die Platine nicht mal mehr richtig erkannt 
sondern als Unknown Device aufgeführt. Ich glaube das ist eher eine 
Low-Level Funktion und nicht um direkt Daten zu senden.

Ich habe mal die von STMCube generierten Dateien angehängt.

von Peter Z. (hangloose)


Lesenswert?

Google mal nach "cdc stm32 example"
Gleich der erste Treffer funktionierte bei mir auf Anhieb
bei meinem STM32F072Disco Board in Verbindung mit der Cube Init.

von Sebastian V. (sebi_s)


Lesenswert?

Meinst du wirklich dieses Ergebnis? 
http://visualgdb.com/tutorials/arm/stm32/usb/

Da steht immerhin schonmal ein wenig zu read und write Funktionen. Werde 
ich mal schauen ob das funktioniert.

von Peter Z. (hangloose)


Lesenswert?

Ja genau das meine ich...
und ja es funktioniert!

von Sebastian V. (sebi_s)


Lesenswert?

Ok jetzt läuft es. Das Problem war scheinbar, dass ich ~2 Sekunden 
warten muss bis Windows das USB Gerät komplett erkannt hat bevor ich 
Daten sende. Kann man irgendwie testen ob der Host bereit ist?

von Bernd K. (prof7bit)


Lesenswert?

Sebastian V. O. schrieb:
> Kann man irgendwie testen ob der Host bereit ist?

Das Device kann das nicht feststellen, wie auch? Lass es einfach 
eingestöpselt.

Oder sende nichts solange vom PC keine Anfrage nach Daten kommt.

Oder entwerfe das Protokoll so dass es keine Rolle spielt wenn man es 
zwischenzeitlich ab- und wieder anstöpselt, so daß der PC sich schnell 
wieder auf die ankommenden Daten synchronisieren kann und unvollständige 
Daten zu Beginn einfach verwirft. (Das solltest Du sowieso machen, sowas 
sollte immer so robust ausgelegt sein daß egal was auch passiert es 
immer irgendwie sinnvoll damit umgehen kann, sich von selbst wieder 
fängt, möglichst dem Nutzer keine Interaktion (sinnloses OK-Klicken) 
abverlangt wenn etwas passiert ist wovon es sich spielend leicht von 
selbst erholen kann und sich auch nicht anderweitig aufhängt).

von Sebastian V. (sebi_s)


Lesenswert?

Bernd K. schrieb:
> Das Device kann das nicht feststellen, wie auch? Lass es einfach
> eingestöpselt.

Das Device wird über USB mit Strom versorgt, ist also immer 
eingestöpselt. Ich würde da nur ungern ein HAL_Delay(2000); im Code 
stehen lassen. Anfangs brauche ich die USB Verbindung erstmal für Debug 
Ausgaben (richtiges UART wäre mir auch lieber aber gibt Pinmangel).

Ich könnte beim Einschalten natürlich solange warten bis vom PC 
irgendwas gesendet wird aber dann ist man gezwungen immer ein Terminal 
zu öffnen auch wenn einen die Debug Infos gerade nicht interessieren.

von Jim M. (turboj)


Lesenswert?

Bernd K. schrieb:
> Oder entwerfe das Protokoll so dass es keine Rolle spielt wenn man es
> zwischenzeitlich ab- und wieder anstöpselt, so daß der PC sich schnell
> wieder auf die ankommenden Daten synchronisieren kann

Hast das mal mit USB2Serial Wandlern gemacht? Dann wüsstest Du, dass das 
mit COM Ports nicht tut. Insbesondere, wenn die Applikation den Port 
nicht schnell genug zugemacht hat ist das Gerät beim neu anstecken nicht 
mehr benutzbar, weil der COM Port nicht mehr arbeitet. Ist AFAIK ein 
Namensproblem.

Das ist einer der Gründe, warum ich hier immer WinUSB oder LibUSB 
empfehle,
dort kann man das Neuverbinden in der App lösen. Außerdem braucht man 
nicht mehr die COM Portnummer aus der Registry rauszupfriemeln oder gar 
den Luser danach zu fragen.

von Sebastian V. (sebi_s)


Lesenswert?

Ja mit den USB to COM Adaptern oder CDC Devices ist schon nicht so 
super. Momentan aber die einzige Möglichkeit Debug Infos aus dem µC 
heraus zu kriegen. Irgendwas über WinUSB oder LibUSB ist mir gerade zu 
kompliziert. Ich würde nur gerne noch das Problem in den Griff kriegen, 
dass Windows das Device nicht richtig erkennt wenn zu früh Daten 
gesendet werden. Ich habe schon mit diversen AVRs (ATmega32U2, 
ATxmega128A1U) als CDC Device benutzt und dort hatte ich nicht das 
Problem. Das muss doch auch mit ARMs gehen.

von Bernd K. (prof7bit)


Lesenswert?

Sebastian V. O. schrieb:
> Das Device wird über USB mit Strom versorgt, ist also immer
> eingestöpselt.

Dann sollte doch auch der COM-Port im PC permanent vorhanden sein.

von Sebastian V. (sebi_s)


Lesenswert?

Schon. Nur die Frage ist was passiert wenn man das Gerät gerade 
einsteckt. Der µC wird mit Strom versorgt, gibt sich als CDC Device aus 
und startet dann seinen normalen Programmablauf. In der Zwischenzeit 
erkennt der PC gerade, dass ein neues USB Device angesteckt wurde. Nun 
scheint es allerdings ein Problem zu geben wenn der µC zu früh Daten 
sendet. Wobei zu früh heißt: Früher als 2 Sekunden nach dem Einstecken. 
Dann wird das Device vom PC entweder gar nicht mehr erkannt (Unkown 
Device) oder es lässt sich der COM Port nicht öffnen. Und das kanns 
meiner Meinung nach nicht sein. Die Nachrichten können gerne im Nirvana 
verschwinden aber darf nicht dafür sorgen, dass der PC das Device nicht 
mehr erkennt.

von W.S. (Gast)


Lesenswert?

Sebastian V. O. schrieb:
> Nun
> scheint es allerdings ein Problem zu geben wenn der µC zu früh Daten
> sendet.

Sowas gibt es eigentlich garnicht. Ein Device tut immer nur genau DAS, 
was der Host von ihm will. Da gibt es nix zu senden, wenn es der Host 
nicht dediziert anfordert.

Vermutlich beruht das Ganze auf einer völlig unzureichenden 
Implementierung auf der µC-Seite. Wenn ich dort sowas lese:

Add the prototypes of the new functions and the initialization flag to 
usb_cdc_if_template.h:
int VCP_read(void *pBuffer, int size);
int VCP_write(const void *pBuffer, int size);

dann wird mir klar, daß dort einfach nicht wirklich nachgedacht worden 
ist. Der Datenverkehr über den USB geht zwar paketweise, aber nicht der 
Verkehr zwischen einer Anwendung im µC und dem USB-Treiber. Deshalb MUSS 
der Treiber den hereinkommenden Datenstrom zeichenweise entgegennehmen, 
zwischenpuffern und bei Aufforderung durch den Host in Blöcken zum Lesen 
durch den Host bereitstellen.

Ich hatte hier schon mal nen CDC Treiber für den STM32F103 gepostet. 
Einfach mal bei Bedarf danach suchen.

W.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
Noch kein Account? Hier anmelden.