一,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));
}
}
}