主页 > 开源代码  > 

STM32串口转虚拟串口---实现USB转串口功能

STM32串口转虚拟串口---实现USB转串口功能

一,USART与UART 区别

USART(Universal Synchronous/Asynchronous Receiver/Transmitter)通用同步/异步串行接收/发送器

相较于UART:通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)多了一个S,即synchronous(同步)。

也就是说UART相较于USART只是少了一个同步方式而已,而串口在嵌入式中经常使用,但是我们一般使用UART就够

这些操作可以在Cubemx下自动生成。

二,串口初始化

void MX_USART1_Init(void) {

  husart1.Instance = USART1;   husart1.Init.BaudRate = 115200;   husart1.Init.WordLength = USART_WORDLENGTH_8B;   husart1.Init.StopBits = USART_STOPBITS_1;   husart1.Init.Parity = USART_PARITY_NONE;   husart1.Init.Mode = USART_MODE_TX_RX;   husart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;   husart1.Init.OverSampling = UART_OVERSAMPLING_16;   husart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;   husart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;   if (HAL_UART_Init(&husart1) != HAL_OK)   {     Error_Handler();   }          //HAL_UART_Receive_IT(&husart1, (u8 *)aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量          //HAL_UARTEx_ReceiveToIdle_IT(&husart1, (u8 *)aRxBuffer, RXBUFFERSIZE);//串口接收任意字长字符串 }

三。IO初始化,DMA通道的设置

void HAL_UART_MspInit(UART_HandleTypeDef* usartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(usartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspInit 0 */ /* USER CODE END USART1_MspInit 0 */ /* USART1 clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART1 DMA Init */ /* USART1_RX Init */ hdma_usart1_rx.Instance = DMA1_Channel5; hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart1_rx.Init.Mode = DMA_NORMAL; hdma_usart1_rx.Init.Priority = DMA_PRIORITY_HIGH; if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(usartHandle,hdmarx,hdma_usart1_rx); /* USART1_TX Init */ hdma_usart1_tx.Instance = DMA1_Channel4; hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart1_tx.Init.Mode = DMA_NORMAL; hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(usartHandle,hdmatx,hdma_usart1_tx); #if EN_USART1_RX /* USART1 interrupt Init */ HAL_NVIC_SetPriority(USART1_IRQn, 1,1); HAL_NVIC_EnableIRQ(USART1_IRQn); #endif } }

四。DMA 中断的设置,注意,如果USART或DMA的中断优先级被设置得太低,它们可能会被其他高优先级的中断延迟。

void MX_DMA_Init(void) {

  /* DMA controller clock enable */   __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */   /* DMA1_Channel4_IRQn interrupt configuration */   HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 1, 0);   HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);   /* DMA1_Channel5_IRQn interrupt configuration */   HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);   HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);

}

 五,DMA中断服务函数 不定长接收

停止HAL_UART_DMAStop(&husart1);  

  dat_len =  sizeof(aRxBuffer) - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);     //计算接收到的数据长度                  USB_USART_Send(aRxBuffer,dat_len);//虚拟串口转发             dat_len = 0;//清零          memset(aRxBuffer,0,sizeof(aRxBuffer)); //重置         Error_code_uart1=HAL_UARTEx_ReceiveToIdle_DMA(&husart1, (u8 *)aRxBuffer, sizeof(aRxBuffer));//再次开启DMA

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)  {          if(huart->Instance==USART1)//如果是串口1     {         HAL_UART_DMAStop(&husart1);           dat_len =  sizeof(aRxBuffer) - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);     //计算接收到的数据长度                  USB_USART_Send(aRxBuffer,dat_len);//虚拟串口转发             dat_len = 0;          memset(aRxBuffer,0,sizeof(aRxBuffer));          Error_code_uart1=HAL_UARTEx_ReceiveToIdle_DMA(&husart1, (u8 *)aRxBuffer, sizeof(aRxBuffer));     }      } //串口1中断服务程序 void USART1_IRQHandler(void)                     {          HAL_UART_IRQHandler(&husart1);    //调用HAL库中断处理公用函数     }  void DMA1_Channel4_IRQHandler(void) {     HAL_DMA_IRQHandler(&hdma_usart1_tx); } /**   * @brief This function handles DMA1 channel5 global interrupt.   */ void DMA1_Channel5_IRQHandler(void) {   HAL_DMA_IRQHandler(&hdma_usart1_rx); }

六,初始化 及溢出错误处理

if (Error_code_uart1 != HAL_OK)//出错,重开     {         // 清空缓冲,置位一些标志,具体看函数内部         HAL_UART_AbortReceive(&husart1);         // 重启接收         Error_code_uart1=HAL_UARTEx_ReceiveToIdle_DMA(&husart1, (u8 *)aRxBuffer, sizeof(aRxBuffer));         }

int main(void) { u8 len; /* 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(); USB_Reset(); // USB断开再重连 HAL_Delay(1); MX_USB_DEVICE_Init(); MX_DMA_Init(); MX_USART1_Init(); HAL_Delay(2000);//等待虚拟串口初始化完成 Error_code_uart1=HAL_UARTEx_ReceiveToIdle_DMA(&husart1, (u8 *)aRxBuffer, sizeof(aRxBuffer)); while (1) { u8 usbstatus = 0; if (usbstatus != USB_GetStatus()) { usbstatus = USB_GetStatus(); // 记录新的状态 } if (Error_code_uart1 != HAL_OK)//出错,重开 { // 清空缓冲,置位一些标志,具体看函数内部 HAL_UART_AbortReceive(&husart1); // 重启接收 Error_code_uart1=HAL_UARTEx_ReceiveToIdle_DMA(&husart1, (u8 *)aRxBuffer, sizeof(aRxBuffer)); } } }
标签:

STM32串口转虚拟串口---实现USB转串口功能由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“STM32串口转虚拟串口---实现USB转串口功能