实现串口空闲中断+DMA接收数据
- 使用STMCubeMX创建工程并设置UART和DMA,注意一点是有时候CUBE生成代码时候,UART初始化在MDA初始化之前,我之前的文章提过,这样DMA会不好使,所以要看好一定要先初始化DMA。
- 设置空闲中断
- 初始化时候打开串口DMA接收中断
HAL_UART_Receive_DMA(&huart1, rx_buff, RX_SIZE);
- 编写中断处理函数,"__HAL_DMA_GET_COUNTER(huart1.hdmarx)"是获取存储空间的剩余值。所以收到的数据就是存储值减去剩余值。
#define RX_SIZE 128
uint8_t rx_len = 0;
uint8_t recv_flag = 0;
uint8_t rx_buff[RX_SIZE] = {0};
void User_Uart1_IRQ(void)
{
static uint8_t temp = 0;
if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) == SET)
{
HAL_UART_DMAStop(&huart1);
rx_len = RX_SIZE - __HAL_DMA_GET_COUNTER(huart1.hdmarx);
recv_flag = 1;
HAL_UART_Receive_DMA(&huart1, rx_buff, RX_SIZE);
}
}
将此函数添加到stm32xx_it.h的USART1_IRQHandler()函数里面,系统自带的“HAL_UART_IRQHandler(&huart1);”不要删除,如果删除,需要在自己调用的函数清除读和空闲标志位,不删除我们可以不用管这些。
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
User_Uart1_IRQ();
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
- 主函数
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(recv_flag == 1)
{
// HAL_UART_Transmit(&huart1, rx_buff, rx_len, 100); // 正常发送
HAL_UART_Transmit_DMA(&huart1, rx_buff, rx_len); // 使用DMA发送
rx_len = 0;
recv_flag = 0;
}
}
- 测试