STM32內(nèi)部集成了一個(gè)片上溫度傳感器,可以用來(lái)測(cè)量MCU及周圍的溫度。測(cè)量范圍:-40~125,精度±1.5℃。雖然精度不高,但在某些應(yīng)用場(chǎng)景下是夠了的,相比于外部接入傳感器,使用內(nèi)部溫度傳感器既可以節(jié)省成本,又可以簡(jiǎn)化電路。
1 溫度傳感器簡(jiǎn)介
1.1 工作原理
STM32內(nèi)部溫度傳感器在芯片內(nèi)部與ADCx_IN16輸入通道相連接,此通道把傳感器輸出的電壓轉(zhuǎn)換成數(shù)字值,繼而換算成溫度值。因此,我們只需設(shè)置一下內(nèi)部ADC,并激活其內(nèi)部通道就可以了。
溫度換算公式如下:
T(℃)= ((V25 - Vsense) / Avg_Slope) + 25
注:
1、V25:Vsense在25度時(shí)的數(shù)值(典型值為:1.43)。
2、Avg_Slope:溫度與Vsense曲線的平均斜率(單位為 mv/℃或 uv/℃)(典型值為4.3mv/℃)。
3、Vsense:溫度傳感器的當(dāng)前輸出電壓(溫度傳感器模擬輸入推薦最快采樣時(shí)間是17.1μs)。
溫度傳感器特性如下:
1.2 軟件配置步驟
1、配置ADC參數(shù)。
2、使能內(nèi)部溫度傳感器。
3、讀取ADC數(shù)值并轉(zhuǎn)換成溫度值。
1.3 注意事項(xiàng)
1、溫度傳感器輸出電壓隨溫度線性變化,由于生產(chǎn)過(guò)程的變化,溫度變化曲線的偏移在不同芯片上會(huì)有不同(最多相差45°C)。
2、內(nèi)部溫度傳感器更適合于檢測(cè)溫度的變化,而不是測(cè)量絕對(duì)的溫度,如果需要測(cè)量精確的溫度,應(yīng)該使用一個(gè)外置的溫度傳感器。
3、硬件設(shè)計(jì)上注意VREF+和VREF-的接入電壓(如果該MCU封裝有VREF引腳的話,一般64pin及以下的沒(méi)有)。
2 程序編寫
根據(jù)上面的原理介紹,使用ADC1的通道16作為采集輸入信號(hào),采集到ADC電壓值以后根據(jù)溫度轉(zhuǎn)換公式轉(zhuǎn)換成溫度數(shù)據(jù)。
參考測(cè)試代碼:
#include "delay.h"
#include "sys.h"
#include "usart.h"
// 初始化配置ADC參數(shù)(以規(guī)則通道為例)
void T_Adc_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_AFIO, ENABLE); // 使能ADC1通道時(shí)鐘
RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 分頻因子6時(shí)鐘為72M/6=12MHz
ADC_DeInit(ADC1); // 將外設(shè)ADC1的全部寄存器重設(shè)為缺省值
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // ADC工作模式:ADC1和ADC2工作在獨(dú)立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 模數(shù)轉(zhuǎn)換工作在單通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 模數(shù)轉(zhuǎn)換工作在單次轉(zhuǎn)換模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 轉(zhuǎn)換由軟件而不是外部觸發(fā)啟動(dòng)
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // ADC數(shù)據(jù)右對(duì)齊
ADC_InitStructure.ADC_NbrOfChannel = 1; // 順序進(jìn)行規(guī)則轉(zhuǎn)換的ADC通道的數(shù)目
ADC_Init(ADC1, &ADC_InitStructure); // 根據(jù)ADC_InitStruct中指定的參數(shù)初始化外設(shè)ADCx的寄存器
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_239Cycles5); // ADC1規(guī)則通道轉(zhuǎn)換,采樣時(shí)間為239.5周期
ADC_Cmd(ADC1, ENABLE); // 使能指定的ADC1
ADC_TempSensorVrefintCmd(ENABLE); // 開啟內(nèi)部溫度傳感器
ADC_ResetCalibration(ADC1); // 重置指定的ADC1的復(fù)位寄存器
while(ADC_GetResetCalibrationStatus(ADC1)); // 獲取ADC1重置校準(zhǔn)寄存器的狀態(tài),設(shè)置狀態(tài)則等待
ADC_StartCalibration(ADC1); // ADC1校準(zhǔn)
while(ADC_GetCalibrationStatus(ADC1)); // 獲取指定ADC1的校準(zhǔn)程序,設(shè)置狀態(tài)則等待
// ADC_SoftwareStartConvCmd(ADC1,ENABLE); // 軟件觸發(fā)開始
}
// 獲取ADC值
uint16_t T_Get_Adc(uint8_t ch)
{
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5); // ADC1規(guī)則通道轉(zhuǎn)換,采樣時(shí)間為239.5周期
ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 使能指定的ADC1的軟件轉(zhuǎn)換啟動(dòng)功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); // 等待轉(zhuǎn)換結(jié)束
return ADC_GetConversionValue(ADC1); // 返回最近一次ADC1規(guī)則組的轉(zhuǎn)換結(jié)果
}
// 獲取通道ch的轉(zhuǎn)換值(取times次平均值)
uint16_t T_Get_Adc_Average(uint8_t ch, uint8_t times)
{
uint32_t temp_val = 0;
uint8_t t;
for(t = 0; t < times; t++)
{
temp_val += T_Get_Adc(ch);
delay_ms(5);
}
return temp_val / times;
}
// 獲取內(nèi)部溫度傳感器溫度值
// 返回值:溫度值(擴(kuò)大了100倍,單位:℃)
int Get_Temprate(void)
{
uint32_t adcx;
int result;
double Vsense;
double temperate;
adcx = T_Get_Adc_Average(ADC_Channel_16, 20); // 讀取通道16, 20次取平均
Vsense = (double)adcx * 3.3 / 4096; // 電壓值
temperate = (1.43 - Vsense) / 0.0043 + 25; // 轉(zhuǎn)換為溫度值,轉(zhuǎn)換公式:T(℃)= ((V25 - Vsense) / Avg_Slope) + 25
result = (temperate *= 100); // 擴(kuò)大100倍.
return result;
}
int main(void)
{
int temp;
SystemInit();
delay_init(); // 延時(shí)函數(shù)初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設(shè)置中斷優(yōu)先級(jí)分組為組2:2位搶占優(yōu)先級(jí),2位響應(yīng)優(yōu)先級(jí)
uart_init(115200); // 串口初始化為115200
T_Adc_Init(); // ADC初始化
while(1)
{
temp = Get_Temprate(); // 讀取溫度值
if(temp > 0)
{// 溫度為正數(shù)
printf("temp: %d.%02dC", temp/100, temp%100);
}
else
{// 溫度為負(fù)數(shù)
printf("temp: %d.%02dC", temp/100, -temp%100);
}
delay_ms(500);
}
}
示例代碼測(cè)試結(jié)果:
結(jié)束語(yǔ)
上面的測(cè)試?yán)又皇墙o大家做一個(gè)參考,實(shí)際上需要根據(jù)項(xiàng)目的具體需求去補(bǔ)充細(xì)節(jié),比如溫度的采樣方式和采樣頻率,本文只是用最簡(jiǎn)單的單次采樣,實(shí)際上可以使用DMA進(jìn)行連續(xù)采樣,跟普通ADC使用是一樣的,這里就不再多說(shuō)了,大家根據(jù)自己的實(shí)際情況調(diào)整即可。
好了,關(guān)于STM32如何使用內(nèi)部溫度傳感器就介紹到這里,如果你們還有什么問(wèn)題,歡迎評(píng)論區(qū)留言。
如果這篇文章能夠幫到你,就…懂的。