STM32 内部温度传感器测量程序(标准库函数版)

一、核心原理与硬件基础

1. 内部温度传感器简介

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

  • 连接通道 :STM32F103系列中,内部温度传感器连接ADC1的通道16 (需使能TSVREFE位)。
  • 测量范围:-40℃~125℃(具体以数据手册为准)。
  • 精度:±1.5℃(典型值,受VDDA电压、采样时间影响)。
  • 转换公式:基于传感器输出电压与温度的线性关系(需参考芯片数据手册)。

2. 温度计算原理

根据STM32F103数据手册,内部温度传感器输出电压VSENSEV_{SENSE}VSENSE与温度TTT的关系为:
VSENSE=V25−(T−25)×Avg_SlopeV_{SENSE} = V_{25} - (T - 25) \times \text{Avg\_Slope}VSENSE=V25−(T−25)×Avg_Slope

其中:

  • V25V_{25}V25:25℃时的输出电压(典型值1.43V);
  • Avg_Slope\text{Avg\_Slope}Avg_Slope:温度系数(典型值4.3mV/℃);
  • TTT:实际温度(℃)。

通过ADC采集VSENSEV_{SENSE}VSENSE对应的数字量,反推温度:
T=25+V25−VSENSEAvg_SlopeT = 25 + \frac{V_{25} - V_{SENSE}}{\text{Avg\_Slope}}T=25+Avg_SlopeV25−VSENSE

其中,VSENSE=ADC值×VDDA4095V_{SENSE} = \frac{\text{ADC值} \times V_{\text{DDA}}}{4095}VSENSE=4095ADC值×VDDA(12位ADC,VDDAV_{\text{DDA}}VDDA为ADC参考电压,通常3.3V)。

二、程序设计(基于STM32F103标准库)

1. 核心函数组成

函数 功能 依赖库文件
ADC1_TempSensor_Init 初始化ADC1及内部温度传感器通道 stm32f10x_adc.cstm32f10x_rcc.c
ADC1_Read_Temp 读取ADC值并计算温度(℃) stm32f10x_adc.c

2. 完整代码实现

2.1 头文件与宏定义(temp_sensor.h
c 复制代码
#ifndef __TEMP_SENSOR_H
#define __TEMP_SENSOR_H

#include "stm32f10x.h"

// ADC参数定义(STM32F103)
#define ADC1_DR_Address    ((uint32_t)0x4001244C)  // ADC1数据寄存器地址
#define TEMP_SENSOR_CH     ADC_Channel_16           // 内部温度传感器通道(ADC1_CH16)
#define VDDA_VOLTAGE       3.3f                     // ADC参考电压(单位:V)
#define V25                1.43f                    // 25℃时传感器输出电压(单位:V)
#define AVG_SLOPE          0.0043f                  // 温度系数(4.3mV/℃,单位:V/℃)

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

#endif /* __TEMP_SENSOR_H */
2.2 源文件实现(temp_sensor.c
c 复制代码
#include "temp_sensor.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"

/**
 * @brief  初始化ADC1及内部温度传感器通道
 * @param  无
 * @retval 无
 */
void ADC1_TempSensor_Init(void) {
    ADC_InitTypeDef ADC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    
    // 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(STM32F103最高ADC时钟)
    
    // 3. 配置GPIO(内部温度传感器无需外部引脚,此处仅为占位)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;  // 示例引脚(实际不使用)
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;  // 模拟输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 4. ADC初始化(独立模式、单次转换、软件触发)
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  // 独立模式
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;       // 单通道模式(非扫描)
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 单次转换(非连续)
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;  // 软件触发
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  // 右对齐
    ADC_InitStructure.ADC_NbrOfChannel = 1;  // 转换通道数:1(通道16)
    ADC_Init(ADC1, &ADC_InitStructure);
    
    // 5. 配置温度传感器通道(通道16,采样时间239.5周期)
    ADC_RegularChannelConfig(ADC1, TEMP_SENSOR_CH, 1, ADC_SampleTime_239Cycles5);
    
    // 6. 使能内部温度传感器和Vrefint通道(关键!)
    ADC_TempSensorVrefintCmd(ENABLE);  // 需在ADC使能前调用
    
    // 7. 使能ADC1并校准
    ADC_Cmd(ADC1, ENABLE);
    ADC_ResetCalibration(ADC1);  // 复位校准寄存器
    while (ADC_GetResetCalibrationStatus(ADC1));  // 等待复位完成
    ADC_StartCalibration(ADC1);  // 开始校准
    while (ADC_GetCalibrationStatus(ADC1));  // 等待校准完成
}

/**
 * @brief  读取ADC值并计算温度(℃)
 * @param  无
 * @retval 温度值(浮点数,单位℃)
 */
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;
}

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

c 复制代码
#include "stm32f10x.h"
#include "temp_sensor.h"
#include "stdio.h"

// 重定向printf到串口(可选,用于调试输出)
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE {
    USART_SendData(USART1, (uint8_t)ch);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    return ch;
}

int main(void) {
    float temperature;
    
    // 初始化系统时钟(72MHz,省略具体代码)
    SystemInit();
    
    // 初始化串口(用于调试输出,可选)
    USART1_Init(115200);  // 假设已实现串口初始化函数
    
    // 初始化ADC1及温度传感器
    ADC1_TempSensor_Init();
    
    while (1) {
        // 读取温度(每秒1次)
        temperature = ADC1_Read_Temp();
        printf("Chip Temperature: %.2f ℃\r\n", temperature);  // 串口输出
        
        // 延时1秒(可通过SysTick实现)
        Delay_ms(1000);
    }
}

// 简单延时函数(毫秒级)
void Delay_ms(uint32_t ms) {
    uint32_t i;
    for (; ms > 0; ms--)
        for (i = 0; i < 7200; i++);  // 72MHz时钟下约1ms
}

参考代码 STM32 测量内部温度传感器程序(库函数) www.youwenfan.com/contentcst/133729.html

三、关键注意事项

1. 硬件前提

  • VDDA电压 :确保ADC参考电压VDDAV_{\text{DDA}}VDDA稳定(通常3.3V),若实际电压偏离,需修改代码中VDDA_VOLTAGE宏定义。
  • 芯片型号差异 :不同STM32型号的传感器参数(V25V_{25}V25、Avg_Slope\text{Avg\Slope}Avg_Slope)可能不同(如F4系列V25=0.76VV{25}=0.76VV25=0.76V,Avg_Slope=2.5mV/℃\text{Avg\_Slope}=2.5mV/℃Avg_Slope=2.5mV/℃),需查阅对应数据手册。

2. 软件优化

  • 多次采样平均 :单次采样误差较大,建议连续采样5~10次取平均值(如adc_value = (adc_value1 + adc_value2 + ...) / n)。
  • 校准必要性 :ADC校准(ADC_StartCalibration)可减少转换误差,必须在ADC使能前完成。
  • 采样时间:内部温度传感器响应较慢,建议使用最长采样时间(239.5周期),确保转换精度。

3. 常见问题排查

问题 原因 解决方案
温度值恒为0或异常 未使能TSVREFE位(ADC_TempSensorVrefintCmd 调用ADC_TempSensorVrefintCmd(ENABLE)
温度波动大 电源噪声或单次采样误差 增加采样次数取平均,靠近芯片放置去耦电容
ADC转换超时 ADC时钟过快(超过14MHz) 降低RCC_ADCCLKConfig分频系数(如RCC_PCLK2_Div8

四、扩展应用

1. 温度报警功能

c 复制代码
// 温度超限报警(阈值30℃)
#define TEMP_THRESHOLD 30.0f
if (temperature > TEMP_THRESHOLD) {
    GPIO_SetBits(GPIOB, GPIO_Pin_0);  // 触发GPIO输出(如LED报警)
}

2. 低功耗优化

  • 休眠模式 :读取温度后关闭ADC(ADC_Cmd(ADC1, DISABLE)),需要时再开启。
  • DMA传输:通过DMA自动读取ADC值,减少CPU干预(适用于多通道采样)。

五、总结

本程序基于STM32标准库实现了内部温度传感器的读取与温度计算,核心步骤包括ADC初始化传感器通道配置ADC值读取公式换算。使用时需注意芯片型号差异与硬件参数校准,适用于芯片温度监控、过热保护等场景。

核心价值:无需外部传感器,低成本实现STM32内部温度监测,为嵌入式系统的热管理提供基础支持。

相关推荐
Hello.Reader3 小时前
为什么学线性代数(一)
线性代数·算法·机器学习
天狼IoT3 小时前
STM32-keil+CubeMX快速开发:新建项目
stm32·单片机·嵌入式硬件
Tomhex3 小时前
STM32型号命名解析
stm32
_深海凉_3 小时前
LeetCode热题100-找到字符串中所有字母异位词
算法·leetcode·职场和发展
木井巳3 小时前
【递归算法】目标和
java·算法·leetcode·决策树·深度优先
旖-旎3 小时前
哈希表(字母异位次分组)(5)
数据结构·c++·算法·leetcode·哈希算法·散列表
别或许3 小时前
4、高数----一元函数微分学的计算
人工智能·算法·机器学习
_深海凉_4 小时前
LeetCode热题100-最长连续序列
算法·leetcode·职场和发展
这里没有酒4 小时前
[信息安全] AES128 加密/解密 --> state 矩阵
算法