STM32之ADC例項(基於DMA方式)

2021-09-30 13:33:35 字數 3595 閱讀 3736

adc簡介:

adc(analog-to-digital converter,模/ 數轉換器

)。也就是將模擬訊號轉換為數碼訊號進行處理,在儲存或傳輸時,模數轉換器幾乎必不可少。

stm32在片上整合的adc外設非常強大,我使用的奮鬥開發板是stm32f103vet6,屬於增強型的cpu,它有18個通道,可測量16個外部和2個內部訊號源。各通道的a/d轉換可以單次,連續,掃瞄或間斷模式執行,adc的結果可以左對齊或右對齊方式儲存在16位資料暫存器中。

adc工作過程分析:

我們以adc規則通道轉換過程來分析,如上圖,所有的器件都是圍繞中間的模擬至數字轉換器部分展開的。它的左端v

ref+,

vref- 等adc參考電壓,adcx_in0 ~ 

adcx_in15為adc的輸入訊號通道,即某些gpio引腳。輸入訊號經過這些通道被送到adc器件,adc器件需要收到觸發訊號才開始進行轉換,如exti外部觸發,定時器觸發,也可以使用軟體觸發。adc部件接受到觸發訊號後,在adcclk時鐘的驅動下對輸入通道的訊號進行取樣,並進行模數轉換,其中adcclk是來自adc預分頻器。

adc部件轉換後的數值被儲存到乙個16位的規則通道資料暫存器(或注入通道資料暫存器)中,我們可以通過cpu指令或dma把它讀到記憶體(變數),模數轉換之後,可以出發dma請求或者觸發adc轉換結束事件,如果配置了模擬看門狗,並且採集的電壓大於閾值,會觸發看門狗中斷。

其實對於adc取樣,軟體程式設計主要就是adc的配置,當然我是基於dma方式的,所以dma的配置也是關鍵!話不多說看**!

主函式:main.c

#include "printf.h"

#include "adc.h"

#include "stm32f10x.h"

extern __io uint16_t adc_convertedvalue;

float adc_convertedvaluelocal;

void delay(__io uint32_t ncount)

int main(void)

return 0;

}

注意adc_convertedvaluelocal儲存了由轉換值計算出來的電壓值,計算公式是:實際電壓值=adc轉換值 x lsb ,這裡由於我的板子vref+接的參考電壓為3.3v,所以lsb=3.3/4096,stm32的adc的精度為12位。

adc與dma配置:adc.c

#include "adc.h"

volatile uint16_t adc_convertedvalue;

void adc_init()

adc配置還是比較簡單的,畢竟只配置了單通道,還是分析一下吧!這裡我是把adc1的通道11使用的gpio引腳pc1配置成模擬輸入模式,在作為adc的輸入時,必須使用模擬輸入。對於adc通道,每個adc通道對應乙個gpio引腳埠,gpio的引腳在設為模擬輸入模式後可用於模擬電壓的輸入。stm32f103vet6有三個adc,這三個adc公用16個外部通道。

dma的整體配置為:使用dma1的通道1,資料從adc外設的資料暫存器(adc1_dr_address)轉移到記憶體(adc_convertedvalue變數),記憶體外設位址都固定,每次傳輸的大小為半字(16位),使用dma迴圈傳輸模式。

dma傳輸的外設位址,也就是adc1的位址為0x40012400+0x4c,這個位址可查stm32 datasheet獲得,如圖;

要特別注意adc轉換時間配置,由於adc時鐘頻率越高,轉換速度越快,那是不是就把adc的時鐘頻率設的越大越好呢?其實不然,根據adc時鐘圖可知,adc時鐘有上限值,即不能超過14mhz,如圖:

這裡adc預分頻器的輸入為高速外設時鐘(pclk2),使用rcc_adcclkconfig()庫函式來設定adc預分頻的分頻值,pclk2常用時鐘為72mhz,而adcclk必須小於14mhz,所以這裡adcclk為pclk2的6分頻,即12mhz,而我的程式中只是隨便設為8分頻,9mhz,若希望adc以最高頻率14mhz執行,可以把pclk2設定為56mhz,然後再4分頻得到acclk。

adc的轉換時間不僅與adc的時鐘有關,還與取樣週期有關。每個adc通道可以設定為不同的取樣週期。stm32的adc取樣時間計算公式為:

t=取樣週期+12.5個週期

公式中的取樣週期就是函式中配置的 adc_sampletime,而後邊加上的12.5個週期為固定值,則adc1通道11的轉換時間為t=(55.5+12.5) x 1/9=7.56us。

補充:在adc.c檔案中定義了adc_convertedvalue變數,要注意這個變數是由關鍵字volatile修飾的,volatile的作用是讓編譯器不要去優化這個變數,這樣每次用到這個變數時都要回到相應變數的記憶體中去取值,而如果不使用volatile進行修飾的話,adc_convertedvalue變數在被訪問的時候可能會直接從cpu的暫存器中取出(因為之前該變數被訪問過,也就是說之前就從記憶體中取出adc_convertedvalue的值儲存到某個cpu暫存器中),之所以直接從暫存器中去取值而不去記憶體中取值,這是編譯器優化**的結果(訪問cpu暫存器比訪問記憶體快得多)。這裡的cpu暫存器指r0,r1等cpu通用暫存器,用於cpu運算及暫存資料,不是指外設中的暫存器。

因為adc_convertedvalue這個變數值隨時都會被dma控制器改變的,所以用volatile來修飾它,確保每次讀取到的都是實時adc轉換值。

adc.h:

#ifndef _adc_h

#define _adc_h

#include "stm32f10x.h"

#include "stm32f10x_dma.h"

#include "stm32f10x_adc.h"

#define adc1_dr_address ((uint32_t)0x4001244c);

void adc_init(void);

#endif

效果圖:

由於我的開發板沒有滑動變阻器,所以我就將電壓的輸入端接入通用io口的3v引腳。如圖:

STM32韌體概述之ADC

table 3.函式描述格式 函式名外設函式的名稱 函式原形 原形宣告 功能描述 簡要解釋函式是如何執行的 輸入引數 輸入引數描述 輸出引數 輸出引數描述 返回值函式的返回值 先決條件 呼叫函式前應滿足的要求 被呼叫函式 其他被該函式呼叫的庫函式 4.模擬 數字轉換器 模擬 數字轉換器 adc 是一...

STM32之ADC 模數轉換

1 adc簡介 stm32f103系列有3個adc,精度為12位,adc是乙個逐次逼近型模擬數字轉換器,且每個adc有18個通道,可以測量16個外部和2個內部訊號源,每個通道的a d轉換可以進行單次 連續 掃瞄或間斷模式執行,adc的結果可以左對齊或右對齊方式儲存在16位資料暫存器中,adc的輸入時...

STM32的ADC轉換模式

stm32的adc轉換模式 stm32的adc總共有兩種轉換模式 單次轉換和連續轉換 前幾天看了st官方的中文手冊,在adc模組的介紹中,同時出現了單次轉換模式 連續轉換模式和掃瞄模式,看完整個模組的文件後,對adc的轉換模式還是不理解,通過學習其他文件和程式設計測試,整理了 單次轉換 連續轉換和掃...