stm32f429-discovery +cubemx + USB转虚拟串口 研究
在实验过stm32f302的USB转串口之后,仍对缺少上拉电阻或者说不能配置上拉的GPIO感到不安。
所以此次直接更新为stm32f429的开发板,贵就是有贵的好处,配置方法不拖泥带水。
按步来吧,先介绍版本:stm32cubemx version 4.15.1 STM32Cube v1.0 ; Firmware Package for family STM32F4 1.12.0; Keil 4.73
以下配置情况仅供参考,意外情况可以提问。
1.配置管脚,一开始用USART2,应该是引脚复用,结果该口没法用,改用USART1就OK. 还开了两个LED作为通讯指示。
2.配置时钟
3.串口1的配置
使用DMA作为发送模式妥妥的省资源。
4.USB底层配置
5.中断配置,需要打开DMA2中断
6.USB中间层配置
7.代码生成配置
8.关键代码示例
main函数中的关键定义及引用。 csdn 的代码好坑 本来都是标红的 都被
<span style="font-size:18px;color:#ff0000;"><span style="color:#ff0000;"> <span style="font-family: Arial, Helvetica, sans-serif;"></span> 包围了。自己小心看吧</span></span>
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "dma.h"
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"
/* USER CODE BEGIN Includes */
<span style="color:#ff0000;">#include "usbd_cdc_if.h"</span>
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
uint8_t aRxBuffer[1];
uint8_t aTxBuffer[16];
//extern uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USB_DEVICE_Init();
MX_USART2_UART_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_Delay(500);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
<span style="color:#ff0000;">if(HAL_UART_Receive_IT(&huart1,&aRxBuffer[0], 1)== HAL_OK)
{
HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin);//灯儿,不想用的屏蔽掉就OK
CDC_Transmit_FS(&aRxBuffer[0],1);
}</span>
// HAL_UART_Transmit(&huart1, test, sizeof(test), 100);
// HAL_Delay(500);
}
/* USER CODE END 3 */
}
- usbd_cdc_if.c文件中的关键配置,标红部分为新加配置。
/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_CDC
* @brief usbd core module
* @{
*/
/** @defgroup USBD_CDC_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
extern UART_HandleTypeDef huart2; //这个没启用成功,还赖在这
<span style="color:#ff0000;">extern UART_HandleTypeDef huart1;</span>
/* The following structures groups all needed parameters to be configured for the
ComPort. These parameters can modified on the fly by the host through CDC class
command class requests. */
<span style="color:#ff0000;">typedef struct
{
uint32_t bitrate;
uint8_t format;
uint8_t paritytype;
uint8_t datatype;
}LINE_CODING;
</span>
//mch settings for usb vcp
<span style="color:#ff0000;">LINE_CODING linecoding =
{
9600, /* baud rate*/
0x00, /* stop bits-1*/
0x00, /* parity - none*/
0x08 /* nb. of bits 8*/
};</span>
<span style="color:#ff0000;">extern uint8_t aRxBuffer[16];</span>
extern uint8_t aTxBuffer[16];
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Defines
* @{
*/
/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
<span style="color:#ff0000;">#define APP_RX_DATA_SIZE 254
#define APP_TX_DATA_SIZE 254</span>
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_Variables
* @{
*/
/* Create buffer for reception and transmission */
/* It's up to user to redefine and/or remove those define */
/* Received Data over USB are stored in this buffer */
uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
/* Send Data over USB CDC are stored in this buffer */
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_CDC_Private_FunctionPrototypes
* @{
*/
static int8_t CDC_Init_FS (void);
static int8_t CDC_DeInit_FS (void);
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS (uint8_t* pbuf, uint32_t *Len);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
CDC_Init_FS,
CDC_DeInit_FS,
CDC_Control_FS,
CDC_Receive_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Init_FS
* Initializes the CDC media low layer over the FS USB IP
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Init_FS(void)
{
/* USER CODE BEGIN 3 */
/* Set Application Buffers */
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0);
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS);
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief CDC_DeInit_FS
* DeInitializes the CDC media low layer
* @param None
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_DeInit_FS(void)
{
/* USER CODE BEGIN 4 */
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief CDC_Control_FS
* Manage the CDC class requests
* @param cmd: Command code
* @param pbuf: Buffer containing command data (request parameters)
* @param length: Number of data to be sent (in bytes)
* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
/* USER CODE BEGIN 5 */
switch (cmd)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
break;
case CDC_SET_COMM_FEATURE:
break;
case CDC_GET_COMM_FEATURE:
break;
case CDC_CLEAR_COMM_FEATURE:
break;
/*******************************************************************************/
/* Line Coding Structure */
/*-----------------------------------------------------------------------------*/
/* Offset | Field | Size | Value | Description */
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
/* 4 | bCharFormat | 1 | Number | Stop bits */
/* 0 - 1 Stop bit */
/* 1 - 1.5 Stop bits */
/* 2 - 2 Stop bits */
/* 5 | bParityType | 1 | Number | Parity */
/* 0 - None */
/* 1 - Odd */
/* 2 - Even */
/* 3 - Mark */
/* 4 - Space */
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
/*******************************************************************************/
<span style="color:#ff0000;"> case CDC_SET_LINE_CODING:
linecoding.bitrate = (uint32_t)(pbuf[0] | (pbuf[1] << 8) | (pbuf[2] << 16) | (pbuf[3] << 24));
linecoding.format = pbuf[4];
linecoding.paritytype = pbuf[5];
linecoding.datatype = pbuf[6];
huart1.Init.BaudRate = linecoding.bitrate;
switch (linecoding.format)
{
case 0 : huart1.Init.StopBits = UART_STOPBITS_1; break;
case 1 : huart1.Init.StopBits = UART_STOPBITS_2; break;
// case 2 : huart2.Init.StopBits = UART_STOPBITS_2; break;//有些位吧429库里没发现 ,奇怪
}
switch (linecoding.paritytype)
{
case 0 : huart1.Init.Parity = UART_PARITY_NONE; break;
case 1 : huart1.Init.Parity = UART_PARITY_ODD; break;
case 2 : huart1.Init.Parity = UART_PARITY_EVEN; break;
}
//UART_WORDLENGTH_7B
switch (linecoding.datatype)
{
case 9 : huart1.Init.WordLength = UART_WORDLENGTH_9B; break;
case 8 : huart1.Init.WordLength = UART_WORDLENGTH_8B; break;
}
HAL_UART_Init(&huart1) ;
/* HAL_RS485Ex_Init(&huart2, UART_DE_POLARITY_HIGH, 0, 0); //这个地方就露馅了,本来是给485用的,后来就改成串口了,当然有兴趣的童鞋可以继续配置成485模式,记得引脚等。详细信息可以参考 http://www.stm32cube.com/article/120 */
break;
case CDC_GET_LINE_CODING:
pbuf[0] = (uint8_t)(linecoding.bitrate);
pbuf[1] = (uint8_t)(linecoding.bitrate >> 8);
pbuf[2] = (uint8_t)(linecoding.bitrate >> 16);
pbuf[3] = (uint8_t)(linecoding.bitrate >> 24);
pbuf[4] = linecoding.format;
pbuf[5] = linecoding.paritytype;
pbuf[6] = linecoding.datatype;
break;</span>
case CDC_SET_CONTROL_LINE_STATE:
break;
case CDC_SEND_BREAK:
break;
default:
break;
}
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief CDC_Receive_FS
* Data received over USB OUT endpoint are sent over CDC interface
* through this function.
*
* @note
* This function will block any OUT packet reception on USB endpoint
* untill 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);
<span style="color:#ff0000;"> HAL_UART_Transmit_DMA(&huart1, Buf, *Len);
HAL_GPIO_TogglePin(LED_RED_GPIO_Port,LED_RED_Pin);//灯儿</span>
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief CDC_Transmit_FS
* Data send over USB IN endpoint are sent over CDC interface
* through this function.
* @note
*
*
* @param Buf: Buffer of data to be send
* @param Len: Number of data to be send (in bytes)
* @retval Result of the operation: 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;
}
最后说一下,在115200波特率的时候会丢帧,可能跟一开始 的72MHz时钟有关。未验证
上一张实物图吧,光说不练假把式
小玩至此结束,有疑问请留言。
还没有评论,来说两句吧...