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 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 【STM32】HAL库 CubeMX例程九---串口DMA发送及IDLE接收空闲中断(附工程源码) -> 正文阅读

[嵌入式]【STM32】HAL库 CubeMX例程九---串口DMA发送及IDLE接收空闲中断(附工程源码)

前期准备:

  1. STM32CubeMX
  2. STM32RCT6核心板
  3. IDE Keil(MDK-ARM)

关于DMA

1. 什么是DMA?

DMA(Direct Memory Access,直接存储器访问) 提供在外设与存储器存储器和存储器外设与外设之间的高速数据传输使用。它允许不同速度的硬件装置来沟通,而不需要依赖于CPU,在这个时间中,CPU对于内存的工作来说就无法使用。

这里的外设指的是spi、usart、iic、adc等基于APB1 、APB2或AHB时钟的外设,而这里的存储器包括自身的闪存(flash)或者内存(SRAM)以及外设的存储设备都可以作为访问地源或者目的。

2. DMA的意义

传感器A获取到了数据,我需要把获取到的数据交给传感器B使用,正常来说,需要CPU控制,把A获取到的数据赋给B。但如果使用DMA,我可以将A与B之间建立一个专门传输数据的通道,CPU无需介入,对于非常大的数据需要转移时,DMA无疑大大节省了CPU的资源

优点: 控制简单,它适用于数据传输率很高的设备进行成组传送。
缺点: 在DMA控制阶段,CPU无法访问内存,内存的效能没有充分发挥,相当一部分内存工作周期是空闲的。这是因为,外围设备传送两个数据之间的间隔一般总是大于内存存储周期,因此许多空闲的存储周期不能被CPU利用。
在这里插入图片描述

3. DMA的结构器

2个DMA控制器,DMA1有7个通道

在这里插入图片描述
DMA2有5个通道
在这里插入图片描述
1个通道同一时间只能进行一个,例如通道 1 的几个 DMA1 请求(ADC1、TIM2_CH3、TIM4_CH1),这几个是通过逻辑或到通道 1 的,这样我们在同一时间,就只能使用其中的一个。其他通道也是类似的

3. DMA的传输方式

  • DMA_Mode_Normal(正常模式)
    一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次
  • DMA_Mode_Circular(循环传输模式)
    当传输结束时,硬件自动会将传输数据量寄存器进行重装,进行下一轮的数据传输。 也就是多次传输模式

4. DMA及通道的优先级

优先级管理采用软件+硬件:

  • 软件:每个通道的优先级可以在DMA_CCRx寄存器中设置,有4个等级
    最高级>高级>中级>低级

  • 硬件:如果2个请求,它们的软件优先级相同,则较低编号的通道比较高编号的通道有较高的优先权。比如:如果软件优先级相同,通道2优先于通道4

在大容量产品和互联型产品中,DMA1控制器拥有高于DMA2控制器的优先级。

5. DMA中断

DMA的每个通道都有 3 个事件标志(DMA 半传输,DMA 传输完成和 DMA 传输出错),这 3 个事件标志逻辑或成为一个单独的中断请求
可以通过设置寄存器的不同位来打开这些中断
在这里插入图片描述

6.指针递增模式

外设和存储器指针在每次传输后可以自动向后递增或保持常量。当设置为增量模式时,下一个要传输的地址将是前一个地址加上增量值


STM32CubeMX部分

1.配置时钟

在这里插入图片描述
选择STM32F103RCTx系列芯片,配置时钟的同时会自动配置IO口引脚
在这里插入图片描述
将HCLK设置为最大频率72MHz

2.配置USART和DMA

在这里插入图片描述
配置USART,【STM32】HAL库 CubeMX例程三—串口中断通信(2)(附工程源码)文章有讲解过,这里就不再赘述
在这里插入图片描述
DMA Settings ——> Add

在这里插入图片描述
然后选择USART1_RX,接着同样步骤再把USART1_TX添加进来

在这里插入图片描述

  • DMA Request(DMA请求): USART1_RX、USART1_TX
  • Channel(通道): 通道5、通道4
  • Dirction (DMA传输方向): Peripheral To Memory(外设到内存)、Memory To Peripheral(内存到外设 )
  • Priority(优先级): 低、低
  • Mode(模式): 正常、正常
  • Increment Address(地址指针递增): 1.这里因我们是一直往固定外设地址&USART1发送数据,所以地址不递增 2.这里我们的场景是将内存中连续存储单元的数据发送到串口,毫无疑问内存地址是需要递增的
  • Data Width(数据宽度): 字节、字节
    在这里插入图片描述
    USART1使能中断

3.工程生成

在这里插入图片描述
在这里插入图片描述
工程管理依旧是这几个选项,然后GENERATE CODE,STM32CubeMX部分完成

Keil部分

//DMA函数
· HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);串口DMA模式发送
· HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);串口DMA模式接收
· HAL_UART_DMAResume(&huart1); 恢复串口DMA
· HAL_UART_DMAPause(&huart1) 暂停串口DMA
· HAL_UART_DMAStop(&huart1); 结束串口DMA

1. DMA串口发送

在main.c中添加

 /* USER CODE BEGIN Init */
	uint8_t Senbuff[] = "Q大帅のUART DMA Test Success ! \r\n";   

  /* USER CODE END Init */

在while里写入

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff));
		HAL_Delay(1000);		

  }

编译下载时需要选择相对应的下载器,勾选以下
在这里插入图片描述

效果如图

在这里插入图片描述

2. IDLE接收(串口空闲中断接收)

当DMA串口接收开始后,DMA通道会不断的将发送来的数据转移到内存,那该如何判断串口接收是否完成从而及时关闭DMA通道?如何知道接收到数据的长度?答案便是使用串口空闲中断
思路流程:

  1. 开启串口DMA接收
  2. 串口收到数据,DMA不断传输数据到内存
  3. 一帧数据发送完毕,串口暂时空闲,触发串口空闲中断
  4. 在中断服务函数中,可以计算刚才收到了多少个字节的数据
  5. 存储接收到的数据,清除标志位,开始下一帧接收

在原有代码上更改

//在main.c定义3个全局变量
/* USER CODE BEGIN Includes */
uint8_t rx_buffer[100];   //接收数据的数组
volatile uint8_t rx_len = 0; //接收数据的长度
volatile uint8_t recv_end_flag = 0; //接收结束标志位
/* USER CODE END Includes */
  /* USER CODE BEGIN 2 */
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);  //开启空闲中断
HAL_UART_Receive_DMA(&huart1,rx_buffer,100);  //开启DMA接收中断
  /* USER CODE END 2 */

在stm32f1xx_it.c文件中

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 */
  uint8_t tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE状态
  if((tmp_flag != RESET))//判断接收是否结束
    { 
      // recv_end_flag = 1; //接收结束
       __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清楚标志位
       HAL_UART_DMAStop(&huart1); 
       uint8_t temp=__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);                 
       rx_len =100-temp; //计算数据长度
	     HAL_UART_Transmit_DMA(&huart1, rx_buffer,rx_len);//发送数据
       HAL_UART_Receive_DMA(&huart1,rx_buffer,100);//开启DMA
    }
  /* USER CODE END USART1_IRQn 1 */
}

效果如图

在这里插入图片描述
链接:本期内容工程
提取码:koaq

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-23 16:51:02  更:2021-08-23 16:52:55 
 
开发: 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年11日历 -2024/11/25 23:52:17-

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