GD32F407单片机开发入门(十九)DMA详解及ADC-DMA方式采集含源码

文章目录

    • 一.概要
    • 二.GD32F407VET6单片机DMA外设特点
    • 三.GD32单片机DMA内部结构图
    • 四.DMA各通道请求
    • 五.GD32F407VET6单片机ADC-DMA采集例程
    • 六.工程源代码下载
    • 七.小结

一.概要

基本概念:
DMA是Direct Memory Access的首字母缩写,是一种完全由硬件执行数据交换的工作方式。DMA控制器从CPU接管对总线的控制,不经过CPU直接在内存和外设之间进行批量数据交换。DMA控制器向内存发出地址和控制信号,修改地址,对传送的字的个数计数,并且以中断方式向CPU报告传送操作的结束。 DMA方式一般用于高速传送成组数据。

DMA传输的三大要素:
传输源:DMA控制器从传输源读出数据;
传输目标:DMA控制器将数据传输的目标;
触发信号:用于触发一次数据传输的动作,执行一个单位的传输源至传输目标的数据传输;可以用来控制传输的时机。

DMA的主要优点:
由于CPU根本不参加传送操作,因此就省去了CPU取指令、取数、送数等操作。在数据传送过程中,没有保存现场、恢复现场之类的工作。内存地址修改、传送字个数的计数等等,也不是由软件实现,而是用硬件线路直接实现的。所以DMA方式能满足高速I/O设备的要求,也有利于CPU效率的发挥。

二.GD32F407VET6单片机DMA外设特点

两个AHB主机接口传输数据,一个AHB从机接口配置DMA。
16个通道(每个DMA控制器有8个通道),每个通道连接8个特定的外设请求。
存储器和外设支持单一传输,4拍、8拍和16拍增量突发传输。
当外设和存储器传输数据时,支持存储器切换。
支持软件优先级(低、中、高、超高)和硬件优先级(通道号越低,优先级越高)。
存储器和外设的数据传输宽度可配置:字节,半字,字。
存储器和外设的数据传输支持固定寻址和增量式寻址。
支持循环传输模式。
支持三种传输方式:
– 存储器到外设;
– 外设到存储器;
– 存储器到存储器(仅DMA1支持);
DMA和外设均可配置为传输控制器: – DMA作为传输控制器:可配置数据传输长度,最大为65535。 – 外设作为传输控制器:数据传输的完成取决于外设的最后一个传输请求。
支持单数据传输和多数据传输模式:
– 多数据传输模式:在存储器数据宽度和外设数据宽度不同的时候,自动打包/解包数
据;
– 单数据传输模式:当且仅当FIFO空的时候从源地址读取数据,存进FIFO,然后把
FIFO 的数据写到目标地址。
每个通道有5种类型的事件标志和独立的中断,支持中断的使能和清除。

三.GD32单片机DMA内部结构图

在这里插入图片描述

DMA控制器由4部分组成:

AHB 从接口配置DMA
AHB主接口进行数据传输
仲裁器进行DMA请求的优先级管理
数据处理和计数

寄存器DMA_CHxCTL的PWIDTH和MWIDTH位域决定了外设和存储器的数据传输宽度。DMA控制器支持8位,16位和32位的数据宽度。

四.DMA各通道请求

DMA从外设读数据存储到存储器,大致流程如下图。
在这里插入图片描述
在这里插入图片描述

如下图所示,每个DMA控制器有8个通道,每个通道有多个外设请求。以ADC0为例,可以映射到DMA的Channel0。
在这里插入图片描述

DMA的传输模式:

循环模式:通过寄存器DMA_CHxCTL的CMEN位置1使能,用于处理一个环形的缓冲区,每轮传输结束时数据传输的配置会自动地更新为初始状态,DMA传输会连续不断地进行,一般采用循环模式。

普通模式:在DMA传输结束时,DMA通道被自动关闭,进一步的DMA请求将不被满足。

五.GD32F407VET6单片机ADC-DMA采集例程

STLINK接GD32F407VET6开发板,STLINK接电脑USB口。

在这里插入图片描述

GD32F407VET6开发板的PA4,PA45引脚上的进行 ADC 电压采集,杜邦线连接 PA4,PA5 引脚与 VDD(3.3V)或者GND(0V),就能读到单片机供电的电压值。

主要代码:

#include "gd32f4xx.h"
#include "gd32f4xx_libopt.h"
#include "systick.h"uint16_t adc_value[2];//ADC采样值//ADC配置,DMA配置
void ADC_config(void)
{dma_single_data_parameter_struct  dma_single_data_parameter;rcu_periph_clock_enable(RCU_GPIOA);gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_4);//PA4配置成输入gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_5);//PA5配置成输入//ADC相关时钟配置rcu_periph_clock_enable(RCU_GPIOA);rcu_periph_clock_enable(RCU_DMA1);rcu_periph_clock_enable(RCU_ADC0);adc_clock_config(ADC_ADCCK_PCLK2_DIV6);/* DMA相关配置 DMA1 CH0*/dma_deinit(DMA1, DMA_CH0);dma_single_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));dma_single_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;dma_single_data_parameter.memory0_addr = (uint32_t)(&adc_value);dma_single_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;                         // 存储器地址是否为增量模式dma_single_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;dma_single_data_parameter.circular_mode = DMA_CIRCULAR_MODE_ENABLE;                        // 循环模式dma_single_data_parameter.direction = DMA_PERIPH_TO_MEMORY;                                // 外设到存储器dma_single_data_parameter.number = 2;                                                      // DMA缓存大小dma_single_data_parameter.priority = DMA_PRIORITY_HIGH;dma_single_data_mode_init(DMA1,DMA_CH0,&dma_single_data_parameter);dma_channel_enable(DMA1, DMA_CH0);dma_circulation_enable(DMA1, DMA_CH0);        //ADC相关配置adc_deinit();      // 复位ADCadc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);                         //独立模式adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);               // 扫描模式adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);         // 连续模式adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);                  // 右对齐adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 2);              //读取2通道/* ADC regular channel config */adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_4, ADC_SAMPLETIME_144);//ADC0的通道4adc_regular_channel_config(ADC0, 1, ADC_CHANNEL_5, ADC_SAMPLETIME_144);//ADC0的通道5adc_external_trigger_config(ADC0,ADC_REGULAR_CHANNEL,EXTERNAL_TRIGGER_DISABLE);adc_dma_request_after_last_enable(ADC0);adc_dma_mode_enable(ADC0);adc_enable(ADC0);adc_calibration_enable(ADC0);adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
}uint16_t Vol_Value1,Vol_Value2;//采集到的电压值
int main(void)
{systick_config();//配置系统主频168M,外部8M晶振,配置在#define __SYSTEM_CLOCK_168M_PLL_8M_HXTAL        (uint32_t)(168000000)ADC_config();	//配置ADCwhile(1){Vol_Value1=adc_value[0]*3300/4095;//转换成电压值Vol_Value2=adc_value[1]*3300/4095;//转换成电压值}
}

实验结果:
PA4接GND,PA5接3.3V,用Keil运行程序,全速运行,查看Keil调试Watch界面,如下图,PA4,PA5引脚的采样值adc_value[0]
为0,adc_value[1]为0xfff,对应的电压值为0mV与3300mV,所以ADC DMA采样成功。
在这里插入图片描述

六.工程源代码下载

源码下载链接如下:
CSDN

七.小结

使用DMA进行数据收发能够提高数据传输的效率和可靠性。其次,使用DMA进行串口数据收发可以减轻CPU的负担。

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

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

相关文章

vue报错:Error: Cannot find module ‘is-stream‘

此错误提示 Cannot find module ‘is-stream’ 表明 Node.js 无法找到 is-stream 模块。一般而言,这是由于项目中未安装该模块所导致的。 解决方案: //npm npm install is-stream //yarn yarn add is-stream安装后检查 安装完成之后,你可以再次运行项目…

全局事件总线EventBus的用法

全局事件总线 EventBus 在前端开发中是一种用于实现组件间通信的机制,适用于兄弟组件或跨层级组件间的数据传递。 1. 创建全局 EventBus 实例 在前端项目中,先创建一个全局的 EventBus 实例。在 Vue 中,可以通过创建一个新的 Vue 实例来实现…

SpringBoot 设置HTTP代理访问

SpringBoot 设置HTTP代理访问 遇到这样的一个场景,代码部署到私有服务器上去之后,这台私有服务器a无法直接访问公网,需要通过代理转发到另外一台专门访问公网的服务器b, 让服务器b去请求对应的公网ip,于是就需要设置Http代理。 …

在C# WebApi 中使用 Nacos01:基础安装教程和启动运行

一、JDK的安装 Nacos需要依赖JAVA环境运行,所以需要先安装JDK 1.检查是否安装 可用命令行检查是否安装JDK 直接win+r,cmd: java -version 出现这个说明安装成功 2.下载JDK 访问官网点击下载:

cURL 入门:10 分钟学会用命令行发 HTTP 请求

curl初识 curl 通过 URL 传输数据的命令行工具和库是一个非常强大的命令行工具,用于在网络上传输数据。它支持众多的协议,像 dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt pop3 pop3s rtsp smb smbs smtp smtps…

Redis应用场景实战:穿透/雪崩/击穿解决方案与分布式锁深度剖析

一、缓存异常场景全解与工业级解决方案 1.1 缓存穿透:穿透防御的三重门 典型场景 恶意爬虫持续扫描不存在的用户ID 参数注入攻击(如SQL注入式查询) 业务设计缺陷导致无效查询泛滥 解决方案进化论 第一层防护:布隆过滤器&am…

C# 高效操作excel文件

C#高效操作Excel文件指南 一、主流Excel处理方案对比 方案类型特点适用场景​​EPPlus​​第三方库功能全面,性能好,支持.xlsx复杂Excel操作,大数据量​​NPOI​​第三方库支持.xls和.xlsx,功能全面兼容旧版Excel文件​​Closed…

Rust 学习笔记:结构体(struct)

Rust 学习笔记:结构体(struct) Rust 学习笔记:结构体(struct)结构体的定义和实例化使用字段初始化简写用 Struct Update 语法从其他实例创建实例使用没有命名字段的元组结构来创建不同的类型没有任何字段的…

Dify Agent节点的信息收集策略示例

Dify Agent节点的信息收集策略示例 0. 安装"对话 Agent"插件1. 创建一个 Chatflow2. 创建一个 Agent 节点3. 创建一个条件分支节点4. 在IF分支创建一个LLM节点5. 创建一个直接回复节点6. 在ELSE分支创建一个直接回复节点7. 分布并预览 0. 安装"对话 Agent"…

Qt/C++开发监控GB28181系统/获取设备信息/设备配置参数/通道信息/设备状态

一、前言 设备注册成功后,接下来要做的就是获取设备的信息,尤其是通道信息,根据国标协议,永远只有两个层级,一个是设备,然后就是设备下面多个通道,设备编码在整个系统中唯一,通道编…

金融风控的“天眼”:遥感技术的创新应用

在金融市场的复杂博弈中,风险管控一直是金融机构的核心竞争力。然而,传统的风控手段在应对现代金融市场的快速变化时,往往显得捉襟见肘。 如今,遥感技术的创新应用为金融风控带来了全新的视角和手段。星图云开放平台的遥感金融立体…

HFI笔记

高频分量: 载波频率的一半 选择alfabeta轴进行计算的原因 最终结果: 观测器方程 采样加减分离法-(高低频分离) 高频信号的评论高频载波 转子极性辨识

halcon关闭图形窗口

1、dev_close_window () 调用一次这个函数关闭一个图形窗口,并且先关闭最后打开的那个图形窗口,如果一共打开了N个图形窗口,那么就需要调用dev_close_window N次。

每日算法-250430

每日算法 - 2025年4月30日 记录下今天解决的两道题目。 870. 优势洗牌 (Advantage Shuffle) 题目描述 解题思路与方法 核心思想:贪心策略 (田忌赛马) 这道题的目标是对于 nums1 中的每个元素,找到 nums2 中一个比它小的元素进行配对(如果…

【MySQL】增删改查(CRUD)

目录 一. CRUD是什么 二. Create(新增数据) 2.1 单行数据全列插入 2.2 单行数据指定列插入 2.3 多行数据指定列插入 三. Retrieve (检索/查询) 3.1 全列查询 3.2 指定列查询 3.3 查询字段为表达式 3.4 为查询结果指定别名 3…

电商平台 API 开发实战:京东商品详情数据实时获取接口对接教程

在电商行业竞争日益激烈的当下,实时获取商品详情数据对于市场分析、竞品监控、商品推荐等业务场景至关重要。京东作为国内领先的电商平台,提供了强大的 API 接口,允许开发者获取丰富的商品信息。本文将详细介绍京东商品详情数据实时获取接口的…

YOLO视觉模型可视化训练与推理测试工具

推荐一款YOLO可视化训练测试工具: 对于yolo的训练,新手小白往往无从下手,本章推荐的这款工具可以非常轻易的帮您从模型训练到测试到部署。 下载地址http://www.voouer.com/yolo 可以点击此处跳转。 下载成功后打开这款工具,将会出现图形化界面,类似于下图所示: 当前页是可视…

微调 LLaMA 2:定制大型语言模型的分步指南

微调 LLaMA 2:定制大型语言模型的分步指南 深入了解如何运用新技术在 Google Colab 平台上对 Llama-2 进行微调操作,从而有效克服内存与计算方面的限制,让开源大型语言模型变得更加易于获取和使用。自从 Meta 发布了 LLaMA 的首个版本后&…

探秘明远智睿SSD2351开发板在HMI领域的独特魅力

人机界面(HMI)是人与机器进行交互的重要桥梁,其性能和用户体验直接影响到整个系统的使用效果。明远智睿的SSD2351开发板凭借其出色的性能和丰富的功能,在HMI领域展现出了独特的魅力。 SSD2351开发板的四核1.4GHz处理器具备强大的图…

Keysight万用表使用指南及基于Python采集数据生成Excel文件

文章目录 说明使用的库openpyxlpyvisa 代码说明效果展示参考代码 说明 本文介绍了 Keysight 34465A 的基本使用和 SCPI 指令设置,演示了使用 Python 的 PyVISA 库控制两台 34465A 同时采集数据的完整流程,包括设置采样参数、触发测量、读取数据、使用 O…