当前位置:   article > 正文

蓝桥杯嵌入式stm32G431RBT6-----空闲中断+DMA实现串口不定长收发_蓝桥杯嵌入式串口不定等长接收

蓝桥杯嵌入式串口不定等长接收

目录

1、cubemx配置

(1)串口选择异步模式,波特率9600,打开串口接收中断

(2)打开dma接收、发送请求,选择normal搬运,数据类型设置为字节

2、在初始化中加入以下代码:空闲中断使能、打开DMA发送、接收请求

3、在stm32g4xx_it.c中找到USART1_IRQHandler(void),重写中断服务函数

4、编写空闲中断回调函数

5、主函数while接收


        空闲中断:顾名思义当串口空闲时候触发中断,当串口接收到数据时,数据是以字节为单位进行传送,当最后一字节接收后一段时间(通常很短)没有接收到下一字节数据,就会触发空闲中断。利用空闲中断的这个特性,可以实现串口数据的不定长接收。

1、cubemx配置

(1)串口选择异步模式,波特率9600,打开串口接收中断

(2)打开dma接收、发送请求,选择normal搬运,数据类型设置为字节

2、在初始化中加入以下代码:空闲中断使能、打开DMA发送、接收请求

  1. __HAL_UART_CLEAR_IDLEFLAG(&huart1); //空闲中断标志位清除
  2. __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
  3. HAL_UART_Receive_DMA(&huart1, (uint8_t *)rx, 20);
  4. HAL_UART_Transmit_DMA(&huart1, (uint8_t *)rx,20);

3、在stm32g4xx_it.c中找到USART1_IRQHandler(void),重写中断服务函数

  1. void USART1_IRQHandler(void)
  2. {
  3. /* USER CODE BEGIN USART1_IRQn 0 */
  4. /* USER CODE END USART1_IRQn 0 */
  5. //HAL_UART_IRQHandler(&huart1); //屏蔽
  6. /* USER CODE BEGIN USART1_IRQn 1 */
  7. if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)!=RESET)
  8. {
  9. ucTemp=1;
  10. __HAL_UART_CLEAR_IDLEFLAG(&huart1);
  11. HAL_UART_DMAStop(&huart1);
  12. idle_rxcallback(&huart1);
  13. }
  14. /* USER CODE END USART1_IRQn 1 */
  15. }

        将中断函数中的回调函数HAL_UART_IRQHandler(&huart1)屏蔽掉,检查空闲中断的标志位,若置位则将uc_Temp置1,然后清除空闲中断标志位(若不清除程序会一直卡在中断里,导致其余代码无法执行)。清除标志位之后停止DMA,然后调用idle_rxcallback(&huart1);回调函数。

注意:回调函数是自己编写,什么名字都可以!!!

不要开启其它串口中断,否则程序可能会卡死在串口中断中。

4、编写空闲中断回调函数

  1. void idle_rxcallback(UART_HandleTypeDef *huart)
  2. {
  3. rx_num=0;
  4. rx_num=20-__HAL_DMA_GET_COUNTER(&hdma_usart1_rx); //DMA传输的剩余数据量
  5. HAL_UART_Receive_DMA(&huart1, (uint8_t *)rx, 20);
  6. }

        在空闲中断中打开DMA的接收搬运,此代码中我添加了对接收数据的计数,没有这个需求的也可以不加。

5、主函数while接收

  1. if(ucTemp==1)
  2. {
  3. ucTemp=0;
  4. //printf("%s",rx); //串口回显
  5. strcpy(tx,rx);
  6. HAL_UART_Transmit_DMA(&huart1, (uint8_t *)tx,20);//串口回显
  7. sprintf(text,"rx_num:%02d",rx_num);
  8. LCD_DisplayStringLine(Line1, (u8 *)text);
  9. memset(rx,0,sizeof((unsigned char)rx));
  10. memset(tx,0,sizeof((unsigned char)tx));
  11. }

        在主函数中检查uc_Temp标志位,若标志位等于1,则说明空闲中断被触发,一帧串口数据接收完成,可以进行数据处理,处理后,再将标志位置0,等待下一帧数据接收完成。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/737480?site
推荐阅读
相关标签
  

闽ICP备14008679号