STM32 内部温度测量程序(标准库HAL库双版本)

STM32 内部温度测量程序(标准库/HAL库双版本)

一、核心原理与硬件基础

1. 内部温度传感器简介

STM32多数型号(如F1/F4/L0系列)内置温度传感器,用于监测芯片内部温度,核心特性:

2. 温度计算原理(以STM32F103为例)

根据数据手册,传感器输出电压与温度的关系:

二、硬件连接(以STM32F103C8T6为例)

三、软件实现(标准库版)

1. 核心代码(基于STM32F103标准库)

1.1 头文件与宏定义(temp_sensor.h

#ifndef __TEMP_SENSOR_H
#define __TEMP_SENSOR_H

#include "stm32f10x.h"

// ADC参数(STM32F103,LSI=40kHz,VDDA=3.3V)
#define ADC1_TEMP_CH     ADC_Channel_16  // 内部温度传感器通道
#define VDDA_VOLTAGE     3.3f            // ADC参考电压(V)
#define V25             1.43f           // 25℃时传感器输出电压(V)
#define AVG_SLOPE        0.0043f         // 温度系数(4.3mV/℃,V/℃)
#define ADC_SAMPLE_TIME  ADC_SampleTime_239Cycles5  // 最长采样时间(确保精度)

// 函数声明
void ADC1_TempSensor_Init(void);  // 初始化ADC1及温度传感器
float ADC1_Read_Temp(void);       // 读取温度值(℃)

#endif /* __TEMP_SENSOR_H */

1.2 源文件实现(temp_sensor.c

#include "temp_sensor.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"

void ADC1_TempSensor_Init(void) {
    ADC_InitTypeDef ADC_InitStruct;
    GPIO_InitTypeDef GPIO_InitStruct;

    // 1. 使能时钟(ADC1、GPIOA、AFIO)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
    
    // 2. 配置ADC时钟(PCLK2分频,最大14MHz)
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);  // 72MHz/6=12MHz(F103最高ADC时钟)
    
    // 3. 配置GPIO(模拟输入)
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;  // 通道16对应PA0(F103)
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // 4. ADC初始化(独立模式、单次转换、软件触发)
    ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
    ADC_InitStruct.ADC_ScanConvMode = DISABLE;       // 单通道
    ADC_InitStruct.ADC_ContinuousConvMode = DISABLE; // 单次转换
    ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;  // 软件触发
    ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;  // 右对齐
    ADC_InitStruct.ADC_NbrOfChannel = 1;
    ADC_Init(ADC1, &ADC_InitStruct);
    
    // 5. 配置温度传感器通道(通道16,采样时间239.5周期)
    ADC_RegularChannelConfig(ADC1, ADC1_TEMP_CH, 1, ADC_SAMPLE_TIME);
    
    // 6. 使能内部温度传感器和Vrefint(关键!)
    ADC_TempSensorVrefintCmd(ENABLE);  // 必须在ADC使能前调用
    
    // 7. 使能ADC并校准
    ADC_Cmd(ADC1, ENABLE);
    ADC_ResetCalibration(ADC1);  // 复位校准
    while (ADC_GetResetCalibrationStatus(ADC1));  // 等待复位完成
    ADC_StartCalibration(ADC1);  // 开始校准
    while (ADC_GetCalibrationStatus(ADC1));  // 等待校准完成
}

float ADC1_Read_Temp(void) {
    uint16_t adc_value;
    float voltage, temp;

    // 1. 启动ADC转换(软件触发)
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    
    // 2. 等待转换完成(EOC标志)
    while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
    
    // 3. 读取ADC原始值(12位,0~4095)
    adc_value = ADC_GetConversionValue(ADC1);
    
    // 4. 计算传感器电压(V)
    voltage = (float)adc_value * VDDA_VOLTAGE / 4095.0f;
    
    // 5. 代入公式计算温度(℃)
    temp = 25.0f + (V25 - voltage) / AVG_SLOPE;
    
    return temp;  // 返回温度值
}

1.3 主程序调用示例(main.c

#include "stm32f10x.h"
#include "temp_sensor.h"
#include "usart.h"  // 假设已实现串口初始化(用于打印)

int main(void) {
    float temp;
    SystemInit();       // 系统时钟初始化(72MHz)
    USART1_Init(115200);  // 串口初始化(调试用)
    ADC1_TempSensor_Init();  // 初始化ADC及温度传感器

    while (1) {
        temp = ADC1_Read_Temp();  // 读取温度
        printf("Internal Temp: %.2f ℃\r\n", temp);  // 串口输出
        Delay_ms(1000);  // 延时1秒(需实现Delay_ms函数)
    }
}

四、软件实现(HAL库版,以STM32F407为例)

1. 核心代码(HAL库)

1.1 初始化函数(temp_sensor_hal.c

#include "temp_sensor_hal.h"
#include "stm32f4xx_hal.h"

ADC_HandleTypeDef hadc1;

void ADC1_TempSensor_Init(void) {
    ADC_ChannelConfTypeDef sConfig = {0};

    // 1. 使能时钟
    __HAL_RCC_ADC1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();

    // 2. ADC配置
    hadc1.Instance = ADC1;
    hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;  // 84MHz/4=21MHz(F407 ADC最大36MHz)
    hadc1.Init.Resolution = ADC_RESOLUTION_12B;
    hadc1.Init.ScanConvMode = DISABLE;
    hadc1.Init.ContinuousConvMode = DISABLE;
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc1.Init.NbrOfConversion = 1;
    hadc1.Init.DMAContinuousRequests = DISABLE;
    hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
    HAL_ADC_Init(&hadc1);

    // 3. 配置温度传感器通道(F407为通道18)
    sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;  // 内部温度传感器通道
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;  // 480周期采样(F407需更长采样时间)
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);

    // 4. 使能温度传感器(HAL库自动处理TSVREFE位)
    HAL_ADCEx_EnableInternalRegulator(&hadc1);
    HAL_Delay(10);  // 等待内部稳压器稳定
}

float ADC1_Read_Temp_HAL(void) {
    uint32_t adc_value;
    float voltage, temp;

    HAL_ADC_Start(&hadc1);  // 启动转换
    HAL_ADC_PollForConversion(&hadc1, 10);  // 等待转换完成
    adc_value = HAL_ADC_GetValue(&hadc1);  // 读取ADC值

    // F407参数:V25=0.76V,Avg_Slope=0.0025V/℃(数据手册)
    voltage = (float)adc_value * 3.3f / 4095.0f;  // VDDA=3.3V
    temp = 25.0f + (0.76f - voltage) / 0.0025f;  // 代入F407公式

    return temp;
}

参考代码 STM32 测量内部温度程序 www.youwenfan.com/contentcst/133742.html

五、关键注意事项

1. 硬件前提

2. 软件优化

3. 常见问题排查

问题 原因 解决方案
温度值恒为0或异常 未使能TSVREFE位(标准库ADC_TempSensorVrefintCmd(ENABLE) 检查使能代码是否执行
温度波动大 电源噪声或单次采样误差 增加采样次数取平均,加去耦电容
ADC转换超时 ADC时钟过快(超过14MHz) 降低RCC_ADCCLKConfig分频系数

六、扩展应用

七、总结

STM32内部温度测量通过ADC采集传感器电压+公式换算实现,核心是确保ADC配置正确(通道、采样时间、使能传感器)和参数准确(依芯片型号调整)。标准库与HAL库实现思路一致,仅函数名和配置方式略有差异,适用于芯片温度监控、过热保护等场景。

专注于matlab/simulink,电子电路,编程