当前位置: 首页 > news >正文

DMA简述与使用实例

之后要学:SPI / IIC+DMA

学习的这位up主的视频:全网最清楚的DMA讲解,三种搬运模式三个例子讲清楚(STM32教程基于HAL库和CUBEIDE)_哔哩哔哩_bilibili

目录

01-基本信息

1-概述

2-方向

3-模式

正常模式

轮询模式

4-地址自增

02-实例一:串口读取陀螺仪

01-基本信息

1-概述

DMA能将外设/内存与外设/内存间建立直接的通道进行数据传输,而无需CPU进行数据的传输,可以将资源用在更合适的地方

2-方向

外设-》内存、内存-》外设,内存-》内存

3-模式

正常模式

只执行一次DMA数据传输,在接收到制定的数据大小之后,结束DMA

轮询模式

可以一直进行数据的传输,不过要注意防止数据的覆盖等,需要特殊的算法进行数据的结算(以后学)

4-地址自增

有这四种自增方式

02-实例一:串口读取陀螺仪

认为适用于接收连续的数据包,协议

1-cubemx配置

配置为正常模式,外设地址不变,内存地址自增

正常模式需要每次调用完成,重新开启DMA,但算法相对简单

当前外设为串口接收寄存器,只有一个地址无需自增

内存需要存放多个数据,所以需要自增,不能覆盖

数据宽度也很重要,但是了解不深,以后再说

串口中断也要打开

在后续处理中,需要用串口中断来进行DMA接收数据完成的判断

2-代码编写

1-初始化

		__HAL_UART_ENABLE_IT(&hlpuart1, UART_IT_IDLE); //使能IDLE//开启DMA接收,HAL_UART_Receive_DMA(&hlpuart1,uart1_rx_buf, UART1_PACK_SIZE);

DMA接收,只需要设定好初始位置,定义好数组大小、接收数据数目比接收的一帧数据大就行,后续会进行处理

使能IDLE,即空闲中断,之后在中断处理函数中进行处理

2-中断处理函数

在stm32g4xx_it.c中

void LPUART1_IRQHandler(void)
{/* USER CODE BEGIN LPUART1_IRQn 0 */extern uint8_t uart1_rx_buf[UART1_PACK_SIZE];//16Byteextern uint16_t uart1_rx_size;extern uint8_t uart1_rx_cplt_flag;uint32_t tmp_flag = 0;uint32_t temp;tmp_flag =__HAL_UART_GET_FLAG(&hlpuart1,UART_FLAG_IDLE); //获取IDLE标志位if((tmp_flag != RESET))//idle标志被置位{ __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);//清除标志位HAL_UART_DMAStop(&hlpuart1);temp  =  __HAL_DMA_GET_COUNTER(&hdma_lpuart1_rx);// 获取DMA中未传输的数据个数   uart1_rx_size =  sizeof(uart1_rx_buf) - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数uart1_rx_cplt_flag = 1;	// 接受完成标志位置1}/* USER CODE END LPUART1_IRQn 0 */HAL_UART_IRQHandler(&hlpuart1);/* USER CODE BEGIN LPUART1_IRQn 1 *//* USER CODE END LPUART1_IRQn 1 */
}

使能IDLE中断后,在串口空闲下便会进入此中断(其他中断会进吗)然后判断串口当前是否空闲,若空闲,代表一帧数据接收完毕,然后结束DMA(之前接收函数比具体数据数量大也没关系就是这个原因,之后会重新开启),使能标志位,之后进行到串口数据处理函数中,便可以进行处理。

ps:一帧数据代表一次发送所有信息,如55 51 aa aa aa 55 52 aa aa aa,此时接受了两个帧头,但因为是一遍发过来的,所以为一帧。

ps:所以单片机,openmv的printf,print发送的是什么呢,是一帧还是一个个发送的呢,或许之后可以用打包函数,直接打包数据发送出去就是一帧

3-串口数据处理函数

uint8_t uart1_receiveData_parse(void)
{uint8_t ret = 1;//如果接收到数据包if(uart1_rx_cplt_flag){//数据处理for(uint8_t i=0;i<99;i++){jy901_read_data(uart1_rx_buf[i]);}//清空数据包与标志位memset(uart1_rx_buf, 0, UART1_PACK_SIZE);uart1_rx_cplt_flag = 0;uart1_rx_size = 0;//重新打开DMA接收HAL_UART_Receive_DMA(&hlpuart1,uart1_rx_buf, UART1_PACK_SIZE);	}return ret;
}

注意,这并不是什么接收完成中断之类的,而是一个简单的函数的,需要外界的调用,我将其放在定时器中断函数中,每1ms调用一次函数,则1ms读取一次数据。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • [译] RAGFlow 使用说明
  • yield 详解
  • 基于Material Design风格开源的Avalonia UI控件库
  • 鸿蒙OS试题(4)
  • Docker深度探索:精通容器化的未来技术
  • 【NO.15】LeetCode经典150题-135. 分发糖果
  • C#高效内存管理:运用对象池与结构体优化技术
  • 文件上传的学习
  • 功能强大的开源数据中台系统 DataCap 2024.03.9 发布
  • 理解 Maven 依赖范围及编译与运行时的需求
  • C#文件的输入和输出
  • 产品入门篇笔记
  • 2024年国家自然科学基金即将公布,如何第一时间知道评审结果?
  • priority_queue的使用方法
  • 树状数组C/C++实现
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • 2017年终总结、随想
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • Django 博客开发教程 8 - 博客文章详情页
  • jQuery(一)
  • mysql外键的使用
  • React系列之 Redux 架构模式
  • Ruby 2.x 源代码分析:扩展 概述
  • Spark VS Hadoop:两大大数据分析系统深度解读
  • spark本地环境的搭建到运行第一个spark程序
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 聊一聊前端的监控
  • 批量截取pdf文件
  • 用mpvue开发微信小程序
  • NLPIR智能语义技术让大数据挖掘更简单
  • 专访Pony.ai 楼天城:自动驾驶已经走过了“从0到1”,“规模”是行业的分水岭| 自动驾驶这十年 ...
  • ​Benvista PhotoZoom Pro 9.0.4新功能介绍
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • #QT(TCP网络编程-服务端)
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (函数)颠倒字符串顺序(C语言)
  • (力扣)循环队列的实现与详解(C语言)
  • (六)DockerCompose安装与配置
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (三)docker:Dockerfile构建容器运行jar包
  • (学习日记)2024.02.29:UCOSIII第二节
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .NET I/O 学习笔记:对文件和目录进行解压缩操作
  • .Net 基于.Net8开发的一个Asp.Net Core Webapi小型易用框架
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • .Net程序猿乐Android发展---(10)框架布局FrameLayout
  • .NET的数据绑定
  • .net实现客户区延伸至至非客户区
  • .net网站发布-允许更新此预编译站点
  • @JSONField或@JsonProperty注解使用
  • @RequestParam详解
  • [000-002-01].数据库调优相关学习