【STM32のHAL库开发】用DMA中断来接收串口数据

需求:

只有一个串口USART1,与以往用DMA+IDLE中断接收数据不同,这个串口在不停地发送数据(25bytes * 100Hz),因此IDLE中断不仅仅由接收事件产生,也在不停地由发送事件产生;此外还有一些其它的问题。正好从没用过DMA接收中断函数,遂决定尝试通过DMA传输完成中断(DMA_IT_TC)中接收数据,结果意外地好使。

CubeMX配置:

用的单片机是F070F6P6,一个很便宜很好焊的TSSOP20单片机;HAL库是通用的,串口DMA配置如下:在这里插入图片描述

main函数初始化

在程序初始化时开启DMA接受(用usart1,接收到uint8_t RX_BUFF[]数组中,接收数据包长度固定为64);开启DMA接收完成中断;关闭DMA发送完成中断:

  HAL_UART_Receive_DMA(&huart1, RX_BUFF, 64);
  __HAL_DMA_ENABLE_IT(&hdma_usart1_rx, DMA_IT_TC);
  __HAL_DMA_DISABLE_IT(&hdma_usart1_tx, DMA_IT_TC);

DMA中断函数

串口1接收挂在DMA1通道3上。以下函数逐行注释:

/**
  * @brief This function handles DMA1 channel 2 and 3 interrupts.
  */
void DMA1_Channel2_3_IRQHandler(void)
{
	int data;
  /* USER CODE BEGIN DMA1_Channel2_3_IRQn 0 */
  if(__HAL_DMA_GET_FLAG(&hdma_usart1_rx, DMA_FLAG_TC3)){
    //清串口状态寄存器
    data = USART1->ISR;
    data = USART1->RDR;

    if(RX_BUFF[0]==0xd1&&RX_BUFF[63]==0xd1){
      //帧校验通过
      //我在TIM16定时器中断中发送S.BUS数据,这里先停掉定时器
      TIM16->CR1 &= ~0x01;
      //等待DMA发送完成
      while(__HAL_DMA_GET_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2)){}
      __HAL_DMA_CLEAR_FLAG(&hdma_usart1_tx, DMA_FLAG_TC2);
      //停掉DMA。只有停掉DMA才能重新启动下一次接收。
      HAL_UART_DMAStop(&huart1);

      //此处处理接收到的数据
      
      //使用普通方式发送一些数据作为应答
      HAL_UART_Transmit(&huart1, (uint8_t *)(&RXer), 64, 99);

      //发送完成了,重启定时器
      TIM16->CR1 |= 0x01;
    }
    //清空接收缓存
    memset(RX_BUFF, 0, DMA_SIZE);
    //清中断
    __HAL_DMA_CLEAR_FLAG(&hdma_usart1_rx, DMA_FLAG_TC3);
    //重启一次接收
    HAL_UART_Receive_DMA(&huart1, RX_BUFF, 64);
  }

  /* USER CODE END DMA1_Channel2_3_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart1_tx);
  HAL_DMA_IRQHandler(&hdma_usart1_rx);
  /* USER CODE BEGIN DMA1_Channel2_3_IRQn 1 */

  /* USER CODE END DMA1_Channel2_3_IRQn 1 */
}

记得清中断并重启发送。

XCOM测试结果:

乱码是串口一直在发的16进制数据,文本 report cfg file 209.\r\n 则表明它每次发送都正常进了中断;再次进也没有问题。
在这里插入图片描述

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32 HAL库中,可以使用DMA方式进行串口接收AD数据。可以使用函数HAL_UART_Receive_DMA来实现。该函数的参数包括UART句柄、接收数据缓冲区的指针和待接收数据的个数。通过调用该函数,可以在DMA方式下接收一定数量的数据。\[2\] 例如,可以使用以下代码来实现DMA方式下的串口接收AD数据: ```c uint8_t adData\[10\]; // 定义接收数据缓冲区 HAL_UART_Receive_DMA(&huart1, adData, 10); // 使用DMA方式接收10个字节的数据 ``` 在接收完成后,可以在DMA中断中调用串口接收中断回调函数HAL_UART_RxCpltCallback进行后续处理。在该回调函数中,可以对接收到的AD数据进行处理。\[2\] ```c void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // 在这里进行接收数据的处理 // adData数组中存放了接收到的AD数据 } ``` 需要注意的是,在使用DMA方式进行串口接收时,需要配置DMA通道和DMA传输方向。具体的配置可以参考STM32 HAL库的相关文档和例程。 #### 引用[.reference_title] - *1* *2* *3* [[016] [STM32] 串口HAL库轮询、中断DMA方式传输数据](https://blog.csdn.net/kouxi1/article/details/123876915)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值