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 Below.
To download the project, click the DOWNLOAD button.

Subscribe
Notify of

8 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
keyboard_arrow_up