赞
踩
目录
(2)打开dma接收、发送请求,选择normal搬运,数据类型设置为字节
2、在初始化中加入以下代码:空闲中断使能、打开DMA发送、接收请求
3、在stm32g4xx_it.c中找到USART1_IRQHandler(void),重写中断服务函数
空闲中断:顾名思义当串口空闲时候触发中断,当串口接收到数据时,数据是以字节为单位进行传送,当最后一字节接收后一段时间(通常很短)没有接收到下一字节数据,就会触发空闲中断。利用空闲中断的这个特性,可以实现串口数据的不定长接收。
- __HAL_UART_CLEAR_IDLEFLAG(&huart1); //空闲中断标志位清除
- __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
-
- HAL_UART_Receive_DMA(&huart1, (uint8_t *)rx, 20);
- HAL_UART_Transmit_DMA(&huart1, (uint8_t *)rx,20);
- void USART1_IRQHandler(void)
- {
- /* USER CODE BEGIN USART1_IRQn 0 */
-
- /* USER CODE END USART1_IRQn 0 */
- //HAL_UART_IRQHandler(&huart1); //屏蔽
- /* USER CODE BEGIN USART1_IRQn 1 */
-
- if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)!=RESET)
- {
- ucTemp=1;
- __HAL_UART_CLEAR_IDLEFLAG(&huart1);
- HAL_UART_DMAStop(&huart1);
- idle_rxcallback(&huart1);
- }
-
-
-
- /* USER CODE END USART1_IRQn 1 */
- }

将中断函数中的回调函数HAL_UART_IRQHandler(&huart1)屏蔽掉,检查空闲中断的标志位,若置位则将uc_Temp置1,然后清除空闲中断标志位(若不清除程序会一直卡在中断里,导致其余代码无法执行)。清除标志位之后停止DMA,然后调用idle_rxcallback(&huart1);回调函数。
注意:回调函数是自己编写,什么名字都可以!!!
不要开启其它串口中断,否则程序可能会卡死在串口中断中。
- void idle_rxcallback(UART_HandleTypeDef *huart)
- {
- rx_num=0;
- rx_num=20-__HAL_DMA_GET_COUNTER(&hdma_usart1_rx); //DMA传输的剩余数据量
- HAL_UART_Receive_DMA(&huart1, (uint8_t *)rx, 20);
-
- }
在空闲中断中打开DMA的接收搬运,此代码中我添加了对接收数据的计数,没有这个需求的也可以不加。
- if(ucTemp==1)
- {
- ucTemp=0;
- //printf("%s",rx); //串口回显
-
- strcpy(tx,rx);
- HAL_UART_Transmit_DMA(&huart1, (uint8_t *)tx,20);//串口回显
-
- sprintf(text,"rx_num:%02d",rx_num);
- LCD_DisplayStringLine(Line1, (u8 *)text);
-
- memset(rx,0,sizeof((unsigned char)rx));
- memset(tx,0,sizeof((unsigned char)tx));
-
- }
在主函数中检查uc_Temp标志位,若标志位等于1,则说明空闲中断被触发,一帧串口数据接收完成,可以进行数据处理,处理后,再将标志位置0,等待下一帧数据接收完成。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。