目錄
一丶ADC介紹
二丶ADC工作原理及管腳分布
三丶代碼部分詳解
(一)庫函數(shù)介紹
(二)代碼部分整合
一丶ADC介紹
????????ADC模塊中文名為模擬/數(shù)字轉(zhuǎn)換器,是12位逐次逼近型的模擬數(shù)字轉(zhuǎn)換器,一般用于數(shù)值的采樣??可以將引腳上連續(xù)變化的模擬電壓轉(zhuǎn)換為內(nèi)存中存儲的數(shù)字變量,建立模擬電路到數(shù)字電路的橋梁。學(xué)習(xí)過stm32后我們知道,stm32是數(shù)字電路,。數(shù)字電路沒有多少伏,多少度的概念,而通常的傳感器模塊,輸出的都是模擬量。
比如我要使用熱敏傳感器測量溫度,那么需要將傳感器模塊的模擬量,轉(zhuǎn)換成STM32可以“看懂的數(shù)字量”,所以想要讀取溫度的數(shù)值,就需要用到ADC模數(shù)轉(zhuǎn)換器來實現(xiàn)了,實現(xiàn)過程簡單來說就是ADC讀取引腳上的電壓,通過轉(zhuǎn)換,儲存到DR寄存器里。(本次使用的是STM32C8T6)
二丶ADC工作原理及管腳分布
AD轉(zhuǎn)換原理如圖
????????
?(1)ADC的輸入通道,包括IN0-IN15,共16GPIO口,和兩個內(nèi)部通道,內(nèi)部溫度傳感器,內(nèi)部參考電壓
(2)共18個輸入通道,將數(shù)據(jù)傳輸?shù)綌?shù)模轉(zhuǎn)換器,模擬多路開關(guān)可選擇我們想要的通道
(3)數(shù)模轉(zhuǎn)換器使用逐次逼近法將模擬量轉(zhuǎn)換為數(shù)字量?
(4)轉(zhuǎn)換后分為兩個組:規(guī)則組和注入組,存放準(zhǔn)換結(jié)果。
????????規(guī)則組:可以傳輸16位數(shù)據(jù),但規(guī)則組寄存器只有一位,所以如果轉(zhuǎn)運不及時會出現(xiàn)數(shù)據(jù)覆蓋的問題,前面的數(shù)據(jù)還沒有讀,后面的數(shù)據(jù)就上來了,這時候就需要用到DMA,DMA可以將ADC寄存器的數(shù)據(jù)暫時挪到DMA寄存器中,需要的時候就會被取出(本次代碼不涉及DMA,如需了解可看下篇文章)本次代碼使用的是規(guī)則組
? ? ?注入組:注入組一次可以傳輸4位數(shù)據(jù),則不需要考慮數(shù)據(jù)覆蓋的問題
(5)我們知道,ADC可以由軟件觸發(fā),也可以由硬件觸發(fā),軟件觸發(fā)顧名思義,在程序中手動調(diào)動代碼即可實現(xiàn)。而硬件觸發(fā),就是框圖內(nèi)所包含的觸發(fā)源??可系氖且?guī)則組,靠下的是注入組
(6)EOC是規(guī)則組準(zhǔn)換完成信號,JEOC是注入組轉(zhuǎn)換完成信號
總結(jié)如圖
三丶代碼部分詳解
(一)庫函數(shù)介紹
? ? ? ? 鑒于ADC庫中函數(shù)繁多,本次只介紹現(xiàn)象代碼會使用到的部分和少量拓展
1丶復(fù)位函數(shù)ADC_DeInit
void ADC_DeInit(ADC_TypeDef* ADCx);
該函數(shù)作用為將外設(shè)ADCx的全部寄存器重設(shè)為缺省值,說的簡單點就是復(fù)位,恢復(fù)“出廠設(shè)置
2丶初始化函數(shù)ADC_Init
工作模式:本次采用單ADC模式
數(shù)據(jù)對其方式:ADC轉(zhuǎn)換是12位,故存儲在寄存器中是12位的數(shù)據(jù),但數(shù)據(jù)寄存器是16位的,存儲時空位補零,所以就出現(xiàn)了數(shù)據(jù)對其問題。一半來說,我們都是采用右對齊的模式。那么左對齊有什么用呢,加入你只想讀一個大概的數(shù)據(jù),不想要這么高的分辨率,就可以使用左對齊,取前八位,就舍棄了后面的數(shù)據(jù),減小了分辨率。
ADC觸發(fā)方式:選擇內(nèi)部軟件觸發(fā)
轉(zhuǎn)換模式:單次轉(zhuǎn)換模式為轉(zhuǎn)換一次給到寄存器數(shù)據(jù)后停止。連續(xù)轉(zhuǎn)換模式轉(zhuǎn)換一次后開始下一輪轉(zhuǎn)換,一直持續(xù)下去,不需要手動開始下一次轉(zhuǎn)換
掃描模式:多通道進(jìn)行
通道數(shù)選擇:只選用一個通道
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //獨立工作模式,即單ADC模式
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //數(shù)據(jù)右對齊
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //內(nèi)部軟件觸發(fā)
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //單次轉(zhuǎn)換模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //非掃描模式
ADC_InitStructure.ADC_NbrOfChannel = 1; //只使用一個通道
ADC_Init(ADC1, &ADC_InitStructure);
3丶 ADC_Cmd使能ADC
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
4丶 ADC_DMACmd是否使用DMA
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
5丶ADC_ITConfig是否使用中斷
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);
6丶根據(jù)手冊規(guī)定,需要進(jìn)行ADC校準(zhǔn)
void ADC_ResetCalibration(ADC_TypeDef* ADCx); //復(fù)位校準(zhǔn)
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx); //復(fù)位校準(zhǔn)狀態(tài)
void ADC_StartCalibration(ADC_TypeDef* ADCx); //開始校準(zhǔn)
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx); //校準(zhǔn)狀態(tài)
7丶ADC_SoftwareStartConvCmd軟件觸發(fā)ADC
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
8丶時鐘分頻
手冊規(guī)定ADC最大14mhz,所以選擇6分頻或8分頻
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
結(jié)合上文總結(jié)一下ADC初始化流程
(1)開啟APB2時鐘和ADC時鐘
(2)ADC時鐘分頻,選擇六分頻或八分頻
(3)初始化GPIO? 注:這里GPIO模式要使用GPIO_Mode_AIN,ADC專用模式
(4)ADC及ADC通道選擇
(5)初始化ADC
(6)使能ADC,給ADC上電
(7)校準(zhǔn)ADC
(二)丶代碼部分整合
ADC部分
#include "stm32f10x.h" // Device header
void AD_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;
ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;
ADC_InitStructure.ADC_NbrOfChannel=1;
ADC_InitStructure.ADC_ScanConvMode=DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
ADC_Init(ADC1,&ADC_InitStructure);
ADC_Cmd(ADC1,ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1)==SET);
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1)==SET);
}
uint16_t AD_GetValue(void)
{
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);
return ADC_GetConversionValue(ADC1);
}
主函數(shù)部分
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "ADC.h"
#include "LED.h"
uint16_t Temp;
#define T25 298.15
#define B 3380
float Vlue;
double myLn(double a)
{
int N = 15;
int k=0,nk=0;
double x=0.0,xx=0.0,y=0.0;
x=(a-1)/(a+1);
xx = x*x;
nk = 2*N+1;
y = 1.0/nk;
for(k = N;k>0;k--)
{
nk = nk -2;
y = 1.0/nk+xx*y;
}
return 2.0*x*y;
}
float Get_Temperaturn(void )
{
float r_f = 0.0,temp_f = 0.0;
Temp = AD_GetValue();
Vlue = (float)Temp/4095*3.3;
r_f = (Vlue*10000)/(3.3-Vlue);
temp_f = 1/((myLn(r_f/10000))/B + 1/T25 ) - 273.15;
return temp_f;
}
int main(void)
{
OLED_Init();
AD_Init();
OLED_ShowString(1, 1, "Temperature:");
LED1_ON();
while (1)
{
Temp = AD_GetValue();
OLED_ShowNum(2, 3, Get_Temperaturn(), 2);
OLED_ShowString(2,6,"C");
Delay_ms(100);
if(Get_Temperaturn()>28)
{
OLED_ShowString(3,1,"warn");
}
if(Get_Temperaturn()<28)
{
OLED_ShowString(3,1,"safe");
}
}
}
關(guān)于溫度的轉(zhuǎn)換
Rt = R 乘 EXP(B 乘 (1/T1-1/T2))
對上面的公式解釋如下:
Rt 是熱敏電阻在T1溫度下的阻值;
R是熱敏電阻在T2常溫下的標(biāo)稱阻值;
B值是熱敏電阻的重要參數(shù);
EXP是e的n次方;
這里T1和T2指的是K度即開爾文溫度,K度=273.15(絕對溫度)+攝氏度;
根據(jù)串聯(lián)分壓,知道總電壓VCC 3.3v,熱敏電阻的電壓V2是adc采集后經(jīng)過轉(zhuǎn)換得到的,也是已知,
所以R1的電壓就是VCC - V2 ,然后根據(jù)R1電阻10K,可以求得電路的電流 I ,所以熱敏電阻的
電阻 就可以用電流電壓比值,于是得到Rt。
參數(shù)R 和 B值都是熱敏電阻的參數(shù),根據(jù)自己買的器件決定,我的就是10k,3380??梢詥栙u家,
也可以自己網(wǎng)上查型號。
這里還要注意,T2的單位是開爾文,所以室溫25攝氏度的開爾文是273.15+25=298.15.
就只剩下T1是未知數(shù),一元一次方程,帶進(jìn)去一算就歐克。文章來源:http://www.zghlxwxcb.cn/news/detail-774695.html
AD視頻文章來源地址http://www.zghlxwxcb.cn/news/detail-774695.html
到了這里,關(guān)于STM32--ADC數(shù)值采樣/附ADC采集熱敏傳感器使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!