Development Environment:
IDE: MKD 5.38a
STM32CubeMX: V6.12.0
Development board: STM32H7S78-DK development board
MCU: STM32H7S7L8H6H
1 Introduction to USB Virtual Serial Port
USB virtual serial port, referred to as VCP, is the abbreviation of Virtual COM Port. It is a communication interface implemented by using the USB CDC class.
We can use the built-in USB function of STM32 to realize a USB virtual serial port, so as to realize data transmission between computer and STM32 through USB. The host computer does not need to write a special USB program, but only needs a serial port debugging assistant for debugging, which is very practical.
2 USB hardware circuit
The hardware circuit of USB is as follows:
Figure 2-1 USB hardware circuit
USB interfaces PM11 and PM12.
3 USB virtual serial port (VPC)
3.1 STM32CubeMX configuration project
First, turn on USB. Configure the USB device, select the USB Device function, and set the speed to the default full-speed USB device 12MHZ.
Enable the USB_DEVICE library, select Virtual Port Com (VPC), and use the default configuration.
Configure the USB FS clock to 48MHz.
Then generate the project.
3.2 Virtual Serial Port Software Implementation
The data transmission and reception interface is in the usbd_cdc_if.c file.
/**
* [url=home.php?mod=space&uid=159083]@brief[/url] Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will issue a NAK packet on any OUT packet received on
* USB endpoint until exiting this function. If you exit this function
* before transfer is complete on CDC interface (ie. using DMA controller)
* it will result in receiving more data while previous ones are still
* not sent.
*
* @param Buf: Buffer of data to be received
* @param Len: Number of data received (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
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);
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data to send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be sent
* @param Len: Number of data to be sent (in bytes)
* @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
*/
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
Printing Output
Of course, you can also use USB as printf similar to uart to output the currently needed log information. We only need to modify this function to use USB and VCP to print output information.
int fputc(int ch, FILE *f)
{
while(CDC_Transmit_FS((uint8_t *)&ch, 1) == USBD_BUSY);
return ch;
}
The main function code is as follows:
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_UART4_Init();
MX_USB_DEVICE_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart4, (uint8_t *)&RxBuffer, 1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
/* Insert delay 200 ms */
HAL_Delay(200);
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
/* Insert delay 200 ms */
HAL_Delay(200);
HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin);
/* Insert delay 200 ms */
HAL_Delay(200);
HAL_GPIO_TogglePin(LED4_GPIO_Port, LED4_Pin);
/* Insert delay 200 ms */
HAL_Delay(200);
printf("USB CDC, %s \r\n", UserRxBufferFS);
memset(UserRxBufferFS, 0, APP_RX_DATA_SIZE);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
3.3 Experimental Phenomena
Insert the USB into the computer, and a new serial port device will be displayed in the computer device manager. If the VPC driver is not installed, you need to install it first.
View the USB hardware information.
The above VID and PID can be found in the file usbd_desc.c.
Use the serial port assistant to connect the device and the following information will be printed.
After sending the data, the virtual serial port will print and process the received data.