欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > GD32F407单片机开发入门(十九)DMA详解及ADC-DMA方式采集含源码

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

2025/5/1 12:45:42 来源:https://blog.csdn.net/zy2232652/article/details/147636752  浏览:    关键词: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的负担。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词