STM32——DMA

STM32——DMA

1.DMA介绍

什么是DMA?

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

DMA是一个数据搬运工

DMA的意义

代替 CPU 搬运数据,为 CPU 减负。

  1. 数据搬运的工作比较耗时间;

  2. 数据搬运工作时效要求高(有数据来就要搬走);

  3. 没啥技术含量(CPU 节约出来的时间可以处理更重要的事)。

搬运什么数据?

存储器、外设

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

三种搬运方式:

  • 存储器→存储器(例如:复制某特别大的数据buf)
  • 存储器→外设 (例如:将某数据buf写入串口TDR寄存器)
  • 外设→存储器 (例如:将串口RDR寄存器写入某数据buf)

存储器→存储器
在这里插入图片描述

存储器->外设
在这里插入图片描述

外设->存储器
在这里插入图片描述

2.实验一、内存到内存搬运

实验要求

使用DMA的方式将数组A的内容复制到数组B中,搬运完之后将数组B的内容打印到屏幕。

用到的库函数

  1. HAL_DMA_Start
HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress,
uint32_t DstAddress, uint32_t DataLength)

参数一:DMA_HandleTypeDef *hdma,DMA通道句柄

参数二:uint32_t SrcAddress,源内存地址

参数三:uint32_t DstAddress,目标内存地址

参数四:uint32_t DataLength,传输数据长度。注意:需要乘以sizeof(uint32_t)

返回值:HAL_StatusTypeDef,HAL状态(OK,busy,ERROR,TIMEOUT)

  1. __HAL_DMA_GET_FLAG
#define __HAL_DMA_GET_FLAG(__HANDLE__, __FLAG__) (DMA1->ISR & (__FLAG__))

参数一:HANDLE,DMA通道句柄

参数二:FLAG,数据传输标志。DMA_FLAG_TCx表示数据传输完成标志

返回值:FLAG的值(SET/RESET)

代码实现

  1. 开启数据传输

  2. 等待数据传输完成

  3. 打印数组内容

#define BUF_SIZE 16
// 源数组
uint32_t srcBuf[BUF_SIZE] = {
    0x00000000,0x11111111,0x22222222,0x33333333,
    0x44444444,0x55555555,0x66666666,0x77777777,
    0x88888888,0x99999999,0xAAAAAAAA,0xBBBBBBBB,
    0xCCCCCCCC,0xDDDDDDDD,0xEEEEEEEE,0xFFFFFFFF
};
// 目标数组
uint32_t desBuf[BUF_SIZE];
int fputc(int ch, FILE *f)
{
    unsigned char temp[1]={ch};
    HAL_UART_Transmit(&huart1,temp,1,0xffff);
    return ch;
}
main函数里:
    // 开启数据传输
    HAL_DMA_Start(&hdma_memtomem_dma1_channel1,
                  (uint32_t)srcBuf, (uint32_t)desBuf, sizeof(uint32_t) * BUF_SIZE);
// 等待数据传输完成
while(__HAL_DMA_GET_FLAG(&hdma_memtomem_dma1_channel1, DMA_FLAG_TC1) == RESET);
// 打印数组内容
for (i = 0; i < BUF_SIZE; i++)
    printf("Buf[%d] = %X\r\n", i, desBuf[i]);

3.实验二、内存到外设搬运

实验要求

使用DMA的方式将内存数据搬运到串口1发送寄存器,同时闪烁LED1。

用到的库函数

HAL_UART_Transmit_DMA

HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData,
uint16_t Size)

参数一:UART_HandleTypeDef *huart,串口句柄

参数二:uint8_t *pData,待发送数据首地址

参数三:uint16_t Size,待发送数据长度

返回值:HAL_StatusTypeDef,HAL状态(OK,busy,ERROR,TIMEOUT)

代码实现

  1. 准备数据

  2. 将数据通过串口DMA发送

#define BUF_SIZE 1000
// 待发送的数据
unsigned char sendBuf[BUF_SIZE];
main函数里
    // 准备数据
    for (i = 0; i < BUF_SIZE; i++)
        sendBuf[i] = 'A';
// 将数据通过串口DMA发送
HAL_UART_Transmit_DMA(&huart1, sendBuf, BUF_SIZE);
while (1)
{
    HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_8);
    HAL_Delay(100);
}

3.外设到内存搬运

实验要求

使用DMA的方式将串口接收缓存寄存器的值搬运到内存中,同时闪烁LED1。

用到的库函数

  1. __HAL_UART_ENABLE
#define __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U)
== UART_CR1_REG_INDEX)? ((__HANDLE__)->Instance->CR1 |= ((__INTERRUPT__) &
                                                         UART_IT_MASK)): \
    (((__INTERRUPT__) >> 28U)
     == UART_CR2_REG_INDEX)? ((__HANDLE__)->Instance->CR2 |= ((__INTERRUPT__) &
                                                              UART_IT_MASK)): \
    ((__HANDLE__)->Instance-
     >CR3 |= ((__INTERRUPT__) & UART_IT_MASK)))

参数一:HANDLE,串口句柄

参数二:INTERRUPT,需要使能的中断

返回值:无

  1. HAL_UART_Receive_DMA
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData,uint16_t Size)

参数一:UART_HandleTypeDef *huart,串口句柄

参数二:uint8_t *pData,接收缓存首地址

参数三:uint16_t Size,接收缓存长度

返回值:HAL_StatusTypeDef,HAL状态(OK,busy,ERROR,TIMEOUT)

  1. __HAL_UART_GET_FLAG
#define __HAL_UART_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR &
(__FLAG__)) == (__FLAG__))

参数一:HANDLE,串口句柄

参数二:FLAG,需要查看的FLAG

返回值:FLAG的值

  1. __HAL_UART_CLEAR_IDLEFLAG
#define__HAL_UART_CLEAR_IDLEFLAG(__HANDLE__)__HAL_UART_CLEAR_PEFLAG(__HANDLE__)

参数一:HANDLE,串口句柄

返回值:无

  1. HAL_UART_DMAStop
HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart)

参数一:UART_HandleTypeDef *huart,串口句柄

返回值:HAL_StatusTypeDef,HAL状态(OK,busy,ERROR,TIMEOUT)

  1. __HAL_DMA_GET_COUNTER
#define __HAL_DMA_GET_COUNTER(__HANDLE__) ((__HANDLE__)->Instance->CNDTR)

参数一:HANDLE,串口句柄

返回值:未传输数据大小

代码实现

main.c

uint8_t rcvBuf[BUF_SIZE]; // 接收数据缓存数组
uint8_t rcvLen = 0; // 接收一帧数据的长度
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); // 使能IDLE空闲中断
HAL_UART_Receive_DMA(&huart1,rcvBuf,100); // 使能DMA接收中断
while (1)
{
    HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_8);
    HAL_Delay(300);
}

main.h

#define BUF_SIZE 100

stm32f1xx_it.c

extern uint8_t rcvBuf[BUF_SIZE];
extern uint8_t rcvLen;
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 */
    if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) == SET)) // 判断IDLE标志位是否被置位
    {
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);// 清除标志位
        HAL_UART_DMAStop(&huart1); // 停止DMA传输,防止干扰
        uint8_t temp=__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
        rcvLen = BUF_SIZE - temp; //计算数据长度
        HAL_UART_Transmit_DMA(&huart1, rcvBuf, rcvLen);//发送数据
        HAL_UART_Receive_DMA(&huart1, rcvBuf, BUF_SIZE);//开启DMA
    }
    /* USER CODE END USART1_IRQn 1 */
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

移动端设计规范 - 文字使用规范

这是一篇关于移动端产品界面设计时&#xff0c;文字大小的使用规范&#xff0c;前端人员如果能了解一点的话&#xff0c;在实际开发中和设计沟通时&#xff0c;节省沟通成本&#xff0c;也能提高设计落地开发时的还原度。 关于 在做移动端产品设计时&#xff0c;有时候使用文字…

fpmarkets实例讲解止损,控制风险如此简单

止损和止盈是交易者在交易时都需要了解的两个基本设置&#xff0c;在上篇文章fpmarkets澳福和各位投资者分享 了止盈如何工作&#xff0c;今天我们继续实例讲解止损&#xff0c;在交易中控制不必要的风险。 止损单是基本交易订单之一。如果市场走向与预期相反&#xff0c;它会限…

[机器学习]LFM梯度下降算法

一.LFM梯度下降算法 2.代码实现 # 0. 引入依赖 import numpy as np import pandas as pd# 1. 数据准备 # 评分矩阵R R np.array([[4,0,2,0,1],[0,2,3,0,0],[1,0,2,4,0],[5,0,0,3,1],[0,0,1,5,1],[0,3,2,4,1],]) # 二维数组小技巧&#xff1a;取行数R.shape[0]和len(R)&#x…

【SPIE独立出版|长春理工大学主办】2024年第四届数字信号与计算机通信国际学术会议(DSCC 2024)

DSCC 2024已通过SPIE出版社审核&#xff0c;ISSN号已确定&#xff1a;ISSN: 0277-786X&#xff0c;往届均已见刊EI检索&#xff01; 2024年第四届数字信号与计算机通信国际学术会议&#xff08;DSCC 2024&#xff09; 2024 4th International Conference on Digital Signal and…

Windows Server 2025 Azure Arc 介绍

Azure Arc 是一个扩展 Azure 平台的桥梁&#xff0c;可帮助你构建可灵活地跨数据中心、边缘和多云环境运行的应用程序和服务。使用一致的开发、操作和安全模型来开发云原生应用程序。 Azure Arc 可在新的和现有的硬件、虚拟化和 Kubernetes 平台、物联网设备和集成系统上运行。…

Flutter 开发3:创建第一个Flutter应用

Step 1: 安装Flutter 1.1 下载Flutter SDK 首先&#xff0c;你需要访问Flutter官方网站下载最新的Flutter SDK。选择适合你操作系统的安装包。 $ cd ~/development $ unzip ~/Downloads/flutter_macos_2.2.3-stable.zip1.2 更新环境变量 接下来&#xff0c;你需要将Flutter…

【项目管理】整合管理

一、管理基础 1、项目整合管理由项目经理负责&#xff0c;项目经理负责整合所有其他知识领域的成果&#xff0c;并掌握项目总体情况。项目整合管理的责任不能被授权或转移&#xff0c;项目经理必须对整个项目承担最终责任。整合是项目经理的一项关键技能。执行项目整合时项目经…

西门子WINCC触摸屏的Audit功能:追溯生产数据与用户操作行为

1为什么要用Audit功能&#xff1f; 在许多工业领域&#xff0c;生产数据的可追溯性及其文档记录变得愈加重要&#xff0c;如医药行业、食品饮料以及相关的机械工程行业。与书面文档相比&#xff0c;以电子形式存储生产数据具有许多优点&#xff0c;如采集和记录数据更方便&…

【HarmonyOS】鸿蒙开发之页面路由——第2.4章

页面路由: 应用程序中实现不同页面之间的跳转和数据传递。 Router有两种页面跳转模式 1.router.pushUrl() 目标耶不会被替换当前页&#xff0c;而是压入页面栈&#xff0c;可以使用router.back()返回当前页 2.router.replaceUrl() 目标替换当前页&#xff0c;当前页会被销毁并…

一文读懂cookie、session和token

HTTP简介 HTTP协议&#xff08;超文本传输协议HyperText Transfer Protocol&#xff09;是一种无状态协议&#xff0c;协议本身不会对发送过的请求和对应的通信状态进行持久化处理。这样的好处是可以保持HTTP协议的简单性&#xff0c;高效率处理大量事务。 但是随之就会出现一…

代码随想录算法训练营第36天(贪心算法05 ● 435. 无重叠区间 ● 763.划分字母区间 ● 56. 合并区间

贪心算法 part05 435. 无重叠区间解题思路 763.划分字母区间解题思路补充 56. 合并区间解题思路不熟悉的基础语法知识 详细布置 今天的三道题目&#xff0c;都算是 重叠区间 问题&#xff0c;大家可以好好感受一下。 都属于那种看起来好复杂&#xff0c;但一看贪心解法&#x…

【C++入门到精通】特殊类的设计 | 单例模式 [ C++入门 ]

阅读导航 引言一、设计模式概念&#xff08;了解&#xff09;二、单例模式1. 饿汉模式&#xff08;1&#xff09;概念&#xff08;2&#xff09;模拟实现&#xff08;3&#xff09;优缺点&#xff08;4&#xff09;适用场景 2. 懒汉模式&#xff08;1&#xff09;概念&#xff…

vue使用富文本

1、安装 cnpm install vue-quill-editor2、在main.js中引入 // 富文本 import VueQuillEditor from vue-quill-editor // require styles 引入样式 import quill/dist/quill.core.css import quill/dist/quill.snow.css import quill/dist/quill.bubble.css Vue.use(VueQuill…

cesium-球体透明

在开发的过程&#xff0c;要求cesium加载的地球透明 只是地表透明还不能满足要求&#xff0c;只加载部分区域的方式来解决的 代码如下&#xff1a; <template><div id"cesiumContainer" style"height: 100vh;"></div><div id"…

【C++进阶08】哈希的应用(位图and布隆过滤器)

一、位图 1.1 位图的概念 面试题 给40亿个不重复的无符号整数&#xff0c;没排过序 给一个无符号整数&#xff0c;如何快速判断一个数是否在 这40亿个数中。【腾讯】 能想到的解决思路&#xff1a; 遍历&#xff0c;时间复杂度O(N)排序(O(NlogN)) 利用二分查找: logN放到哈…

centos搭建ftp踩坑记录

ftp服务器搭建参考b站视频 第1坑&#xff0c;开放端口后仍然无法连接&#xff1a; 这里不仅需要在防火墙打开20和21端口&#xff0c;还需要打开被动访问所使用的端口&#xff0c;也就是在配置文件vsftpd.conf中指定的被动访问接收端口。 pasv_enableYES pasv_min_port40000 p…

小红书论文刷新 SOTA:人体动作预测再升级,能精准到指尖

想象一下&#xff0c;你在玩一款 VR 游戏&#xff0c;准备伸手拿起一个虚拟杯子喝水。‍​​‌​‌​‎‎ 在传统的交互系统中&#xff0c;这通常需要你按下控制器上的特定按钮。但如果游戏集成了 EAI 框架&#xff0c;这一过程将变得无比自然。当你的手缓缓接近虚拟杯子时&…

数据库基础知识(一)

数据库基础知识&#xff08;一&#xff09; 一、数据库基本概念 1.1 数据 数据&#xff08;Data&#xff09;是指对客观事物进行描述并可以鉴别的符号&#xff0c;这 些符号是可识别的、抽象的。它不仅指狭义上的数字&#xff0c;而是有多 种表现形式&#xff1a;字母、文…

如何开通GitHub Copilot

GitHub Copilot 是由GitHub 和OpenAI共同开发的人工智能代码辅助工具&#xff0c;可以自动地生成高质量代码片段、上下文信息等。 通过自然语言处理和机器学习技术&#xff0c;能够通过分析程序员编写的代码、注释和上下文信息&#xff0c;自动生成代码&#xff0c;减轻程序员的…

在线摸头GIF生成系统源码

在线摸头GIF在线生成器html网页源码&#xff0c;可以点击选择文件按钮&#xff0c;或者直接将图片拖入&#xff0c;即可生成导出