STM32F4xx系列提供的12位ADC是逐次逼近型模數(shù)轉(zhuǎn)換器。它具有多達(dá) 19 個(gè)復(fù)用通道,可測(cè)量來自 16 個(gè)外部源、兩個(gè)內(nèi)部源和 V BAT 通道的信號(hào)。這些通道的 A/D 轉(zhuǎn)換可在單次、連續(xù)、掃描或不連續(xù)采樣模式下進(jìn)行。ADC 的結(jié)果存儲(chǔ)在一個(gè)左對(duì)齊或右對(duì)齊的 16 位數(shù)據(jù)寄存器中。
ADC 具有模擬看門狗特性,允許應(yīng)用檢測(cè)輸入電壓是否超過了用戶自定義的閾值上限或下限。
單個(gè)ADC框圖
ADC 引腳
ADC開關(guān)控制
可通過將ADC_CR2寄存器中的 ADON 位置1來為 ADC 供電。首次將 ADON 位置1時(shí),會(huì)將ADC從掉電模式中喚醒。
SWSTART 或 JSWSTART 位置 1 時(shí),啟動(dòng) AD 轉(zhuǎn)換。
可通過將 ADON 位清零來停止轉(zhuǎn)換并使 ADC 進(jìn)入掉電模式。在此模式式下,ADC 幾乎不耗電(只有幾 μA)。
ADC時(shí)鐘
ADC 具有兩個(gè)時(shí)鐘方案:
● 用于模擬電路的時(shí)鐘:ADCCLK,所有 ADC 共用
此時(shí)鐘來自于經(jīng)可編程預(yù)分頻器分頻的 APB2 時(shí)鐘,該預(yù)分頻器允許 ADC 在 f PCLK2 /2、/4、/6 或 /8 下工作。有關(guān) ADCCLK 的最大值,請(qǐng)參見數(shù)據(jù)手冊(cè)。
● 用于數(shù)字接口的時(shí)鐘(用于寄存器讀/寫訪問)
此時(shí)鐘等效于 APB2 時(shí)鐘。可以通過 RCC APB2 外設(shè)時(shí)鐘使能寄存器 (RCC_APB2ENR)分別為每個(gè) ADC 使能/禁止數(shù)字接口時(shí)鐘。
通道選擇
有 16 條復(fù)用通道。可以將轉(zhuǎn)換分為兩組:規(guī)則轉(zhuǎn)換和注入轉(zhuǎn)換。每個(gè)組包含一個(gè)轉(zhuǎn)換序列,該序列可按任意順序在任意通道上完成。例如,可按以下順序?qū)π蛄羞M(jìn)行轉(zhuǎn)換:ADC_IN3、ADC_IN8、ADC_IN2、ADC_IN2、ADC_IN0、ADC_IN2、ADC_IN2、ADC_IN15。
● 一個(gè)規(guī)則轉(zhuǎn)換組最多由 16 個(gè)轉(zhuǎn)換構(gòu)成。必須在 ADC_SQRx 寄存器中選擇轉(zhuǎn)換序列的規(guī)則通道及其順序。規(guī)則轉(zhuǎn)換組中的轉(zhuǎn)換總數(shù)必須寫入 ADC_SQR1 寄存器中的 L[3:0] 位。
● 一個(gè)注入轉(zhuǎn)換組最多由 4 個(gè)轉(zhuǎn)換構(gòu)成。必須在 ADC_JSQR 寄存器中選擇轉(zhuǎn)換序列的注入通道及其順序。注入轉(zhuǎn)換組中的轉(zhuǎn)換總數(shù)必須寫入 ADC_JSQR 寄存器中的 L[1:0] 位。
如果在轉(zhuǎn)換期間修改 ADC_SQRx 或 ADC_JSQR 寄存器,將復(fù)位當(dāng)前轉(zhuǎn)換并向 ADC 發(fā)送一個(gè)新的啟動(dòng)脈沖,以轉(zhuǎn)換新選擇的組。
溫度傳感器、V REFINT 和 V BAT 內(nèi)部通道
● 對(duì)于 STM32F40x 和 STM32F41x 器件,溫度傳感器內(nèi)部連接到通道 ADC1_IN16。
內(nèi)部參考電壓 VREFINT 連接到 ADC1_IN17。
● 對(duì)于 STM23F42x 和 STM32F43x 器件,溫度傳感器內(nèi)部連接到與 VBAT 共用的通道
ADC1_IN18。一次只能選擇一個(gè)轉(zhuǎn)換(溫度傳感器或 VBAT)。同時(shí)設(shè)置了溫度傳感器和 VBAT 轉(zhuǎn)換時(shí),將只進(jìn)行 VBAT 轉(zhuǎn)換。
內(nèi)部參考電壓 VREFINT 連接到 ADC1_IN17。
VBAT通道連接到通道ADC1_IN18。該通道也可轉(zhuǎn)換為注入通道或規(guī)則通道。
單次轉(zhuǎn)換模式
在單次轉(zhuǎn)換模式下, ADC 執(zhí)行一次轉(zhuǎn)換 。CONT 位為 0 時(shí),可通過以下方式啟動(dòng)此模式:
● 將 ADC_CR2 寄存器中的 SWSTART 位置 1(僅適用于規(guī)則通道)
● 將 JSWSTART 位置 1(適用于注入通道)
● 外部觸發(fā)(適用于規(guī)則通道或注入通道)
完成所選通道的轉(zhuǎn)換之后:
● 如果轉(zhuǎn)換了規(guī)則通道:
— 轉(zhuǎn)換數(shù)據(jù)存儲(chǔ)在 16 位 ADC_DR 寄存器中
— EOC(轉(zhuǎn)換結(jié)束)標(biāo)志置 1
— EOCIE 位置 1 時(shí)將產(chǎn)生中斷
● 如果轉(zhuǎn)換了注入通道:
— 轉(zhuǎn)換數(shù)據(jù)存儲(chǔ)在 16 位 ADC_JDR1 寄存器中
— JEOC(注入轉(zhuǎn)換結(jié)束)標(biāo)志置 1
— JEOCIE 位置 1 時(shí)將產(chǎn)生中斷
然后,ADC 停止。
連續(xù)轉(zhuǎn)換模式
在連續(xù)轉(zhuǎn)換模式下, ADC 結(jié)束一個(gè)轉(zhuǎn)換后立即啟動(dòng)一個(gè)新的轉(zhuǎn)換 。CONT 位為 1 時(shí),可通過外部觸發(fā)或?qū)?ADC_CR2 寄存器中的 SWSTRT 位置 1 來啟動(dòng)此模式(僅適用于規(guī)則通道)。
每次轉(zhuǎn)換之后:
● 如果轉(zhuǎn)換了規(guī)則通道組:
— 上次轉(zhuǎn)換的數(shù)據(jù)存儲(chǔ)在 16 位 ADC_DR 寄存器中
— EOC(轉(zhuǎn)換結(jié)束)標(biāo)志置 1
— EOCIE 位置 1 時(shí)將產(chǎn)生中斷
時(shí)序圖
ADC 在開始精確轉(zhuǎn)換之前需要一段穩(wěn)定時(shí)間 t STAB 。ADC 開始轉(zhuǎn)換并經(jīng)過 15 個(gè)時(shí)鐘周期后,EOC 標(biāo)志置 1,轉(zhuǎn)換結(jié)果存放在 16 位 ADC 數(shù)據(jù)寄存器中。
掃描模式
此模式用于掃描一組模擬通道。
通過將 ADC_CR1 寄存器中的 SCAN 位置 1 來選擇掃描模式。將此位置 1 后,ADC 會(huì)掃描在 ADC_SQRx 寄存器(對(duì)于規(guī)則通道)或 ADC_JSQR 寄存器(對(duì)于注入通道)中選擇的所有通道。為組中的每個(gè)通道都執(zhí)行一次轉(zhuǎn)換。每次轉(zhuǎn)換結(jié)束后,會(huì)自動(dòng)轉(zhuǎn)換該組中的下一個(gè)通道。如果將 CONT 位置 1,規(guī)則通道轉(zhuǎn)換不會(huì)在組中最后一個(gè)所選通道處停止,而是再次從第一個(gè)所選通道繼續(xù)轉(zhuǎn)換。
如果將 DMA 位置 1,則在每次規(guī)則通道轉(zhuǎn)換之后,均使用直接存儲(chǔ)器訪問 (DMA) 控制器將轉(zhuǎn)換自規(guī)則通道組的數(shù)據(jù)(存儲(chǔ)在 ADC_DR 寄存器中)傳輸?shù)?SRAM。在以下情況下,ADC_SR 寄存器中的 EOC 位置 1:
● 如果 EOCS 位清零,在每個(gè)規(guī)則組序列轉(zhuǎn)換結(jié)束時(shí)
● 如果 EOCS 位置 1,在每個(gè)規(guī)則通道轉(zhuǎn)換結(jié)束時(shí)
從注入通道轉(zhuǎn)換的數(shù)據(jù)始終存儲(chǔ)在 ADC_JDRx 寄存器中。
數(shù)據(jù)對(duì)齊
由于STM32的ADC是12位的,結(jié)果存儲(chǔ)在16位的數(shù)據(jù)寄存器中,有4位用不到,所以ADC存在左對(duì)齊或右對(duì)齊的方式。為方便讀數(shù),一般都選擇右對(duì)齊。
可獨(dú)立設(shè)置各通道采樣時(shí)間
ADC 會(huì)在數(shù)個(gè) ADCCLK 周期內(nèi)對(duì)輸入電壓進(jìn)行采樣,可使用 ADC_SMPR1 和 ADC_SMPR2寄存器中的 SMP[2:0] 位修改周期數(shù)。每個(gè)通道均可以使用不同的采樣時(shí)間進(jìn)行采樣。
總轉(zhuǎn)換時(shí)間的計(jì)算公式如下:
T conv = 采樣時(shí)間 + 12 個(gè)周期
快速轉(zhuǎn)換模式
可通過降低 ADC 分辨率來執(zhí)行快速轉(zhuǎn)換。RES 位用于選擇數(shù)據(jù)寄存器中可用的位數(shù)。每種分辨率的最小轉(zhuǎn)換時(shí)間如下:
● 12 位:3 + 12 = 15 ADCCLK 周期
● 10 位:3 + 10 = 13 ADCCLK 周期
● 8 位:3 + 8 = 11 ADCCLK 周期
● 6 位:3 + 6 = 9 ADCCLK 周期
溫度傳感器和VRENFINT通道框圖
要使用傳感器,請(qǐng)執(zhí)行以下操作:
- 選擇 ADC1_IN16 或 ADC1_IN18 輸入通道。
- 選擇一個(gè)采樣時(shí)間,該采樣時(shí)間要大于數(shù)據(jù)手冊(cè)中所指定的最低采樣時(shí)間。
- 在 ADC_CCR 寄存器中將 TSVREFE 位置 1,以便將溫度傳感器從掉電模式中喚醒。
- 通過將 SWSTART 位置 1(或通過外部觸發(fā))開始 ADC 轉(zhuǎn)換
- 讀取 ADC 數(shù)據(jù)寄存器中生成的 V SENSE 數(shù)據(jù)
- 使用以下公式計(jì)算溫度:
溫度(單位為 °C)= {(V SENSE — V 25 ) / Avg_Slope} + 25
其中:
— V 25 = 25 °C 時(shí)的 V SENSE 值
— Avg_Slope = 溫度與 V SENSE 曲線的平均斜率(以 mV/°C 或 μV/°C 表示)
由于ADC寄存器的相關(guān)配置相對(duì)比較簡(jiǎn)單,這里直接附上測(cè)量溫度相關(guān)的ADC初始化和中斷程序:
void ADC_Init()
{
u32 prigroup = 0;
u32 priority = 0;
RCC- >APB2ENR |= 1< 8; //開ADC1時(shí)鐘
ADC- >CCR = 0;
ADC- >CCR |= 1< 23; //使能溫度傳感器和 V REFINT 通道
ADC- >CCR |= 1< 16; //ADCCLK=21mHZ
ADC1- >CR1 = 0;//分辨率12位
ADC1- >CR2 = 0; //數(shù)據(jù)右對(duì)齊
ADC1- >CR2 |= 1< 10; //通道只要轉(zhuǎn)換結(jié)束,則將EOC置1,使能溢出檢測(cè)
ADC1- >SMPR1 =0; //通道16采樣時(shí)間3T
ADC1- >SQR3 |= 16< 0;
ADC1- >CR1 |= 1< 5; //使能EOC中斷
ADC1- >SR &=~ (1< 1); //清中斷標(biāo)記33
prigroup = NVIC_GetPriorityGrouping(); //得到優(yōu)先級(jí)分組
priority = NVIC_EncodePriority(prigroup,1,2); //優(yōu)先級(jí)編碼
NVIC_SetPriority(ADC_IRQn,priority); //設(shè)置中斷優(yōu)先級(jí)
NVIC_EnableIRQ(ADC_IRQn); //使能ADC中斷
ADC1- >CR2 |= 1< 0; //使能ADC
Delay_us(3);
ADC1- >CR2 |= 1< 30; //啟動(dòng)AD轉(zhuǎn)換
}
u16 ADC1_Value={0}; //定義二維數(shù)組,按行存入三個(gè)通道的轉(zhuǎn)換結(jié)束
u8 ADC1_OK = 0;
//中斷處理函數(shù)
void ADC_IRQHandler()
{
if(ADC1- >SR & (1< 1))
{
ADC1- >SR &=~ (1< 1); //寫0,請(qǐng)標(biāo)記
ADC1_Value = ADC1- >DR; //按行依次存入各通道的轉(zhuǎn)換結(jié)果
ADC1_OK = 1; //采集完成結(jié)束標(biāo)記置1
}
}
接著編寫主函數(shù)測(cè)試
#include "stm32f4xx.h"
#include "usart.h"
#include "delay.h"
#include "stdio.h"
#include "ADC.h"
extern u8 ADC1_OK;
extern u16 ADC1_Value;
int main()
{
float wendu = 0;
NVIC_SetPriorityGrouping(7-2);
Usart1_Init(115200);
ADC_Init();
while(1)
{
if(ADC1_OK == 1)
{
ADC1- >SR &=~ (1< 1); //清中斷標(biāo)記
ADC1_OK = 0;
wendu = 3.3*ADC1_Value/4095; //求溫度數(shù)字值對(duì)應(yīng)的模擬電壓值
wendu = (wendu -0.76)*1000/2.5+25; //計(jì)算溫度值
printf("溫度AD值:%drnwendu = %.lf°Crn",ADC1_Value,wendu);
ADC1- >CR2 |= 1< 0; //再次開啟ADC1
Delay_us(3);
ADC1- >CR2 |= 1< 30; //觸發(fā)一次轉(zhuǎn)換
}
Delay_ms(1000);
}
}
從串口可以看到ADC讀取的溫度值,ADC溫度測(cè)量成功。
對(duì)于電池電壓或者其他外部模擬量的測(cè)量,配置方法與溫度測(cè)量類似,這里不再贅述。如果想要讓CPU更多地用于算法或者其他功能的處理,同樣可以配置DMA進(jìn)行數(shù)據(jù)傳輸。
評(píng)論
查看更多