Library 24- Virtual COM Port (VCP) for STM32F4
This library provides Virtual COM port on USB OTG. This means, that you don’t need external USB->UART converter (like FTDI) to communicate with computer. STM32F4xx will be seen to computer like COM port.
Library can be used on all STM32F4xx devices. It has also features to support STM32F4- and STM32F429 Discovery boards.
To use USB with HAL, check my HAL USB library.
Library
Features
- Enables USB VCP
- Works in USB FS mode
- Default for STM32F4-Discovery board
- Works in USB HS in FS mode
- Default for STM32F429-Discovery board
- Version 1.2 – March 08, 2015
- Added options to detect if user has changed parameters in terminal (baudrate, stop bits, data bits, parity) in case you are doing USB<->UART converter
Dependencies
- CMSIS
- STM32F4xx
- STM32F4xx RCC
- STM32F4xx GPIO
- STM32F4xx EXTI
- MISC
- TM
- defines.h
- defines.h
- USB
- USB CDC device stack provided by STMicroelectronics (included in library)
Pinout
As 2 options can be used, there are 2 pinouts:
USB | FS Mode | HS in FS Mode | Description |
---|---|---|---|
Data + | PA12 | PB15 | USB Data+ line |
Data – | PA11 | PB14 | USB Data- line |
ID | PA10 | PB12 | USB ID pin |
VBUS | PA9 | PB13 | USB activate |
Notes:
- STM32F4-Discovery has micro USB connected to USB FS mode
- STM32F429-Discovery has micro USB connected to USB HS in FS mode
- If you have USB->4 wires cable, you can connect both boards in both ways, but then you don’t have fancy connected.
- Clock for STM32F429 was set down to 168MHz, because you can not get 48MHz for USB with 180MHz core clock
By default, library is set in FS mode, so pins PA11 and PA12 are in use. If you are working with STM32F429 Discovery board and you want to use microUSB connector instead of wires on pinheaders, then open your defines.h file and activate USB HS in FS mode:
1 2 |
/* Activate USB HS in FS mode */ #define USE_USB_OTG_HS |
You are now working in HS mode.
Default internal buffer size for received data is 128bytes. If you need more, you can set more in defines.h file using specific define:
1 2 |
/* Custom buffer size */ #define USB_VCP_RECEIVE_BUFFER_LENGTH 128 |
When you connect board to USB to computer, there will be new COMx seen. For that, you also need USB VCP drivers provided by STMicroelectronics.
Note: In your terminal are options to set baudrate, stop bits, etc. Leave that at it is, these settings don’t care, because everything is configured by USB.
Precompiled versions
Some users has issues with setting project (example below) correctly (don’t know why) and I have precompile long time ago 2 versions of example for F4-Disco and F429-Discovery boards. This is now available here for download.
These examples has positive feedbacks as they work ok.
Functions and enumerations
I have written some basic functions to work with data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
/** * @defgroup TM_USB_VCP_Typedefs * @brief Library Typedefs * @{ */ /** * @brief VCP Result Enumerations */ typedef enum { TM_USB_VCP_OK, /*!< Everything ok */ TM_USB_VCP_ERROR, /*!< An error occurred */ TM_USB_VCP_RECEIVE_BUFFER_FULL, /*!< Receive buffer is full */ TM_USB_VCP_DATA_OK, /*!< Data OK */ TM_USB_VCP_DATA_EMPTY, /*!< Data empty */ TM_USB_VCP_NOT_CONNECTED, /*!< Not connected to PC */ TM_USB_VCP_CONNECTED, /*!< Connected to PC */ TM_USB_VCP_DEVICE_SUSPENDED, /*!< Device is suspended */ TM_USB_VCP_DEVICE_RESUMED /*!< Device is resumed */ } TM_USB_VCP_Result; /** * @brief Structure for USART if you are working USB/UART converter with STM32F4xx */ typedef struct { uint32_t Baudrate; /*!< Baudrate, which is set by user on terminal. Value is number of bits per second, for example: 115200 */ uint8_t Stopbits; /*!< Stop bits, which is set by user on terminal. Possible values: - 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits */ uint8_t DataBits; /*!< Data bits, which is set by user on terminal. Possible values: - 5: 5 data bits - 6: 6 data bits - 7: 7 data bits - 8: 8 data bits - 9: 9 data bits */ uint8_t Parity; /*!< Parity, which is set by user on terminal. Possible values: - 0: No parity - 1: Odd parity - 2: Even parity - 3: Mark parity - 4: Space parity */ uint8_t Changed; /*!< When you check for settings in my function, this will be set to 1 if user has changed parameters, so you can reinitialize USART peripheral if you need to. */ } TM_USB_VCP_Settings_t; /** * @} */ /** * @defgroup TM_USB_VCP_Functions * @brief Library Functions * @{ */ /** * @brief Initializes USB VCP * @param None * @retval TM_USB_VCP_OK */ TM_USB_VCP_Result TM_USB_VCP_Init(void); /** * @brief Reads settings from user * @note These settings are set in terminal on PC * @param *Settings: Pointer to TM_USB_VCP_Settings_t structure where to save data * @retval TM_USB_VCP_OK */ TM_USB_VCP_Result TM_USB_VCP_GetSettings(TM_USB_VCP_Settings_t* Settings); /** * @brief Gets received character from internal buffer * @param *c: pointer to store new character to * @retval Character status: * - TM_USB_VCP_DATA_OK: Character is valid inside *c_str * - TM_USB_VCP_DATA_EMPTY: No character in *c */ TM_USB_VCP_Result TM_USB_VCP_Getc(uint8_t* c); /** * @brief Puts character to USB VCP * @param c: character to send over USB * @retval TM_USB_VCP_OK */ TM_USB_VCP_Result TM_USB_VCP_Putc(volatile char c); /** * @brief Gets string from VCP port * * @note To use this method, you have to send \n (0x0D) at the end of your string, * otherwise data can be lost and you will fall in infinite loop. * @param *buffer: Pointer to buffer variable where to save string * @param bufsize: Maximum buffer size * @retval Number of characters in buffer: * - 0: String not valid * - > 0: String valid, number of characters inside string */ uint16_t TM_USB_VCP_Gets(char* buffer, uint16_t bufsize); /** * @brief Puts string to USB VCP * @param *str: Pointer to string variable * @retval TM_USB_VCP_OK */ TM_USB_VCP_Result TM_USB_VCP_Puts(char* str); /** * @brief Gets VCP status * @param None * @retval Device status: * - TM_USB_VCP_CONNECTED: Connected to computer * - other: Not connected and not ready to communicate */ TM_USB_VCP_Result TM_USB_VCP_GetStatus(void); /** * @brief Checks if receive buffer is empty * @param None * @retval Buffer status: * - 0: Buffer is not empty * - > 0: Buffer is empty */ uint8_t TM_USB_VCP_BufferEmpty(void); /** * @brief Checks if receive buffer is fukk * @param None * @retval Buffer status: * - 0: Buffer is not full * - > 0: Buffer is full */ uint8_t TM_USB_VCP_BufferFull(void); /** * @brief Checks if character is in buffer * @param c: Character to be checked if available in buffer * @retval Character status: * - 0: Character is not in buffer * - > 0: Character is in buffer */ uint8_t TM_USB_VCP_FindCharacter(volatile char c); /* Internal functions */ extern TM_USB_VCP_Result TM_INT_USB_VCP_AddReceived(uint8_t c); /** * @} */ |
Example
I have used STM32F4-Discovery for this example with default settings, because STM32F4-Discovery has micro USB connected to FS mode (default mode).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
/** * USB VCP for STM32F4xx example. * * @author Tilen Majerle * @email tilen@majerle.eu * @website http://stm32f4-discovery.net * @ide Keil uVision * * Add line below to use this example with F429 Discovery board (in defines.h file) * * #define USE_USB_OTG_HS */ #include "tm_stm32f4_usb_vcp.h" #include "tm_stm32f4_disco.h" #include "defines.h" int main(void) { uint8_t c; /* System Init */ SystemInit(); /* Initialize LED's. Make sure to check settings for your board in tm_stm32f4_disco.h file */ TM_DISCO_LedInit(); /* Initialize USB VCP */ TM_USB_VCP_Init(); while (1) { /* USB configured OK, drivers OK */ if (TM_USB_VCP_GetStatus() == TM_USB_VCP_CONNECTED) { /* Turn on GREEN led */ TM_DISCO_LedOn(LED_GREEN); TM_DISCO_LedOff(LED_RED); /* If something arrived at VCP */ if (TM_USB_VCP_Getc(&c) == TM_USB_VCP_DATA_OK) { /* Return data back */ TM_USB_VCP_Putc(c); } } else { /* USB not OK */ TM_DISCO_LedOff(LED_GREEN); TM_DISCO_LedOn(LED_RED); } } } |
View project on Github, download library below.
Recent comments