Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
847 views
in Technique[技术] by (71.8m points)

stm32 - STM32CubeMX USB CDC VCP?

I've found large number of examples, but nothing on how to do it "properly" from STM32MXCube.

How do I create skeleton code from STM32CubeMX for USB CDC virtual COM port communications (if possible STM32F4 Discovery)?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A STM32CubeMX project for Discovery F4 with CDC as USB device should work out of the box. Assuming you use an up-to-date STM32CubeMX and library:

  • Start STM32CubeMX
  • Select the board Discovery F4
  • Enable peripheral UBS_OTG_FS device only (leave over stuff uncheck)
  • Enable midlleware USB_Device Communication .. .aka CDC

In the clock tab check the clock source is HSE HCLK. It shall give 168 MHz HLCK and 48 MHz in the 48 MHz (USB). Check there is no red anywhere.

Save the project

Generate code (I used SW4STM32 toolchains)

Build (you may need to switch to internal CDT builder vs. GNU make).

Now add some code to send data over the COM port and voila it should work.

Actually, the tricky part is not try to make any "CDC" access until the host USB connects (no CDC setup yet)

Here is how I did it for quick emit test:

In file usbd_cdc_if.c

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
    uint8_t result = USBD_OK;

    /* USER CODE BEGIN 7 */
    if (hUsbDevice_0 == NULL)
        return -1;

    USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, Len);
    result = USBD_CDC_TransmitPacket(hUsbDevice_0);
    /* USER CODE END 7 */

    return result;
}

static int8_t CDC_DeInit_FS(void)
{
    /* USER CODE BEGIN 4 */
    hUsbDevice_0 = NULL;
    return (USBD_OK);
    /* USER CODE END 4 */
}

In file main.c

/* USER CODE BEGIN Includes */
#include "usbd_cdc_if.h"
/* USER CODE END Includes */
....

/* USER CODE BEGIN WHILE */
while (1)
{
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    uint8_t HiMsg[] = "hello
";
    CDC_Transmit_FS(HiMsg, strlen(HiMsg));
    HAL_Delay(200);
}

As soon you plug the micro USB (CN5) CDC data will start to show on the host terminal.

That works. I can see "hello" on the terminal (you may need to install a driver, http://www.st.com/web/en/catalog/tools/PF257938).

For reception, it needs to be first armed, say, started by a first call to USBD_CDC_ReceivePacket() in a good place. For that it can be CDC_Init_FS.

Then you can handle data as it arrives in CDC_Receive_FS and rearming reception again from here.

That works for me.

static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
    /* USER CODE BEGIN 6 */
    USBD_CDC_ReceivePacket(hUsbDevice_0);
    return (USBD_OK);
    /* USER CODE END 6 */
}

static int8_t CDC_Init_FS(void)
{
    hUsbDevice_0 = &hUsbDeviceFS;

    /* USER CODE BEGIN 3 */
    /* Set Application Buffers */
    USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, 0);
    USBD_CDC_SetRxBuffer(hUsbDevice_0, UserRxBufferFS);
    USBD_CDC_ReceivePacket(hUsbDevice_0);

    return (USBD_OK);
    /* USER CODE END 3 */
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...