GD32/STM32 ADC/DMA使用指南

首先我們對ADC及DMA的基礎知識作一下簡單介紹。

一、?GD32/STM32? ADC模塊的核心要點

一)、ADC基礎特性

  1. ?12位逐次逼近型?
    GD32/STM32 ADC為12位分辨率,最大量化值為4095(對應3.3V參考電壓),支持0-3.3V模擬輸入范圍。
  2. ?多通道架構?
    • 外部通道:16個(部分型號支持24個外部通道)
    • 內部通道:2個(溫度傳感器、內部參考電壓)
  3. ?時鐘系統?
    • 模擬時鐘(ADCCLK):由APB2時鐘分頻(/2、/4、/6、/8)生成,上限14MHz
    • 數字時鐘:等同于APB2時鐘

二)、核心功能模式

  1. ?轉換模式?
    • ?單次轉換?:手動觸發單次采樣
    • ?連續轉換?:自動循環采樣同一通道
    • ?掃描模式?:自動遍歷多通道
  2. ?通道分組機制?
    • ?規則組?:常規轉換隊列(最多16路)
    • ?注入組?:高優先級中斷式轉換(最多4路)
  3. ?觸發方式?
    • 軟件觸發
    • 硬件觸發(TIMER、EXTI等)

三)、數據管理

  1. ?對齊方式?
    • 右對齊:默認模式,數據存于寄存器低12位
    • 左對齊:便于快速讀取高8位數據
  2. ?校準機制?
    • 上電自校準
    • 溫度傳感器校準(需單獨使能)

四)、典型應用配置

// HAL庫配置示例(單通道連續轉換)
ADC_HandleTypeDef hadc;
hadc.Instance = ADC1;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;  // ADCCLK=21MHz
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.ContinuousConvMode = ENABLE;  // 連續轉換模式
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
HAL_ADC_Init(&hadc);

五)、進階應用方案

  1. ?DMA傳輸?
    實現多通道數據自動搬運,減少CPU開銷
  2. ?定時器觸發?
    精確控制采樣間隔(適用于波形采集)
  3. ?模擬看門狗?
    設置電壓閾值觸發中斷(過壓/欠壓保護)

六)、關鍵注意事項

  1. 輸入阻抗匹配:建議源阻抗≤10kΩ
  2. 抗干擾設計:
    • 獨立模擬供電引腳(VDDA、VSSA)
    • 添加RC濾波電路
    • 避免數字信號線平行走線
  3. 開啟DMA雙緩沖模式提升吞吐量
  4. 使用過采樣技術提高有效分辨率
  5. 低溫漂外部基準電壓(如REF3030)提升精度

七)、關于ADC轉換時間計算

轉換時間 = (采樣周期 + 12.5周期) / ADCCLK
例如:當ADCCLK=21MHz,采樣周期=84周期時,總轉換時間≈4.59μs37

二、GD32/STM32? DMA?介紹

?一)、DMA基礎概念

  1. ?定義與作用?
    DMA(Direct Memory Access)是一種無需CPU參與的硬件數據傳輸機制,可實現外設與內存之間(如ADC數據存入數組)、內存與外設之間(如UART發送數據)或內存與內存之間的高速數據搬運56。其核心作用是釋放CPU資源,提升系統實時性與效率。

  2. ?硬件架構?

    • ?雙控制器架構?:STM32F1系列包含DMA1(7通道)和DMA2(5通道,僅大容量型號支持)
    • ?總線矩陣?:DMA通過總線矩陣連接AHB總線,實現與外設、存儲器的并行訪問
    • ?數據流與通道?:每個DMA控制器包含獨立的數據流(Stream),每個數據流可映射至8個硬件通道(如DMA1_Channel4對應UART1_TX)

二)、DMA核心特性

  1. ?傳輸方向?

    • 外設→存儲器(如ADC采集數據)
    • 存儲器→外設(如SPI發送數據)
    • 存儲器→存儲器(高速數據拷貝)
  2. ?數據管理?

    • ?數據寬度?:支持8/16/32位,源與目標寬度可獨立配置(自動填充/截斷)
    • ?地址遞增?:傳輸后自動遞增源/目標地址,支持非連續數據傳輸
    • ?循環模式?:自動重置傳輸計數器,實現環形緩沖區(適用于連續采樣場景)
  3. ?優先級與仲裁?

    • 軟件可設4級優先級(很高、高、中、低)
    • 硬件仲裁器自動處理同優先級請求

三)、DMA配置流程(以HAL庫為例)

// 示例:配置UART通過DMA發送數據
// 1. 使能DMA時鐘
__HAL_RCC_DMA1_CLK_ENABLE();  // DMA1時鐘使能:ml-citation{ref="4,8" data="citationList"}// 2. 初始化DMA參數
DMA_HandleTypeDef hdma_uart_tx;
hdma_uart_tx.Instance = DMA1_Channel4;          // 選擇通道
hdma_uart_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; // 存儲器→外設
hdma_uart_tx.Init.PeriphInc = DMA_PINC_DISABLE;     // 外設地址固定
hdma_uart_tx.Init.MemInc = DMA_MINC_ENABLE;         // 存儲器地址遞增
hdma_uart_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; 
hdma_uart_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_uart_tx.Init.Mode = DMA_NORMAL;            // 單次傳輸模式
HAL_DMA_Init(&hdma_uart_tx);// 3. 綁定外設與DMA
__HAL_LINKDMA(&huart1, hdmatx, hdma_uart_tx);  // 關聯UART1發送端:ml-citation{ref="4,8" data="citationList"}

四)、典型應用場景

場景描述關鍵配置要點
?ADC多通道采樣?循環采集多個傳感器數據并存入數組掃描模式 + DMA循環傳輸
?串口大數據傳輸?高速發送/接收數據包(如Modbus通信)雙緩沖機制 + 傳輸完成中斷
?內存高速拷貝?內部Flash到SRAM的固件升級存儲器到存儲器模式

五)、關鍵注意事項

  1. ?時鐘使能?

    • 必須使能DMA控制器時鐘(如__HAL_RCC_DMA1_CLK_ENABLE())和外設時鐘
  2. ?中斷管理?

    • 使能傳輸完成/半傳輸/錯誤中斷,并在中斷服務函數中清除標志位
  3. ?數據對齊?

    • 確保源/目標地址對齊(如32位傳輸時地址需4字節對齊)

三、ADC校正?

一)、校準核心流程

  1. ?基礎校準(標準模式)?

    • 上電后執行基礎校準,消除電容誤差
    • ?操作步驟?:
      ① ADC上電(ADON=1)但未啟動轉換
      ② 執行校準命令(ADC_StartCalibration(ADC1))
      ③ 等待校準完成標志位
  2. ?內部參考電壓校準?

    • 利用內置VREFINT通道(通道17)實現動態精度補償
    • ?實現邏輯?:
      ① 測量VREFINT通道原始值(典型值約1.2V)
      ② 計算比例因子:Scale = VREFINT_實際值 / ADC_VREFINT原始值
      ③ 應用比例因子至其他通道

? ??????考慮到電壓校準需要手動測量VREFINT,加上我們大多應用并不需要獲取準確電壓值,只需要知道ADC值的變化,所以通常我們可以不做電壓校準。

?四、ADC程序實現示例

?一)、單通道輪詢模式(標準庫)

// 引用[1][8]的配置邏輯
#include "stm32f10x.h"void ADC1_Init(void) {// 開啟時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);// 配置ADC時鐘為PCLK2的6分頻(ADCCLK=12MHz)RCC_ADCCLKConfig(RCC_PCLK2_Div6); // GPIO配置為模擬輸入GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;GPIO_Init(GPIOA, &GPIO_InitStruct);// ADC參數配置ADC_InitTypeDef ADC_InitStruct;ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;       // 獨立模式ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;   // 右對齊ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;      // 單次轉換ADC_InitStruct.ADC_ScanConvMode = DISABLE;            // 非掃描模式ADC_Init(ADC1, &ADC_InitStruct);// 校準ADCADC_Cmd(ADC1, ENABLE);ADC_ResetCalibration(ADC1);while(ADC_GetResetCalibrationStatus(ADC1));ADC_StartCalibration(ADC1);while(ADC_GetCalibrationStatus(ADC1));
}uint16_t Get_ADC_Value(void) {ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);ADC_SoftwareStartConvCmd(ADC1, ENABLE);  // 啟動轉換while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); // 等待轉換完成return ADC_GetConversionValue(ADC1);     // 返回12位轉換結果
}

?二)、多通道DMA傳輸(標準庫)

void	ADC1_Init(void)
{
#if 1GPIO_InitTypeDef GPIO_InitStructure;DMA_InitTypeDef DMA_InitStructure;ADC_InitTypeDef ADC_InitStructure;u8	rank = 1;/* Enable DMA clock */RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);	/* Enable ADC1 clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);/* Configure PB0 & PB1 as analog input */GPIO_InitStructure.GPIO_Pin = PAPER_END_SEN | PAPER_IN_SEN;// | GPIO_BM_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_Init(GPIO_SENSOR, &GPIO_InitStructure);				// PB0 & PB1,輸入時不用設置速率/* DMA channel1 configuration */DMA_DeInit(DMA1_Channel1);DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;;	 //ADC地址DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SensorNow.ADC_Val;//內存地址DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;DMA_InitStructure.DMA_BufferSize = ADC_CH_MAX;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外設地址固定DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //內存地址增加DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;	//半字DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;		//循環傳輸DMA_InitStructure.DMA_Priority = DMA_Priority_High;DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;DMA_Init(DMA1_Channel1, &DMA_InitStructure);/* Enable DMA channel1 */DMA_Cmd(DMA1_Channel1, ENABLE);/* ADC1 configuration */ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//獨立ADC模式ADC_InitStructure.ADC_ScanConvMode = ENABLE ; 	 //使能掃描模式,掃描模式用于多通道采集ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;	//開啟連續轉換模式ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//不使用外部觸發轉換ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 	//采集數據右對齊ADC_InitStructure.ADC_NbrOfChannel = ADC_CH_MAX;	 	//通道數目ADC_Init(ADC1, &ADC_InitStructure);/*配置ADC時鐘,為PCLK2的8分頻,即9MHZ*/RCC_ADCCLKConfig(RCC_PCLK2_Div8); /*配置ADC的通道采樣周期及序列 */ ADC_RegularChannelConfig(ADC1, ADC_Channel_15, rank ++, ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC1, ADC_Channel_14, rank ++, ADC_SampleTime_55Cycles5);
/* Enable ADC1 DMA */ADC_DMACmd(ADC1, ENABLE);/* Enable ADC1 */ADC_Cmd(ADC1, ENABLE);/*復位校準寄存器*/   ADC_ResetCalibration(ADC1);/*等待校準寄存器復位完成*/while(ADC_GetResetCalibrationStatus(ADC1));/* ADC校準*/ADC_StartCalibration(ADC1);/* 等待校準完成*/while(ADC_GetCalibrationStatus(ADC1));/* 前面設置為不使用外部觸發轉換,所以使用軟件觸發ADC轉換 */ ADC_SoftwareStartConvCmd(ADC1, ENABLE);
#endif	
}

?三)、定時器觸發ADC采樣(標準庫)

? ?1、TIM定時器配置?

  • ?時鐘使能與模式設置?
    選擇TIM工作模式(如PWM模式或基本定時模式),配置預分頻器(PSC)和自動重載值(ARR)以設定觸發頻率。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 使能TIM3時鐘TIM_TimeBaseInitTypeDef TIM_InitStruct;
TIM_InitStruct.TIM_Prescaler = 72 - 1;       // 72MHz/72=1MHz
TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_InitStruct.TIM_Period = 1000 - 1;        // 觸發頻率1kHz (1MHz/1000)
TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3, &TIM_InitStruct);TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update); // 更新事件觸發TRGO
TIM_Cmd(TIM3, ENABLE);                                // 啟動定時器

2. ?ADC觸發源配置
ADC初始化與外部觸發選擇
?
啟用ADC外部觸發,選擇TIM的TRGO事件作為觸發源。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // 使能ADC1時鐘ADC_InitTypeDef ADC_InitStruct;
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;          // 獨立模式
ADC_InitStruct.ADC_ScanConvMode = DISABLE;               // 單通道掃描
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;         // 單次轉換模式
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO; // TIM3觸發
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;      // 右對齊
ADC_Init(ADC1, &ADC_InitStruct);ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5); // 配置通道0
ADC_Cmd(ADC1, ENABLE);                                                       // 啟動ADC

五、完整工程文件?

【免費】GD32/stm32ADC、DMA、UART、SPI、Flash讀寫、DRV8812/DRV8813步進馬達驅動、TIMER中斷、GPIO控制資源-CSDN文庫

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/79882.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/79882.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/79882.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux(十四)進程間通信(IPC),管道

一、進程間通信 (一)系統介紹進程間通信 進程間通信(IPC)介紹 小編插入的這篇文章詳細介紹了進程間通信的一些內容,大家可以一起學習。 (二)進程間通信的方法 1、管道 2、信號量 3、共享…

使用Homebrew下載配置git和連接GitHub(Mac版)

本文詳細介紹了在M系列Mac上安裝Homebrew并配置Git的過程,包括git的下載、設置全局用戶名和郵箱、生成SSH密鑰、添加GitHubSSH密鑰以及終端驗證。這些步驟有助于用戶順利進行協同開發。 一、下載git 1、終端輸入一下命令 brew install git2、這時下載完成 二、配…

懸崖邊的攝影牧歌

在云霧繚繞的懸崖邊,一場獨屬于自然與光影的邂逅悄然上演。 攝影師佇立于此,身旁是一群靈動的羊。他架起相機,眼神專注而熾熱,仿佛要將這天地間的一切都收納進小小的取景器。懸崖陡峭,巖石冷峻,卻因羊群的潔…

Linux環境基礎與開發工具使用

1. Linux編譯器vim 1.1 vim的基本概念講解 vim有很多種模式,我們初學者常用的就是命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode)。 命令/正常模式(Normal mode) …

《Python星球日記》 第36天:線性代數基礎

名人說:路漫漫其修遠兮,吾將上下而求索。—— 屈原《離騷》 創作者:Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder😊) 專欄:《Python星球日記》,限時特價訂閱中ing 目錄 一、標量、…

使用VMware Workstation pro 17.5.1在Windows上安裝Ubuntu 24.04.2的 詳細步驟

一、準備工作 1. 下載Ubuntu 24.04.2 ISO鏡像 官方下載地址:Ubuntu 24.04.2 (Noble Numbat) 選擇 ubuntu-24.04.2-desktop-amd64.iso(桌面版)或 ubuntu-24.04.2-live-server-amd64.iso(服務器版)。 2. 確認系統要求…

ios systeam introduction

Here is an in-depth look at Apple’s iOS, from its inception to its latest major release, covering architecture, core components, security, app lifecycle, development tools, and the headline features of iOS 18. iOS began life as “iPhone OS,” unveiled alo…

優化04-選擇率和直方圖

選擇率 在Oracle數據庫中,選擇率(Selectivity) 是優化器(CBO,基于成本的優化器)用來評估SQL語句中某個條件(如WHERE子句)過濾數據的比例的關鍵指標。它直接影響優化器選擇執行計劃的…

python實戰:通過輸入文字匹配在docx文檔中的具體位置

在指定的docx文檔中,輸入一串文字來查看該文字在文檔中的具體位置;方便后續處理(如替換文字,高亮顯示等等操作) from docx import Documentdef find_text_in_docx(file_path, search_text):# 讀取docx文件doc = Document(file_path)# 遍歷段落,查找匹配的文本for i

Flutter——數據庫Drift開發詳細教程(二)

目錄 1.核心API1.1查詢數據列表分頁1.2 列表排序1.3推遲獲取與觀察 1.核心API 1.1查詢數據列表分頁 限制返回的結果數量limit&#xff0c;從某一位置開始查詢offset ///limit10, offset10 Future<List<TodoItem>> limitTodos(int limit, {int? offset}) {return …

mux-vlan基礎配置

1.top配置 2.各個交換機設置 sw3交換機的 sysname swb # undo info-center enable # vlan batch 10 20 30 100 # vlan 10description financial vlan vlan 20description marketing vlan vlan 30description client vlan vlan 100description principal vlanmux-vlansubordi…

SAM詳解2(初級應用)

SAM SAM5. 初級應用5.1 靜態本質不同子串個數5.2 字符串匹配5.3 關于子串出現次數5.4 動態添加時本質不同子串個數SAM 5. 初級應用 記 l o n g e s t ( x ) longest(x) longest(x) 為點 x x x 代表子串集合中最長串的長度。記 s h o r t e s t ( x ) shortest(x) shortest(…

【日擼 Java 三百行】Day 4(條件語句實戰——閏年問題)

目錄 Day 4&#xff1a;條件語句實戰——閏年問題 一、基礎知識及代碼思路 二、代碼及測試 小結 Day 4&#xff1a;條件語句實戰——閏年問題 Task&#xff1a; if 語句的嵌套.基本規律自行百度.布爾類型. 一、基礎知識及代碼思路 1. 什么是閏年&#xff1f; 閏年是歷法中…

MySQL 中 EXISTS (SELECT 1 FROM ...) 的用法詳解

EXISTS (SELECT 1 FROM ...) 是 MySQL 中用于存在性檢查的核心語法&#xff0c;其核心邏輯是判斷子查詢是否返回至少一行數據。以下從作用原理、使用場景、性能優化等方面展開解析&#xff0c;并結合具體示例說明。 1. 基本語法與作用原理 語法結構&#xff1a; SELECT 列名 F…

阿里云服務器防御是怎么做出來的?服務器攻擊方式有幾種?

阿里云服務器防御是怎么做出來的?服務器攻擊方式有幾種&#xff1f; 服務器防御是一個多層次、多維度的體系&#xff0c;通常包括以下核心措施&#xff1a; 1. 網絡層防御 防火墻&#xff08;Firewall&#xff09;&#xff1a;過濾非法流量&#xff0c;僅允許授權通信&#xf…

ElasticSearch深入解析(八):索引設置、索引別名、索引模板

一、索引的動態設置、靜態設置 索引設置包含兩部分核心內容&#xff1a; 靜態設置(static index settings)&#xff0c;只允許在創建索引時或者針對已關閉的索引進行設置。指動態設置(dynamic index settings)&#xff0c;可以借助更新設置(update settings)的方式進行動態更新…

Prometheus實戰教程:k8s平臺手動部署Grafana

以下是一個可用于生產環境的 Kubernetes 部署 Grafana 的 YAML 文件。該配置包括 Deployment、Service、ConfigMap 和 PersistentVolumeClaim&#xff0c;確保 Grafana 的高可用性和數據持久化。 Grafana 生產部署 YAML 文件 ☆實操示例 cat grafana-deployment.yaml 登錄后復制…

VSTO外接程序與VBA的聯動嘗試

文章目錄 前言一、第一坑&#xff1a;安裝offic2007后excel加載項找不到了二、示例1 通過Ribbon XML自定義Excel主菜單并添加新項二、示例1 總結三、示例2 創建VSTO外接程序三、示例2 總結四、示例 3 C# VSTO外接程序示例四、示例 3 總結五、實現C# 的VSTO調用VBA函數(xlam)六、…

DeepSeek驅動的金市情緒量化:NLP解析貿易政策文本的情緒傳導路徑

【AI觀察】政策信號與市場情緒的量化關聯 基于自然語言處理技術對全球財經文本的情緒分析顯示&#xff0c;4月30日亞盤時段現貨黃金價格波動率較前日下降12.3%&#xff0c;與技術面修正指標呈現強相關性。特政府最新關稅政策調整引發市場風險偏好指數&#xff08;RPI&#xff…

期末代碼Python

以下是 學生信息管理系統 的簡化版代碼示例&#xff08;控制臺版本&#xff0c;使用文件存儲數據&#xff09;&#xff0c;包含核心功能&#xff1a; 1. 定義學生類 class Student: def __init__(self, sid, name, score): self.sid sid # 學號 self.name name # 姓名 self.s…