STM32CubeMX学习笔记-USART_DMA

STM32CubeMX学习笔记-USART_DMA

  • 一、DMA的概念
  • 二、数据传输方式
    • 普通模式
    • 循环模式
  • 三、以串口方式讲解
    • 串口DMA方式发送函数:HAL_UART_Transmit_DMA
    • 串口DMA方式接收函数:HAL_UART_Receive_DMA
    • 获取未传输数据个数函数:__HAL_DMA_GET_COUNTER
    • 关闭DMA数据流:__HAL_DMA_DISABLE
  • 四、DMA2
    • 4.1 配置串口2
    • 4.2 配置DMA
    • 4.3 生成代码
    • 4.4 USART+DMA数据发送
    • 4.5 USART+DMA数据接收
    • 4.6 串口IDLE空闲中断+DMA数据接收

一、DMA的概念

直接存储器访问(DMA):用于在外设与存储器之间以及存储器与存储器之间进行高速数据传输。DMA传输过程的初始化和启动由CPU完成,传输过程由DMA控制器来执行,无需CPU参与,从而节省CPU资源,提高利用率。
在这里插入图片描述

DMA数据传输的四个要素:
①传输源:DMA数据传输的来源
②传输目标:DMA数据传输的目的
③传输数量:DMA传输数据的数量
④触发信号:启动一次DMA数据传输的动作

STM32的DMA控制器特点
1.STM32F411微控制器具备两个DMA控制器:DMA1和DMA2,每个控制器有8个数据流,每个数据流可以映射到8个通道(或请求);
2.每一个DMA控制器用于管理一个或多个外设的存储器访问请求,并通过总线仲裁器来协调各个DMA请求的优先级;
3.数据流(stream)是用于连接传输源和传输目标的数据通路,每个数据流可以配置为不同的传输源和传输目标,这些传输源和传输目标称为通道(Channel);
4.具备16字节的FIFO。使能FIFO功能后,源数据先送入FIFO,达到FIFO的触发阈值后,再传送到目标地址。

二、数据传输方式

普通模式

传输结束后(即要传输数据的数量达到零),将不再产生DMA操作。若开始新的DMA传输,需在关闭DMA通道情况下,重新启动DMA传输。

循环模式

可用于处理环形缓冲区和连续数据流(例如ADC扫描模式)。当激活循环模式后,每轮传输结束时,要传输的数据数量将自动用设置的初始值进行加载,并继续响应DMA请求。

三、以串口方式讲解

串口DMA方式发送函数:HAL_UART_Transmit_DMA

函 数 原 型 | HAL_StatusTypeDef HAL_UART_Transmit_DMA (UART_HandleTypeDef *huart,uint8_t *pData, uint16_t Size)
------------------ | ---------------DMA
功能描述 | 在DMA方式下发送一定数量的数据
入口参数1 | huart:串口句柄的地址
入口参数2 | pData:待发送数据的首地址
入口参数3 | Size:待发送数据的个数
返回值 | HAL状态值:HAL_OK表示发送成功;HAL_ERROR表示参数错误;HAL_BUSY表示串口被占用
注意事项 | 1.该函数将启动DMA方式的串口数据发送2.完成指定数量的数据发送后,可以触发DMA中断,在中断中将调用发送中断回调函数HAL_UART_TxCpltCallback进行后续处理3.该函数由用户调用

串口DMA方式接收函数:HAL_UART_Receive_DMA

函 数 原 型HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart,uint8_t *pData, uint16_t Size)
功能描述在DMA方式下接收一定数量的数据
入口参数1huart:串口句柄的地址
入口参数2pData:待收数数据的首地址
入口参数3Size:待收数数据的个数
返回值HAL状态值:HAL_OK表示发送成功;HAL_ERROR表示参数错误;HAL_BUSY表示串口被占用
注意事项1.该函数将启动DMA方式的串口数据接收2.完成指定数量的数据接收后,可以触发DMA中断,在中断中将调用接收中断回调函数HAL_UART_RxCpltCallback进行后续处理3.该函数由用户调用

获取未传输数据个数函数:__HAL_DMA_GET_COUNTER

函 数 原 型HAL_DMA_GET_COUNTER(HANDLE)
功能描述获取DMA数据流中未传输数据的个数
参数HANDLE_:串口句柄的地址
返回值NDTR寄存器的内容,即DMA数据流中无传输数据的个数
注意事项1.该函数是宏函数,进行宏替换,不发生函数调用2.该函数需要由用户调用,用于获取未传输数据的个数

关闭DMA数据流:__HAL_DMA_DISABLE

函数原型HAL_DMA_DISABLE(HANDLE_)
功能描述关闭指定的DMA数据流
参数HANDLE_:串口句柄的地址
返回值
注意事项1.该函数是宏函数,进行宏替换,不发生函数调用2.该函数需要由用户调用,用于关闭指定的DMA数据流3.关闭DMA数据流后触发DMA中断,最终调用串口收发的回调函数

四、DMA2

4.1 配置串口2

Connectivity 中选择 USART2 设置,并选择 Asynchronous 异步通信
基础参数:波特率为115200 Bits/s。传输数据长度为8 Bit奇偶检验无,停止位1 接收和发送都使能
在这里插入图片描述
NVIC Settings 一栏使能接收中断
在这里插入图片描述

4.2 配置DMA

在这里插入图片描述
根据DMA通道预览可以知道,点击 DMA Settings 添加 USART2 TX 和 USART2 RX 分别对应DMA1 的通道5和通道6。

●Direction: 传输方向

外设到内存 Peripheral To Memory
内存到外设 Memory To Peripheral
内存到内存 Memory To Memory
外设到外设 Peripheral To Peripheral

●Priority: 传输速度

最高优先级 Very Hight
高优先级 Hight
中等优先级 Medium
低优先级;Low

当发生多个 DMA 通道请求时,就意味着有先后响应处理的顺序问题,这个就由仲裁器也管理。仲裁器管理 DMA 通道请求分为两个阶段。第一阶段属于软件阶段,可以在 DMA_CCRx 寄存器中设置,有 4 个等级:非常高、高、中和低四个优先级。第二阶段属于硬件阶段,如果两个或以上的 DMA 通道请求设置的优先级一样,则他们优先级取决于通 道编号,编号越低优先权越高,比如通道 0 高于通道 1。在大容量产品和互联型产品中,DMA1 控制器拥有高于 DMA2 控制器的优先级。

■DMA Request Setting: DMA传输的对应外设

●Mode:传输模式

Normal 正常模式。表示当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次。
Circular 循环模式。表示传输完成后又重新开始继续传输,不断循环永不停止。

●Increment Address:

Peripheral 表示外设地址自增。
Memory 表示内存地址自增。

串口发送数据是将数据不断存进串口的发送数据寄存器(USARTx_TDR)。所以外接的地址是不递增。而内存储器存储的是要发送的数据,所以地址指针要递增才能将所以的数据发送出去。

●Data Width:
Byte 一个字节。
Half Word 半个字,等于两字节。
Word 一个字,等于四字节。
串口数据发送寄存器只能存储8bit,每次发送一个字节,所以数据长度选择Byte。
在这里插入图片描述

4.3 生成代码

输入项目名和项目路径
在这里插入图片描述

选择应用的 IDE 开发环境 MDK-ARM V5
在这里插入图片描述

每个外设生成独立的 ’.c/.h’ 文件
不勾:所有初始化代码都生成在 main.c
勾选:初始化代码生成在对应的外设文件。 如 GPIO 初始化代码生成在 gpio.c 中。
在这里插入图片描述

点击 GENERATE CODE 生成代码
在这里插入图片描述

4.4 USART+DMA数据发送

新建一个变量

uint8_t sendBuff[] = "USART test by DMA\r\n";

在 man.c 中的主循环添加以下代码:

  /* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */HAL_UART_Transmit_DMA(&huart2, (uint8_t *)sendBuff, sizeof(sendBuff));HAL_Delay(1000);/* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

通过串口助手可以看到在接收区有数据不断的打印输出
在这里插入图片描述

注意:如果不开启串口中断,则程序只能发送一次数据,程序不能判断DMA传输是否完成,USART一直处于busy状态。

4.5 USART+DMA数据接收

/*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 */uint8_t rxSize = 1;/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_DMA_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */HAL_UART_Receive_DMA(&huart2, (uint8_t *)Buffer, rxSize);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

stm32f1xx_it.c 这个文件的最下面添加 HAL_UART_RxCpltCallback()

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if (huart->Instance == USART2){// 在这里处理接收到的数据,例如将数据存储到缓冲区或者显示在UI上memcpy(Buffer, (uint8_t *)&huart2->Instance->DR, rxSize);HAL_UART_Receive_DMA(&huart2, (uint8_t *)Buffer, rxSize);}
}

通过串口助手发送 OK,可以看到接收到 O,这是因为设置的接收数据是一个字符,如果要接收更多字符,请加大 Buffer。
在这里插入图片描述

4.6 串口IDLE空闲中断+DMA数据接收

特点:

●可以实现任意字符串接收并输出。
●在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断。
在 main.c 中添加以下变量:

uint8_t recvBuff[BUFFER_SIZE];  //接收数据缓存数组
volatile uint8_t recvLength = 0;  //接收一帧数据的长度
volatile uint8_t recvDndFlag = 0; //一帧数据接收完成标志

在 main.h 中添加以下宏定义与变量:

#define BUFFER_SIZE 256
extern uint8_t recvBuff[BUFFER_SIZE];  //接收数据缓存
extern volatile uint8_t recvLength;  //接收一帧数据的长度
extern volatile uint8_t recvDndFlag; //一帧数据接收完成标志

在 main.c 中,while 循环前,串口初始化后,添加空闲中断和DMA接收开启函数,这样在第一次接收到数据的时候才会触发中断。

/*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_DMA_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能IDLE中断HAL_UART_Receive_DMA(&huart1, recvBuff, BUFFER_SIZE);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

stm32f1xx_it.c 这个文件的最下面修改 USART1_IRQHandler()

void USART1_IRQHandler(void)
{/* USER CODE BEGIN USART1_IRQn 0 */uint32_t tmpFlag = 0;uint32_t temp;tmpFlag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位if((tmpFlag != RESET))//idle标志被置位{ __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位HAL_UART_DMAStop(&huart1); //temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 获取DMA中未传输的数据个数   recvLength  =  BUFFER_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数recvDndFlag  = 1;   // 接受完成标志位置1    HAL_UART_Transmit_DMA(&huart1, recvBuff, recvLength);recvLength = 0;//清除计数recvDndFlag = 0;//清除接收结束标志位memset(recvBuff,0,recvLength);HAL_UART_Receive_DMA(&huart1, recvBuff, BUFFER_SIZE);//重新打开DMA接收,不然只能接收一次数据}/* USER CODE END USART1_IRQn 0 */HAL_UART_IRQHandler(&huart1);/* USER CODE BEGIN USART1_IRQn 1 *//* USER CODE END USART1_IRQn 1 */
}

通过串口助手发送不定长数据
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/99816.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在Apache和Resin环境中实现HTTP到HTTPS的自动跳转:一次全面的探讨与实践

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

【MySQL】基本查询(二)

文章目录 一. 结果排序二. 筛选分页结果三. Update四. Delete五. 截断表六. 插入查询结果结束语 操作如下表 //创建表结构 mysql> create table exam_result(-> id int unsigned primary key auto_increment,-> name varchar(20) not null comment 同学姓名,-> chi…

解决yolo无法指定显卡的问题,实测v5、v7、v8有效

方法1 基本上这个就能解决了!!! 在train.py的最上方加上下面这两行,注意是最上面,其次指定的就是你要使用的显卡 import os os.environ[CUDA_VISIBLE_DEVICES]6方法2: **问题:**命令行参数指…

C#:出题并判断

C#:出题并判断 //出题并判断 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace Test_…

# 解析Pikachu靶场:一个安全研究的练习场

引言 Pikachu靶场是一个非常流行的安全研究和渗透测试练习平台。这个环境包括多个安全漏洞,从基础的到高级的,供安全研究人员和渗透测试者进行实验和学习。在这篇博客中,我们将探讨Pikachu靶场的基本概念,功能,以及如…

使用安卓Termux+Hexo,手机也能轻松搭建个人博客网站

文章目录 前言1.安装 Hexo2.安装cpolar3.远程访问4.固定公网地址5.结语 前言 Hexo 是一个用 Nodejs 编写的快速、简洁且高效的博客框架。Hexo 使用 Markdown 解析文章,在几秒内,即可利用靓丽的主题生成静态网页。 下面介绍在Termux中安装个人hexo博客并…

stl 输入输出流

标准输入输出流 头文件 iostream 从标准输入读取流 cin >> 从标准输出写入流 cout << get 系列函数 get 无参数&#xff1a;cin.get() 从指定的输入流中提取一个字符&#xff08;包括空白字符&#xff09;&#xff0c;若读取成功&#xff0c;返回该字符的 ASC…

论文分享 | 利用单模态自监督学习实现多模态AVSR

本次分享上海交通大学发表在 ACL 2022 会议 的论文《Leveraging Unimodal Self-Supervised Learning for Multimodal AVSR》。该论文利用大规模单模态自监督学习构建多模态语音识别模型。 论文地址&#xff1a; https://aclanthology.org/2022.acl-long.308.pdf 代码仓库&am…

css 写带三角形的对话框,空心的三角形边框

首先&#xff0c;我们要会先实现一个小三角形&#xff1b; 思路&#xff1a;利用元素的 border 属性&#xff0c;将其三个方向的 border-color 值设为透明色&#xff08;或者和其父元素的背景色一致&#xff0c;形成视觉差&#xff0c;俗称障眼法&#xff09;&#xff0c;剩下…

操作系统学习笔记--进程与线程

进程 概念 不同的角度有不同的定义 进程是程序的一次执行过程进程是一个程序及其数据在处理机上顺序执行时所发生的活动进程是具有独立功能的程序在一个数据集合上运行的过程&#xff0c;它是系统进行资源分配和调度的一个独立单位 进程&#xff1a;是动态的&#xff0c;是…

ESP-07S进行TCP 通信测试

一&#xff0c;TCP Server 为 AP 模式&#xff0c;TCP Client 为 Station 模式。 这里电脑pc作为TCP Server&#xff0c;ESP-07S作为TCP Client 。 二&#xff0c;电脑端配置。 1&#xff0c;开启热点。 2&#xff0c;转到“设置”&#xff0c;编辑热点信息。 3&#xff0c;关闭…

nio 文件传输

transferto方法一次只能传输2个g的数据 文件大于2个g时

动态壁纸软件iWall mac中文特色

iWall for mac是一款动态壁纸软件&#xff0c;它可以使用任何格式的漂亮视频(无须转换)&#xff0c;音频(可视化功能)&#xff0c;图片&#xff0c;动画&#xff0c;Flash&#xff0c;gif&#xff0c;swf&#xff0c;程序&#xff0c;网页&#xff0c;网站做为您的动态壁纸&…

90后整顿秦始皇老板

我的日常就像跑步机上急速前行的仓鼠&#xff0c;使劲往前冲&#xff0c;心有余力力有限。 我在一个电商运营公司做策划和写文案&#xff0c;每天总是加不完的班&#xff0c;从来没见过下午六点钟的太阳。 我做文案吗&#xff1f;唉&#xff0c;说实话&#xff0c;我倒觉得大…

HP打印机一点击打印就出现Windows资源管理器已停止工作问题解决

本次处理的打印机型号是HP Officejet 200 移动便携式打印机&#xff0c;不过其他型号如果出现类似现象&#xff0c;解决方法应该是一致的。 在弹出Windows资源管理器已停止工作的报错提示框后&#xff0c;点击左下角的详细信息&#xff0c;看到的内容显示是KernelBase.dll崩溃…

第二证券:汽车产业链股活跃,恒勃股份、博俊科技“20cm”涨停

轿车产业链股9日盘中走势活跃&#xff0c;截至发稿&#xff0c;恒勃股份、博俊科技“20cm”涨停&#xff0c;德迈仕涨超17%&#xff0c;上声电子涨超14%&#xff0c;川环科技涨超10%&#xff0c;圣龙股份、科华控股、沪光股份、上海沿浦、日盈电子、赛力斯等均涨停。 工作方面…

Feign(替代RestTemplate)远程调用

Feign初步学习 定义 Feign 是一个基于 Java 的 HTTP 客户端库&#xff0c;它是 Spring Cloud 中的一部分&#xff0c;用于简化微服务之间的 HTTP 通信。与传统的使用 RestTemplate 来调用 RESTful 服务不同&#xff0c;Feign 提供了一种声明式、基于接口的方式来定义和调用 H…

XLSX.utils.sheet_to_json()解析excel,给空的单元格赋值为空字符串

前言 今天用到XLSX来解析excel文件&#xff0c;调用XLSX.utils.sheet_to_json(worksheet)&#xff0c;发现如果单元格为空的话&#xff0c;解析出来的结果&#xff0c;就会缺少相应的key&#xff08;如图所示&#xff09;。但是我想要单元格为空的话&#xff0c;值就默认给空字…

HarmonyOS/OpenHarmony原生应用开发-华为Serverless认证服务说明(二)

一、支持HarmonyOS(Stage模型-API9)应用的账户注册登录方式 文档中的TS作者认为就是ArkTS之意。暂时支持四种模式&#xff0c;手机、邮箱、匿名、自有账户。 二、暂时不支持HarmonyOS(Stage模型-API9)应用的账户注册登录方式 包括华为账户注册登录&#xff0c;HarmonyOS…

计算机竞赛 题目:基于深度学习的手势识别实现

文章目录 1 前言2 项目背景3 任务描述4 环境搭配5 项目实现5.1 准备数据5.2 构建网络5.3 开始训练5.4 模型评估 6 识别效果7 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的手势识别实现 该项目较为新颖&#xff0c;适合作为竞赛课题…