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

【DMA】DMA入门:外设数据到内存,以串口DMA接收为例,解析底层实现

目录

DMA实战操作(DMA搬运外设数据到内存)

串口相关功能

串口DMA配置

代码编写与底层实现

HAL库代码复用小结


DMA实战操作(DMA搬运外设数据到内存

下文以简单的使用DMA从串口接收数据到内部SRAM,Polling|中断方法 讲解

串口相关功能

串口功能框图:

配置好串口DMA后,如果串口接收到数据,就会发送一个 DMA_request ,通知DMA取走RDR寄存器中的数据(一个字节)。

串口接收过程中有关DMA的寄存器:

串口DMA配置

代码编写与底层实现

编写代码使用串口DMA接收20个字节:

用很简单,但是我们现在关注的是他的底层实现。

DMA不论和谁配合,都是搬运数据,并且给你扔 3 个回调出来:搬运一半回调(半满回调)、搬运完成回调(全满回调)、error回调

上一个实验我们还需要注册回调,但是这里运行了一句话好像就已经什么都帮我们完成了?

进入 HAL_UART_Receive_DMA() 函数,它实际调用的是 UART_Start_Receive_DMA():

我们进入 UART_Start_Receive_DMA() 函数,可以发现这个函数就在注册回调函数:

也就是说,它会把 UART_DMAReceiveCplt() 函数挂载到 DMA 传输完成回调函数上,当DMA传输完成,会自动调用 UART_DMAReceiveCplt() 。

但是 UART_DMAReceiveCplt() 就是串口传输完成回调函数吗?其实不是的,串口传输完成回调函数是 HAL_UART_RxCpltCallback() 。我们将 UART_DMAReceiveCplt() 函数往下翻,会发现它其实最终也是调用 HAL_UART_RxCpltCallback() 串口传输完成回调函数:

在注册完回调函数后,UART_Start_Receive_DMA() 就会开始启动 DMA 搬运数据:

还有一个比较重要的是 DMAR 寄存器,只有这个寄存器被置位为一,UART 才能启用DMA模式接收。

(该语句同样在UART_Start_Receive_DMA()函数体内)

HAL库代码复用小结

通过上面的代码截图,我们可以知道挂载在DMA全满回调上的函数最终调用的就是串口传输完成回调,而DMA错误回调也是,最终会调用串口传输错误回调,相当于所有错误信息在串口传输错误回调函数中汇总了。

这就是HAL库架构与代码复用的冰山一角。

http://www.dtcms.com/a/391590.html

相关文章:

  • Java 中 super 和 this关键字总结
  • 我的创作纪念日 ----- 第512天
  • 【docker】删除镜像
  • 亚马逊 MWS 关键字 API 实战:关键字搜索商品列表接口深度解析与优化方案
  • 博文干货 | Pulsar 平均负载器(AvgShedder)
  • 【硬件】嘉立创专业版layout流程(一)
  • PyQt6之分组框
  • 深度剖析 IM 单聊与群聊架构设计
  • 农业自动化:技术重塑传统农业的新范式
  • Nginx 日志文件在哪?
  • 小程序开发者转多端应用app调整视频播放功能
  • 九、Java-注解
  • Java学习笔记——AI插件、新建模块、算数运算符类型、隐式转换、强制转换、自增自减运算符、赋值运算符、关系运算符、逻辑运算符、三元运算符
  • 【从零开始刷力扣006】leetcode206
  • FreeRTOS——介绍及移植过程
  • Day 07 Physics list-----以B1为例
  • 重读一次IS015765-2,记录对错误和异常处理的方式
  • Edge浏览器CSDN文章编辑时一按shift就乱了(Edge shift键)欧路翻译问题(按Shift翻译鼠标所在段落)
  • SpringIoc 基础练习 验证码
  • 前端项目,CDN预热有什么用?
  • TF卡的存储数据结构—fat32格式
  • led的带宽在模拟太阳光中设备中的影响
  • go资深之路笔记(三) sync.WaitGroup, sync.errgroup和 sync.go-multierror
  • Docker 与数据库环境
  • Node.js 模块系统详解
  • proxy代理应用记录
  • 基于python大数据的汽车数据分析系统设计与实现
  • WebSocket实现原理
  • 从保存到加载Docker镜像文件操作全图解
  • IDEA文件修改后改变文件名和文件夹颜色