USB CDC Device and HOST in STM32

In this tutorial I will cover how to implement USB CDC (Communication Device Class) in STM32 using both the modes, i.e. CDC Device, and CDC Host.
For the Host purpose, I will use STM32F411 DISCOVERY Board, and STM32F103 is used as a Device. Both the microcontrollers will be able to communicate with each other using the USB connected between them.

HOST Setup

host setup 1

First of all we need to select the USB_OTG_FS in Host Only mode. Also make sure you activate the VBUS, Host is the one responsible to provide the power to the USB device.


host setup 2
  • Next, select the USB_HOST and select the class as Communication Host Class, and Leave everything here to default.
  • You can see the Pins got selected on the right
  • Also I have selected the PC0 as output so that VBUS can be activated. This is explained below

As we need to enable the voltage supply to the VBUS pin, and to do that, take a look at the board schematics. I am using STM32F4 discovery board, and it have the following diagram for the USB

As you can see above, the VBUS Voltage is controlled by the PC0 pin. Which is connected to the EN Pin, which is an active Low pin. This means in order to supply the voltage to the VBUS, we must Pull down the PC0 Pin, or basically Set it LOW.

That’s all for the HOST setup, now let’s take a look at the device setup






DEVICE Setup

device setup 1

Select the Device mode in the USB Settings


device setup 2
  • In the USB_DEVICE, select the Communication Device Class, and Leave everything to default.
  • You can see the 2 pins also got selected on the right

This is all for the CDC Device Setup.



Connection

connection

As you can see above, the USB is connected between the Host and the Device.



Some Insight into the CODE

HOST CODE

Below are some defines, that will be used in the code

extern USBH_HandleTypeDef hUsbHostFS;
extern ApplicationTypeDef Appli_state;
extern USBH_StatusTypeDef usbresult;

#define RX_BUFF_SIZE   64  /* Max Received data 1KB */

uint8_t CDC_RX_Buffer[RX_BUFF_SIZE];
uint8_t CDC_TX_Buffer[RX_BUFF_SIZE];

typedef enum {
  CDC_STATE_IDLE = 0,
  CDC_SEND,
  CDC_RECEIVE,
}CDC_StateTypedef;

CDC_StateTypedef CDC_STATE = CDC_STATE_IDLE;

uint8_t i=0;
void CDC_HANDLE (void)
{
	switch (CDC_STATE)
	{
	case CDC_STATE_IDLE:
	{
		  USBH_CDC_Stop(&hUsbHostFS);
		  int len = sprintf ((char *)CDC_TX_Buffer, "DATA = %d", i);
		  if (USBH_CDC_Transmit (&hUsbHostFS, CDC_TX_Buffer, len) == USBH_OK)
		  {
			  CDC_STATE = CDC_RECEIVE;
		  }
		  i++;
		  break;
	}

	case CDC_RECEIVE:
	{
		  USBH_CDC_Stop(&hUsbHostFS);
		  usbresult = USBH_CDC_Receive(&hUsbHostFS, (uint8_t *) CDC_RX_Buffer, RX_BUFF_SIZE);
		  HAL_Delay (1000);
		  CDC_STATE = CDC_IDLE;
	}

	default:
		  break;
	}
}
  • CDC_HANDLE will handle the HOST part
  • When the Host is IDLE, it will send the data to the Device
  • Once the data transfer is successful, it will change the CDC state to RECEIVE mode
  • In the Receiving state, Data will be received from the device, and stored in the CDC_RX_Buffer
  • The state will be again changed to IDLE, so that the next data can be transmitted

  while (1)
  {
    /* USER CODE END WHILE */
    MX_USB_HOST_Process();

    if (Appli_state == APPLICATION_READY)
    {
    	CDC_HANDLE();
    }

    /* USER CODE BEGIN 3 */
  }

As you can see above, once the USB device is ready, CDC_HANDLE will always execute, and the data transfer goes on forever.



DEVICE CODE

In the CDC Device, we need to set the Line Coding first. Open the file USB_DEVICE->App->usbd_cdc_if.c and modify the function CDC_Control_FS as shown in the picture below

line coding

The rest of the code for the Reception and transmission is written in CDC_Receive_FS

static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  uint16_t len = *Len;
  CDC_Transmit_FS (Buf, len);
  return (USBD_OK);
  /* USER CODE END 6 */
}

Basically, whenever the device gets the receive request, it will receive the data, and transmit it back to the host using CDC_Transmit_FS function



Result

As you can see above that the CDC_RX_Buffer have received the data (DATA = 0), that we transmitted to the device.

Check out the Video Below










Info

You can help with the development by DONATING
To download the code, click DOWNLOAD button and view the Ad. The project will download after the Ad is finished.

7 Comments. Leave new

  • Hi CT.
    Ur Demo was very helpful.i m configuring host on stm32 f767zit6, I’m able to transmit the data from host ,bunt unable to receive on the host, can u please help me with this.

    Reply
  • when i connect the micro-usb cable ,there is nothing as appearance in device manager.
    how can i solve it ???

    Reply
  • Hi! I see that you keep the ST link usb for power supply and the micro usb for communication, is there a possibility to supply the microcontroller by using only the micro usb? Thank you

    Reply
  • Great job!
    Did you have an idea, How to set the baud rate and the configuration of “ATmega16U2 (usb/serial bridge of Arduino uno)” by stm32f407g-disc1 USB as a HOST using CDC class?

    Reply
  • Thank you for your very useful information

    Reply
  • Thanks for the demo. I tried the host setup with Nucleo-L4R5ZI but I get three errors:
    1) undefined reference to ‘usbresult’
    2) Core/Src/main.o: in function ‘CDC_HANDLE’:
    3) make: *** [makefile:69: Nucleo0L4R5Zi-USB-Host.elf] Error 1

    Could you give some guidance? Thank you for all the information.

    Reply
  • Very helpful. Thankyou.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

keyboard_arrow_up

Adblocker detected! Please consider reading this notice.

We've detected that you are using AdBlock Plus or some other adblocking software which is preventing the page from fully loading.

We don't have any banner, Flash, animation, obnoxious sound, or popup ad. We do not implement these annoying types of ads!

We need money to operate the site, and almost all of it comes from our online advertising.

Please add controllerstech.com to your ad blocking whitelist or disable your adblocking software.

×