一、为什么需要两种温度采集方案?

在 STM32 项目中,温度采集的需求无处不在:电源监控、电机保护、环境监测等。片上温度传感器(如 STM32F4 系列内置的)无需外部硬件,适合粗略的芯片温度监测;而外部 NTC 热敏电阻精度高、响应快,适合测量环境或目标物体温度。理解两者的原理与实现,是嵌入式工程师的基本功。

二、STM32 片上温度传感器:原理与校准

2.1 工作原理

STM32 内部集成了一个基于 PN 结的温度传感器,其输出电压与温度呈线性关系。该电压通过 ADC 内部通道(如 STM32F407 的 ADC1_IN16)采样,转换公式为:

温度(°C) = (V_sense - V_25) / Avg_Slope + 25

其中 V_25 是 25°C 时的典型电压(通常为 0.76V),Avg_Slope 是平均斜率(典型值 2.5 mV/°C)。注意:这些参数因芯片型号而异,需查阅数据手册。

2.2 关键配置步骤

  1. 使能 ADC 时钟和内部传感器电源(LL_ADC_EnableInternalRegulator)。
  2. 配置 ADC 为单次转换模式,选择内部温度传感器通道。
  3. 读取 ADC 值并转换为电压,再套用公式计算温度。
  4. 为提高精度,建议使用芯片出厂校准值(如 STM32F3/F4 系列在 ROM 中存储的校准数据)。

2.3 代码示例(HAL 库)

#include "stm32f4xx_hal.h"

ADC_HandleTypeDef hadc;

void MX_ADC1_Init(void) {
    hadc.Instance = ADC1;
    hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
    hadc.Init.Resolution = ADC_RESOLUTION_12B;
    hadc.Init.ScanConvMode = DISABLE;
    hadc.Init.ContinuousConvMode = DISABLE;
    hadc.Init.DiscontinuousConvMode = DISABLE;
    hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc.Init.NbrOfConversion = 1;
    HAL_ADC_Init(&hadc);
}

float ReadChipTemperature(void) {
    ADC_ChannelConfTypeDef sConfig = {0};
    sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_84CYCLES;
    HAL_ADC_ConfigChannel(&hadc, &sConfig);

    HAL_ADC_Start(&hadc);
    HAL_ADC_PollForConversion(&hadc, 100);
    uint32_t adc_val = HAL_ADC_GetValue(&hadc);
    HAL_ADC_Stop(&hadc);

    float voltage = (float)adc_val * 3.3f / 4095.0f;
    float temp = (voltage - 0.76f) / 0.0025f + 25.0f;
    return temp;
}

注意:实际使用时,建议从芯片 ROM 读取校准值(如 V25Avg_Slope),以替代上述典型值,可显著提高精度。

三、外部 NTC 分压电路:设计与计算

3.1 电路原理

NTC(负温度系数)热敏电阻的阻值随温度升高而降低。常用分压电路:将 NTC 与固定电阻串联,中间节点接 ADC 输入。选择固定电阻时,需考虑温度测量范围和灵敏度。

NTC分压电路(示意图:VCC -> R_fixed -> 节点 -> NTC -> GND)

3.2 电阻选型与计算

假设 NTC 在 25°C 时阻值为 10kΩ(B=3950),电源为 3.3V,ADC 为 12 位。

  • 固定电阻 R_fixed 通常取 NTC 在测量范围中值附近的阻值,例如 10kΩ,以获得最大线性度。
  • 节点电压公式:V_out = VCC * R_ntc / (R_fixed + R_ntc)
  • 温度与阻值关系(Steinhart-Hart 简化公式):
float NTC_ResistanceToTemp(float resistance) {
    float T0 = 298.15f; // 25°C 开尔文
    float B = 3950.0f;
    float R0 = 10000.0f;
    float invT = 1.0f/T0 + (1.0f/B) * logf(resistance / R0);
    return 1.0f / invT - 273.15f;
}

3.3 配置步骤

  1. 硬件连接:NTC 一端接 3.3V,另一端接固定电阻到 GND,中间节点接 STM32 的 ADC 引脚(如 PA0)。
  2. 配置 ADC 引脚为模拟输入模式。
  3. 初始化 ADC,选择对应通道。
  4. 读取 ADC 值,计算节点电压,反推 NTC 阻值,再转换为温度。

3.4 代码示例(HAL 库)

#include "stm32f4xx_hal.h"
#include <math.h>

ADC_HandleTypeDef hadc;

void MX_ADC1_Init(void) {
    __HAL_RCC_ADC1_CLK_ENABLE();
    hadc.Instance = ADC1;
    hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
    hadc.Init.Resolution = ADC_RESOLUTION_12B;
    hadc.Init.ScanConvMode = DISABLE;
    hadc.Init.ContinuousConvMode = DISABLE;
    hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc.Init.NbrOfConversion = 1;
    HAL_ADC_Init(&hadc);
}

float ReadNTC_Temperature(void) {
    ADC_ChannelConfTypeDef sConfig = {0};
    sConfig.Channel = ADC_CHANNEL_0; // PA0
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_84CYCLES;
    HAL_ADC_ConfigChannel(&hadc, &sConfig);

    HAL_ADC_Start(&hadc);
    HAL_ADC_PollForConversion(&hadc, 100);
    uint32_t adc_val = HAL_ADC_GetValue(&hadc);
    HAL_ADC_Stop(&hadc);

    float voltage = (float)adc_val * 3.3f / 4095.0f;
    float r_ntc = 10000.0f * voltage / (3.3f - voltage); // 假设固定电阻为10k
    return NTC_ResistanceToTemp(r_ntc);
}

四、两种方案对比与选型建议

  • 片上传感器:零成本、无需外部电路,但精度低(±2°C 左右),且测量的是芯片内部温度,受负载影响大。适合用于芯片过热保护。
  • 外部 NTC:精度高(可达 ±0.5°C),响应快,可测量环境或物体温度,但需要额外电路和校准。适合对温度精度有要求的应用。

选型建议:若仅需监控芯片温度,优先使用片上传感器;若需测量外部环境,则选用 NTC 并做好分压电路设计。

五、注意事项与工程实践

  • ADC 参考电压:确保 VREF+ 稳定,否则会影响采样精度。可使用内部参考电压(如 2.5V)并配置 ADC 为相应范围。
  • 采样时间:NTC 阻值较大时,需增加 ADC 采样时间(如 84 或 480 周期),以稳定内部电容充电。
  • 滤波处理:对 ADC 采样值进行软件滤波(如滑动平均),可减少噪声干扰。
  • 校准:NTC 的 B 值存在离散性,批量生产时建议使用标准温度源进行两点校准。
  • 电源去耦:在 NTC 分压电路附近放置 100nF 电容,抑制电源高频噪声。

六、总结

本文详细介绍了 STM32 片上温度传感器和外部 NTC 分压电路两种方案,从原理到代码实现,并给出了选型建议。实际项目中,应根据精度、成本和环境要求灵活选择。希望这篇文章能帮助你快速完成温度采集功能,并在嵌入式开发中少走弯路。