IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 基于HAL库的STM32的串口DMA发送数据(解决只发送一次数据)及DMA+空闲中断接受数据 -> 正文阅读

[嵌入式]基于HAL库的STM32的串口DMA发送数据(解决只发送一次数据)及DMA+空闲中断接受数据

目录

前提回顾

配置串口的DMA发送数据和空闲中断+DMA接受数据

关于串口的DMA发送只发送一次的问题解决

前人经验(DMA初始化在串口初始化之前,这里我只用了串口1的DMA发送)?

我遇到的坑点

DMA+空闲中断


前提回顾

通过CUBEMX配置串口以DMA方式发送。

为什么使用DMA,DMA可以为外设和内存提供一条数据通道,使得数据的复制不需要CPU去参与,减低CPU的负担,在实时性的工作时显得格外重要。

通过一般的串口发送数据函数:

   HAL_UART_Transmit(&huart5,(uint8_t*)Rx5sBuf,length,10);      

可以看到有一个等待时间,这里表示CPU参与数据搬运最多等待10ms,所以CPU是在等待串口的。

而配置成DMA发送,基于STM32F103ZET6只有usart1 ,usart2,usart3的发送和接受有DMA模式。串口4,和串口5都只能异步发送(一般我们都使用异步发送数据,只有在某些时序中需要使用到同步)。

再回到串口以DMA的方式发送数据

  HAL_UART_Transmit_DMA(&huart1, (uint8_t *)RX1sBuf, sizeof(RX1sBuf));   

此时没有等待时间,这里表示CPU不需要等待串口,在程序后台DMA通道将数据搬运到串口再发送。这里需要注意的是,虽然cpu无须干预,可以继续执行后面的代码,但DMA将数据从内存(定义数组的位置)搬运到外设(串口)是需要时间的,如果是连续使用DMA串口发送(连续调用上面代码),必然是不合理的,这时需要判断此串口发送所在的DMA通道是否是空闲再继续发送。

在CUBEMX配置时,默认是把DMA的中断打开的,无论是adc的dma还是串口,它们的完成中断都是打开的,为了避免不必要的进入中断,一般我把ADC的DMA中断关闭,把串口的以DMA接受数据的中断也关闭.

如下图中的强制DMA中断?

配置串口的DMA发送数据和空闲中断+DMA接受数据

串口一配置DMA发送和DMA接受(这里以DMA加空闲中断的方式)?

串口接受数据模式normal ,发送数据也为normal。(接受数据若设置为循环模式则不知道接受的数组缓存是否错位,除非在

?

在这里,DMA接受数据的DMA中断关闭,发送数据的DMA中断使能?。(这里的DMA中断是发送数据和接受完数据后会进入中断)

串口全局中断使能。

关于串口的DMA发送只发送一次的问题解决

前人经验(DMA初始化在串口初始化之前,这里我只用了串口1的DMA发送)?

我遇到的坑点

而我则是未打开串口以DMA发送的中断。

这里串口发送用到的是DMA1通道4

?

在stm32f1xx_it.c中看到其通道4的中断函数?

再进入其回调函数 HAL_DMA_IRQHandler

(在传输一半完成中断管理,传输完成中断管理,传输错误中断管理里中做标记处理)

通过点灯判断出了串口DMA发送进入了传输完成中断管理,清除了该dma通道的中断标记位和

设置dma通道为就绪状态以及该dma通道作为资源的释放。

/**
  * @brief  Handles DMA interrupt request.
  * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
  *               the configuration information for the specified DMA Channel.  
  * @retval None
  */
void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
{
  uint32_t flag_it = hdma->DmaBaseAddress->ISR;
  uint32_t source_it = hdma->Instance->CCR;
  
  /* Half Transfer Complete Interrupt management ******************************/
  if (((flag_it & (DMA_FLAG_HT1 << hdma->ChannelIndex)) != RESET) && ((source_it & DMA_IT_HT) != RESET))
  {
    /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
    if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
    {
      /* Disable the half transfer interrupt */
      __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
    }
    /* Clear the half transfer complete flag */
    __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));

    /* DMA peripheral state is not updated in Half Transfer */
    /* but in Transfer Complete case */

    if(hdma->XferHalfCpltCallback != NULL)
    {
      /* Half transfer callback */
      hdma->XferHalfCpltCallback(hdma);
    }
  }

  /* Transfer Complete Interrupt management ***********************************/
  else if (((flag_it & (DMA_FLAG_TC1 << hdma->ChannelIndex)) != RESET) && ((source_it & DMA_IT_TC) != RESET))
  {
    if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
    {
      /* Disable the transfer complete and error interrupt */
      __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);  

      /* Change the DMA state */
      hdma->State = HAL_DMA_STATE_READY;
    }
    /* Clear the transfer complete flag */
      __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
  

    /* Process Unlocked */
    __HAL_UNLOCK(hdma);

    if(hdma->XferCpltCallback != NULL)
    {
      /* Transfer complete callback */
      hdma->XferCpltCallback(hdma);
    }
  }

  /* Transfer Error Interrupt management **************************************/
  else if (( RESET != (flag_it & (DMA_FLAG_TE1 << hdma->ChannelIndex))) && (RESET != (source_it & DMA_IT_TE)))
  {
    /* When a DMA transfer error occurs */
    /* A hardware clear of its EN bits is performed */
    /* Disable ALL DMA IT */
    __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));

    /* Clear all flags */
    hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);

    /* Update error code */
    hdma->ErrorCode = HAL_DMA_ERROR_TE;

    /* Change the DMA state */
    hdma->State = HAL_DMA_STATE_READY;

    /* Process Unlocked */
    __HAL_UNLOCK(hdma);

    if (hdma->XferErrorCallback != NULL)
    {
      /* Transfer error callback */
      hdma->XferErrorCallback(hdma);
    }
  }
  return;
}

最后通过调用

? HAL_UART_Transmit_DMA(&huart1, (uint8_t *)RX1sBuf, sizeof(RX1sBuf));?

完成DMA的数据发送。

一般使用DMA发送数据我还是采用定时发送。

DMA+空闲中断

这个极大地提高了效率,而且简洁,hal库不愧是不断完善的。

相比于之前我用串口接受中断和空闲中断接受数据会接受一个字节就进入接受数据中断。而DMA+空闲中断则是接受完一个数据帧再进入空闲中断。

总共就2个函数解决问题。

 HAL_UARTEx_ReceiveToIdle_DMA(&huart1,Rx1Buf,102); //串口1开启DMA接受

while之前开启数据接受。

再重写其回调函数

//  DMA加串口空闲中断
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if(huart->Instance == USART1)
	{
	//这里的DMA为Normal模式
	//HAL_UART_DMAStop(huart)//如果DMA为Circular模式,回调函数加上stop函数
		//USER_FNC();//用户自定义函数
        
        printf("[RX1:] %s\r\n",Rx1Buf);
        
        
    
        memset(Rx3Buf,0x00,sizeof(Rx1Buf));
        
        
		HAL_UARTEx_ReceiveToIdle_DMA(&huart1,Rx1Buf,102);//继续接收数据
	}
}

效果?

参考博客

STM32使用串口空闲中断(IDLE)和 DMA接收一串数据流_ONE_Day|的博客-CSDN博客_idle标志位

STM32基于HAL库的串口接受中断和空闲中断_昊月光华的博客-CSDN博客_stm32hal库串口空闲中断

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:58:04  更:2022-10-08 20:58:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 19:44:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码