文章目錄
- 一.概要
- 二.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的負擔。