Ich bin ein Anfänger in STM32F4 und lerne, wie man den USB Virtual COM Port ("VCP") verwendet, um Daten vom Mikrocontroller an einen PC zu übertragen.
Der virtuelle Port wird als "STMicroelectronics Virtual COM Port" erkannt, und ich verwende eine serielle Überwachungssoftware, um die vom PC empfangenen Daten anzuzeigen.
Der PC empfängt alle 0x00, egal was ich in meinem Code sende.
Ich habe die Funktion VCP_DataTx() aufgerufen, um Daten zu senden.
Irgendwelche Ideen, was falsch ist?
ps in meiner main()-Funktion habe ich nur USBD_Init() aufgerufen, um das USB-Gerät zu initialisieren, reicht das? Habe ich etwas übersehen, das konfiguriert werden sollte? Ich sehe jemanden, der USART sagt, wenn er über VCP spricht. Gibt es eine Beziehung zwischen ihnen?
Danke.
Das ist meine main.cpp. Ich habe nichts weiter getan, als das USB-Gerät initialisiert und Daten gesendet.
#include "usbd_cdc_core.h"
#include "usbd_usr.h"
#include "usb_conf.h"
#include "usbd_desc.h"
#include "usbd_cdc_vcp.h"
USB_OTG_CORE_HANDLE USB_OTG_dev;
uint8_t Buf[6] = "A";
int main(void)
{
__IO uint32_t i = 0;
USBD_Init(&USB_OTG_dev,
USB_OTG_FS_CORE_ID,
&USR_desc,
&USBD_CDC_cb,
&USR_cb);
VCP_DataTx(Buf, 6);
/* Main loop */
while (1)
{
VCP_DataTx(Buf, 6);
while (i < 0x77ffff)
{
i++;
}
}
}
Um VCP_DataTx() in main aufzurufen, habe ich das statische Schlüsselwort in usbd_cdc_vcp.h und usbd_cdc.vcp.c gelöscht
pps Ich wusste nicht, dass usbd_cdc_vcp.c nicht in der STM USB-Bibliothek ist. Es stammt aus dem VCP-Beispiel in STM32_USB-Host-Device_Lib_V2.1.0, und die Funktion VCP_DataTx() sieht so aus:
uint16_t VCP_DataTx (uint8_t* Buf, uint32_t Len)
{
if (linecoding.datatype == 7)
{
APP_Rx_Buffer[APP_Rx_ptr_in] = USART_ReceiveData(EVAL_COM1) & 0x7F;
}
else if (linecoding.datatype == 8)
{
APP_Rx_Buffer[APP_Rx_ptr_in] = USART_ReceiveData(EVAL_COM1);
}
APP_Rx_ptr_in++;
/* To avoid buffer overflow */
if(APP_Rx_ptr_in == APP_RX_DATA_SIZE)
{
APP_Rx_ptr_in = 0;
}
return USBD_OK;
}
Ich verwende die ST-USB-Bibliothek für einen anderen ST-ARM-Mikrocontroller (STM32F105), aber die Struktur sieht gleich aus. Auch ich habe meinen Code auf dem VCP-Beispiel basiert.
Zunächst ist eine zusätzliche Initialisierung erforderlich, damit der USB funktioniert. Es folgt eine Liste der Dinge, die überprüft werden müssen. Sie können einige dieser Beispiele neu anpassen, um mit Ihrem Mikrocontroller zu arbeiten:
Sie müssen den OTG_FS_IRQHandler
Interrupt aktiviert haben:
NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 7;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
Folgendes ist in meiner Interrupt-Vektordatei:
#include "usb_core.h"
#include "usbd_core.h"
#include "usbd_cdc_core.h"
extern USB_OTG_CORE_HANDLE USB_OTG_dev;
extern uint32_t USBD_OTG_ISR_Handler (USB_OTG_CORE_HANDLE *pdev);
void OTG_FS_IRQHandler(void)
{
USBD_OTG_ISR_Handler (&USB_OTG_dev);
} // end OTG_FS_IRQHandler()
Sie müssen eine 48-MHz-Taktquelle für das OTG/USB-Modell auswählen und aktivieren, bevor Sie anrufen USBD_Init
. In meinem Fall wurde dies abgeleitet, indem der 144-MHz-PLLVCO durch 3 dividiert wurde. Der Taktbaum kann schwierig sein; Stellen Sie sicher, dass Sie diesen Abschnitt des Referenzhandbuchs verstanden haben.
// Configure USB Clock Source
RCC_OTGFSCLKConfig(RCC_OTGFSCLKSource_PLLVCO_Div3);
// Enable USB Clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE);
In der USB-Bibliothek ist die usb_conf.h
Datei. Dies ist ein Gewirr von bedingten Definitionen. Stellen Sie sicher, dass diese tatsächlich definiert werden (falls sie für Ihre Anwendung geeignet sind):
#define USE_USB_OTG_FS
#define USB_OTG_FS_CORE
#define USE_EMBEDDED_PHY
#define VBUS_SENSING_ENABLED
#define USE_DEVICE_MODE
Als nächstes muss, wie @Tut in den Kommentaren betonte, Ihre VCP_DataTX
Funktion geändert werden. Es verwendet derzeit das USART-Peripheriegerät als Quelle der USB-Daten. Sie möchten es so ändern, dass es Buf
und verwendet Len
. Obwohl der Funktionsaufruf die Argumente Buf
und enthält Len
, werden diese nicht wirklich in der Funktion verwendet.
Der VCP_DataTx
stopft Daten, ein Byte nach dem anderen, in das APP_Rx_Buffer
Array. Jedes Mal, wenn es ein Byte in das Array schreibt, erhöht es auch den APP_Rx_ptr_in
Wert. Dieser Puffer wird regelmäßig vom Code der OTG/USB-Bibliothek überprüft und verarbeitet.
Meine Funktion sieht so aus:
uint16_t VCP_DataTx(uint8_t *Buf, uint32_t Len)
{
uint32_t i;
// Put the data into the buffer. It will be processed by the USB stack.
for (i=0; i<Len; i++)
{
// Add a byte to the buffer
APP_Rx_Buffer[APP_Rx_ptr_in] = Buf[i];
// Update the circular buffer index
APP_Rx_ptr_in++;
// Loop the index if necessary
if (APP_Rx_ptr_in == APP_RX_DATA_SIZE)
{
APP_Rx_ptr_in = 0;
}
}
return USB_SUCCESS;
}
Schließlich gibt es noch ein paar andere Probleme in Ihrem Code. Ich nehme an, Sie kennen einige davon, aber ich werde sie nur für den Fall auflisten:
Die Anweisung uint8_t Buf[6] = "A";
initialisiert nur den ersten Wert auf 'A'. Die restlichen fünf Werte sind '\0'. Weitere Informationen finden Sie hier .
Wenn die Zählervariable i
Ihre Verzögerungsgrenze überschreitet, sollte sie auf Null zurückgesetzt werden. Dies könnte ein primäres Problem sein . Wenn die Verzögerung das erste Mal endet, verzögert sie sich derzeit nie wieder. Die äußere while
Schleife beginnt VCP_DataTx(Buf, 6);
kontinuierlich zu rufen. Dies wird den USB-Puffer überlaufen lassen und zu allen möglichen Problemen führen.
Sobald Sie das Verzögerungsproblem behoben haben, erhalten Sie immer noch zwei Anrufe hintereinander VCP_DataTx(Buf, 6);
ohne Verzögerungen. Einmal vor der Verzögerungsschleife und sofort noch einmal vor der ersten Verzögerung. Dies sollte kein Problem darstellen, aber ich wollte darauf hinweisen.
Zu Ihrer Information, wenn Sie nur versuchen, Daten über USB an einen PC hin und her zu senden, müssen Sie keine USART-Funktionalität im Mikrocontroller aktivieren. Das VCP-Beispiel verwendet den USART als Datenquelle (und Ziel), aber das versuchen Sie nicht. Ihre Datenquelle ist Ihr Buf[]
Array.
bitsmack
Marko Buršič
Alexander Zhang
Tut
Alexander Zhang