STM32的HAL庫開發---單通道ADC采集(DMA讀取)實驗

一、實驗簡介

正常單通道ADC采集順序是先開啟ADC采集,然后等待ADC轉換完成,也就是判斷EOC位置1,然后再讀取數據寄存器的值。

如果配置了DMA功能,在EOC位被硬件置1后,自動產生DMA請求,然后DMA進行數據搬運。

1,功能描述?通過DMA讀取數據

通過ADC1通道1PA1)采集電位器的電壓,并顯示ADC轉換的數字量及換算后的電壓值

2、確定最小刻度

VREF+ = 3.3V ---》 0V?≤?VIN?≤??3.3V ---》最小刻度 = 3.3 / 4096 ,F1的分辨率是12位的,也就是把3.3V分為4096份。F4/F7/H7還可以自己配置分辨率,例如H7可以把分辨率配置為16位的,也就是把3.3V進行65536等分。

3,確定轉換時間

采樣時間239.5個ADC時鐘周期為例,可以得到轉換時間為21us。例如配置為最長的采樣時間239.5個采樣周期,那么采樣時間就是239.5 + 12.5? = 252個時鐘周期。配置ADC的時鐘的12M,則轉換時間為252 * (1 / 12000000) = 21us,采樣時間設置的越大,準確度越高,設置的越小,準確度越低。

4、模式組合

由于使用了DMA搬運,所以使用連續轉換模式、不使用掃描模式

二、單通道ADC采集實驗配置步驟?

1、HAL_DMA_Init()函數,初始化DMA

2、__HAL_LINKDMA()宏定義,將DMAADC句柄聯系起來

3、HAL_ADC_Init()函數,用于初始化ADC,配置ADC工作參數。

4、HAL_ADCEx_Calibration_Start()函數,用于ADC校準的。

5、HAL_ADC_MspInit()函數,?配置NVIC、CLOCK、GPIO

6、HAL_ADC_ConfigChannel()函數,配置ADC相應通道相關參數

7、HAL_NVIC_SetPriority()HAL_NVIC_EnableIRQ()函數,使能DMA數據流傳輸完成中斷

8、DMAx_Channely_IRQHandler()函數,編寫DMA數據流中斷服務函數

9、HAL_DMA_Start_IT()函數,啟動DMA,開啟傳輸完成中斷

10、HAL_ADC_Start_DMA()函數,觸發ADC轉換,DMA傳輸數據

三、?實驗程序

1、寄存器版本

dma.c源程序

#include "./BSP/DMA/dma.h"
#include <string.h>uint16_t ADC_data[20];
//配置ADC1的DMA1的通道1請求
void DMA_Init(void)
{//開啟DMA1時鐘RCC->AHBENR |= (1 << 0);//MEM2MEM 設置為非存儲器到存儲器模式DMA1_Channel1->CCR &= ~(1 << 14);//PL 設置通道優先級為中DMA1_Channel1->CCR |= (1 << 12);//MSIZE 設置存儲器數據寬度為16位DMA1_Channel1->CCR |= (1 << 10);//PSIZE 設置外設數據寬度為16位DMA1_Channel1->CCR |= (1 << 8);//MINC 設置存儲器增量模式DMA1_Channel1->CCR |= (1 << 7);//PINC 設置外設不增量模式DMA1_Channel1->CCR &= ~(1 << 6);//CIRC 不執行循環模式//DMA1_Channel1->CCR &= ~(1 << 5);DMA1_Channel1->CCR |= (1 << 5);//DIR 從外設讀取DMA1_Channel1->CCR &= ~(1 << 4);	//設置傳輸數量DMA1_Channel1->CNDTR = 20;//設置DMA的外地址DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR;//清空ADC_datamemset((void*)ADC_data,0,20);DMA1_Channel1->CMAR = (uint32_t)ADC_data;//EN 開啟DMA  這個必須放在最后  不然CNDTR寄存器不能寫入DMA1_Channel1->CCR |= (1 << 0);
}

adc.c源程序

#include "./BSP/ADC/adc.h"//配置ADC1的通道1 PA1進行
void ADC_Init(void)
{//開啟ADC1時鐘RCC->APB2ENR |= (1 << 9);//關閉掃描模式ADC1->CR1 &= ~(1 << 8);//開啟外部觸發轉換ADCADC1->CR2 |= (1 << 20);//EXTSEL 設置軟件觸發ADC轉換ADC1->CR2 |= (7 << 17);//ALIGN 數據右對齊ADC1->CR2 &= ~(1 << 11);//DMA 開啟DMA轉換ADC1->CR2 |= (1 << 8);//CONT 開啟連續轉換模式ADC1->CR2 |= (1 << 1);//設置ADC1通道1轉換時間為239.5個周期ADC1->SMPR2 |= (7 << 3);//L 設置總共1一個轉換通道ADC1->SQR1 |= (1 << 20);//設置ADC第一個轉換為通道1ADC1->SQR3 |= (1 << 0);//EXTTRIG 開啟GPIOA時鐘RCC->APB2ENR |= (1 << 2);//設置PA1為輸入模式GPIOA->CRL &= ~(0XF << 4);//ADON 開啟ADC功能ADC1->CR2 |= (1 << 0);//RSTCAL 初始化ADC校準寄存器ADC1->CR2 |= (1 << 3);//等待ADC校準寄存器初始化完畢while(ADC1->CR2 & (1 << 3));//開啟ADC校準ADC1->CR2 |= (1 << 2);//等待ADC校準完成while(ADC1->CR2 & (1 << 2));//SWSTART 開啟規則組轉換 軟件觸發ADC1->CR2 |= (1 << 22);
}

2、庫函數版本

dam.c源程序

#include "./BSP/DMA/dma.h"
#include <string.h>extern ADC_HandleTypeDef hadc;
DMA_HandleTypeDef hdma;
//配置ADC1的DMA1的通道1請求
void DMA_Init(void)
{//開啟DMA1時鐘__HAL_RCC_DMA1_CLK_ENABLE();//配置DMA1通道  因為ADC1連接在DMA1的通道1  這個在使用手冊可以查找到hdma.Instance = DMA1_Channel1;//外設到內存hdma.Init.Direction = DMA_PERIPH_TO_MEMORY;//內存為16位hdma.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;//內存遞增hdma.Init.MemInc = DMA_MINC_ENABLE;//循環搬運 //當啟動了循環模式,數據傳輸的數目變為0時,將會自動地被恢復成配置通道時設置的初值,DMA操作將會繼續進行。hdma.Init.Mode = DMA_NORMAL;//外設16位hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;//外設地址不遞增hdma.Init.PeriphInc = DMA_PINC_DISABLE;//通道1優先級為中hdma.Init.Priority = DMA_PRIORITY_MEDIUM;//配置DMA的通道1為外設到內存HAL_DMA_Init(&hdma);//將DMA句柄于ADC句柄連接起來 可以理解為將這個DMA句柄拷貝到ADC句柄里的DMA句柄上__HAL_LINKDMA(&hadc,DMA_Handle,hdma);
}//標志DMA數據搬運完
uint8_t state = 0;
void DMA1_Channel1_IRQHandler(void)
{if(DMA1->ISR & (1 << 1)){state = 1;//清除中斷標志位DMA1->IFCR |= (1 << 1);}DMA1->IFCR |= (1 << 0);
}

adc.c源程序

#include "./BSP/ADC/adc.h"
#include "string.h"extern DMA_HandleTypeDef hdma;
uint16_t ADC_data[20];
ADC_HandleTypeDef hadc;
//配置ADC1的通道1 PA1進行
void ADC_Init(void)
{hadc.Instance = ADC1;//配置ADC連續轉換模式 就是ADC轉換完成一次后會自動下一次轉換hadc.Init.ContinuousConvMode = ENABLE;//轉換結果采用右對齊hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;//不開啟間斷模式hadc.Init.DiscontinuousConvMode = DISABLE;//ADC觸發選用軟件觸發hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;//設置ADC轉換數量的 SQR1的L位hadc.Init.NbrOfConversion = 1;//設置間斷模式寫轉換一次轉換數量hadc.Init.NbrOfDiscConversion = 0;//不開啟掃描模式 因為就一個通道hadc.Init.ScanConvMode = ADC_SCAN_DISABLE;//設置ADC為軟件觸發轉換HAL_ADC_Init(&hadc);//開啟ADC校準HAL_ADCEx_Calibration_Start(&hadc);ADC_ChannelConfTypeDef sConfig;//配置通道1sConfig.Channel = ADC_CHANNEL_1;//通道1第一個轉換sConfig.Rank = ADC_REGULAR_RANK_1;//采樣周期采用239.5sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;//配置ADC通道一為第一個轉換HAL_ADC_ConfigChannel(&hadc, &sConfig);memset((void*)ADC_data,0,20);//這句話最好寫 不然下面那個會把半傳輸中斷也開開  這里就會開一個中斷 因為下面那個函數回把ADC半傳輸回調函數復制 //這句話不寫也行 但是中斷里邊要清除所有位  不然卡在中斷HAL_DMA_Start_IT(&hdma, (uint32_t)ADC1->DR, (uint32_t)ADC_data, 20);//開啟DMA傳輸 這個函數里邊會把中斷都打開HAL_ADC_Start_DMA(&hadc, (uint32_t* )ADC_data, 20);
}void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{//開啟ADC1時鐘__HAL_RCC_ADC1_CLK_ENABLE();//開啟GPIOA時鐘__HAL_RCC_GPIOA_CLK_ENABLE();GPIO_InitTypeDef GPIO_Init;GPIO_Init.Mode = GPIO_MODE_ANALOG;GPIO_Init.Pin = GPIO_PIN_1;GPIO_Init.Pull = GPIO_NOPULL;//設置PA1為模擬輸入模式HAL_GPIO_Init(GPIOA,&GPIO_Init);//使能DMA1通道1中斷HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);//設置中斷優先級HAL_NVIC_SetPriority(DMA1_Channel1_IRQn,2,2);
}

這里主要是要注意先配置DMA中斷,再調用ADC的DMA函數,具體原因在代碼里寫了

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

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

相關文章

編譯原理基礎(1)

1.什么是ASCII碼&#xff1f; ASCII碼即美國信息交換標準代碼&#xff0c;是基于拉丁字母的電腦編碼系統&#xff0c;用于顯示現代英語和部分西歐語言。其7位編碼范圍0-127&#xff0c;8位擴展到0-255。字符集含控制字符&#xff08;0-31、127&#xff0c;用于控制設備或表示通…

基于 Highcharts 實現 Vue 中的答題統計柱狀圖組件

在現代 Web 開發中&#xff0c;數據可視化是一個重要的組成部分&#xff0c;而 Highcharts 是一個廣泛使用的 JavaScript 圖表庫&#xff0c;可以幫助開發者在 Web 頁面上輕松地繪制豐富的圖表。在本文中&#xff0c;我們將基于 Highcharts 創建一個用于答題統計的柱狀圖&#…

SQLAlchemyError: A transaction is already begun on this Session.

資料 sqlalchemy 事務 - 簡書 在 SQLAlchemy 中&#xff0c;事務是通過會話來管理的。當你開始一個事務&#xff08;例如使用 async with db.begin()&#xff09;&#xff0c;它會開啟一個新的事務&#xff0c;并在事務塊結束時自動提交或回滾。如果在同一個會話中&#xff0c…

Java Web開發實戰與項目——Spring Boot與Redis實現緩存管理

緩存技術在現代Web開發中至關重要&#xff0c;尤其是在高并發的環境中&#xff0c;緩存能夠有效減少數據庫訪問壓力、提高系統性能。Redis作為最流行的內存數據存儲系統之一&#xff0c;常用于緩存管理。本節將講解如何在Spring Boot項目中集成Redis&#xff0c;實現緩存管理&a…

C語言學習【1】C語言關于寄存器的封裝

目錄 1.封裝寄存的C語言的語法volatile&#xff1a;unsigned int:*pGpiobOdrvolatile unsigned int * 2.進一步C語言的封裝 在嵌入式中&#xff0c;底層一定是操作寄存器&#xff0c;我有一個理念&#xff0c;凡事一定要想清楚&#xff0c;把任何知識點融入自己的理解之中&…

#滲透測試#批量漏洞挖掘#暢捷通T+遠程命令執行漏洞

免責聲明 本教程僅為合法的教學目的而準備,嚴禁用于任何形式的違法犯罪活動及其他商業行為,在使用本教程前,您應確保該行為符合當地的法律法規,繼續閱讀即表示您需自行承擔所有操作的后果,如有異議,請立即停止本文章讀。 目錄 一、漏洞概況 二、攻擊特征 三、應急處置…

ollama 學習筆記

1. 參考博客&#xff1a;1. Ollama完整教程&#xff1a;本地LLM管理、WebUI對話、Python/Java客戶端API應用&#xff1a;https://blog.csdn.net/python122_/article/details/1409457202. https://gitee.com/ai-big-model/ollama/tree/main --》REST APIollama 離線安裝包 ollam…

ARM Linux平臺下 OpenCV Camera 實驗

一、硬件原理 1. OV2640 1.1 基本功能 OV2640 是一款低功耗、高性能的圖像傳感器&#xff0c;支持以下功能&#xff1a; 最高分辨率&#xff1a;200 萬像素&#xff08;1600x1200&#xff09;。 輸出格式&#xff1a;JPEG、YUV、RGB。 內置圖像處理功能&#xff1a;自動曝…

vue2.x中父組件通過props向子組件傳遞數據詳細解讀

1. 父組件向子組件傳遞數據的步驟 在子組件中定義 props&#xff1a; 子組件通過 props 選項聲明它期望接收的數據。props 可以是數組形式&#xff08;簡單聲明&#xff09;或對象形式&#xff08;支持類型檢查和默認值&#xff09;。 在父組件中使用子組件時綁定 props&#x…

【Gin】2:快速上手Gin框架(模版、cookie、session)

本文目錄 一、模版渲染二、自定義模版函數三、cookie四、Session五、cookie、session區別六、會話攻擊 一、模版渲染 在 Gin 框架中&#xff0c;模板主要用于動態生成 HTML 頁面&#xff0c;結合 Go 語言的模板引擎功能&#xff0c;實現數據與視圖的分離。 模板渲染是一種動態…

【AI繪畫】大衛? 霍克尼風格——自然的魔法(一丹一世界)

大衛? 霍克尼&#xff0c;很喜歡這個老頭&#xff0c;“藝術是一場戰斗”。老先生零九年有了iphone&#xff0c;開始用iphone畫畫&#xff0c;一零年開始用ipad畫畫&#xff0c;用指頭劃拉&#xff0c;據說五分鐘就能畫一幅&#xff0c;每天早上隨手畫幾幅送給身邊的朋友。很c…

解碼 NLP:從萌芽到蓬勃的技術蛻變之旅

內容概況&#xff1a; 主要講述NLP專欄的內容和NLP的發展及其在現代生活中的廣泛應用。專欄強調實踐為主、理論為輔的學習方法&#xff0c;并通過多個生活場景展示了NLP技術的實際應用&#xff0c;如對話機器人、搜索引擎、翻譯軟件、電商推薦和智能客服等。 這邊我就不多做自我…

解決DeepSeek服務器繁忙問題的實用指南

目錄 簡述 1. 關于服務器繁忙 1.1 服務器負載與資源限制 1.2 會話管理與連接機制 1.3 客戶端配置與網絡問題 2. 關于DeepSeek服務的備用選項 2.1 納米AI搜索 2.2 硅基流動 2.3 秘塔AI搜索 2.4 字節跳動火山引擎 2.5 百度云千帆 2.6 英偉達NIM 2.7 Groq 2.8 Firew…

前端(AJAX)學習筆記(CLASS 2):圖書管理案例以及圖片上傳

* BootStrap彈框 功能&#xff1a;不離開當前頁面&#xff0c;顯示單獨內容&#xff0c;供用戶操作 步驟&#xff1a; 1、引入bootstrap.css和bootstrap.js 2、準備彈框標簽&#xff0c;確認結構 3、通過自定義屬性&#xff0c;控制彈框的顯示和隱藏 其中的bootstrap.css…

數據結構:雙鏈表list

list 是 C 標準庫中的雙向鏈表容器。 list初始化示例&#xff1a; #include <list>int n 7;std::list<int> lst; // 初始化一個空的雙向鏈表 lststd::list<int> lst(n); // 初始化一個大小為 n 的鏈表 lst&#xff0c;鏈表中的值默認都為 0std::list<i…

AI Agent Service Toolkit:一站式大模型智能體開發套件

項目簡介 該工具包基于LangGraph、FastAPI和Streamlit構建,提供了構建和運行大模型Agent的最小原子能力,包含LangGraph代理、FastAPI服務、用于與服務交互的客戶端以及一個使用客戶端提供聊天界面的Streamlit應用。用戶可以利用該工具包提供的模板快速搭建基于LangGraph框架…

論文概覽 |《Urban Analytics and City Science》2023.10 Vol.50 Issue.8

本次給大家整理的是《Environment and Planning B: Urban Analytics and City Science》雜志2023年10月第50卷第8期的論文的題目和摘要&#xff0c;一共包括21篇SCI論文&#xff01; 論文1 Advances in geospatial approaches to transport networks and sustainable mobility …

大語言模型推理能力從何而來?

前言 DeepSeek R1采用強化學習進行后訓練&#xff0c;通過獎勵機制和規則引導模型生成結構化思維鏈&#xff08;CoT&#xff09;&#xff0c;從而顯著提升了推理能力。這一創新方法使得DeepSeek R1能夠在無需大量監督數據的情況下&#xff0c;通過自我進化發展出強大的推理能力…

用 WOW.js 和 animate.css 實現動畫效果

用 wow.js 就可以實現動畫效果&#xff0c;但由于里面的動畫樣式太少&#xff0c;一般還會引入 animated.css 第一步&#xff1a;下載 選擇合適的包管理器下載對應的內容 pnpm i wow.js animated.css --save 第二步&#xff1a;引入 在main.js中加入&#xff1a; import …

設計模式教程:解釋器模式(Interpreter Pattern)

1. 什么是解釋器模式&#xff1f; 解釋器模式&#xff08;Interpreter Pattern&#xff09;是一種行為型設計模式&#xff0c;通常用于處理語言&#xff08;例如數學表達式、SQL查詢等&#xff09;中的語法和解釋。該模式定義了一個文法&#xff0c;并通過解釋器類來解釋文法中…