## 一、为什么需要两种温度采集方案? 在 STM32 项目中,温度采集的需求无处不在:电源监控、电机保护、环境监测等。片上温度传感器(如 STM32F4 系列内置的)无需外部硬件,适合粗略的芯片温度监测;而外部 NTC 热敏电阻精度高、响应快,适合测量环境或目标物体温度。理解两者的原理与实现,是嵌入式工程师的基本功。 ## 二、STM32 片上温度传感器:原理与校准 ### 2.1 工作原理 STM32 内部集成了一个基于 PN 结的温度传感器,其输出电压与温度呈线性关系。该电压通过 ADC 内部通道(如 STM32F407 的 ADC1_IN16)采样,转换公式为: ```c 温度(°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 库) ```c #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 读取校准值(如 `V25` 和 `Avg_Slope`),以替代上述典型值,可显著提高精度。 ## 三、外部 NTC 分压电路:设计与计算 ### 3.1 电路原理 NTC(负温度系数)热敏电阻的阻值随温度升高而降低。常用分压电路:将 NTC 与固定电阻串联,中间节点接 ADC 输入。选择固定电阻时,需考虑温度测量范围和灵敏度。 ![NTC分压电路](https://example.com/ntc_divider.png)(示意图: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 简化公式): ```c 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 库) ```c #include "stm32f4xx_hal.h" #include 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 分压电路两种方案,从原理到代码实现,并给出了选型建议。实际项目中,应根据精度、成本和环境要求灵活选择。希望这篇文章能帮助你快速完成温度采集功能,并在嵌入式开发中少走弯路。