
1. STM32内部温度传感器的工作原理STM32F103ZET6芯片内部集成了一个温度传感器这个设计非常巧妙。它就像给芯片装了一个体温计可以实时监测CPU的工作温度。这个传感器本质上是一个输出电压会随温度变化的半导体器件其工作原理基于PN结的温度特性。具体来说当温度升高时传感器输出的电压会线性下降。这个变化关系非常稳定每升高1摄氏度输出电压大约下降4.3mV这个值就是Avg_Slope参数。传感器固定在ADC的通道16上所以我们只需要读取这个通道的值就能获取当前的电压读数。在实际应用中这个内部温度传感器有几个特点需要注意。首先它的测量范围是-40℃到125℃基本覆盖了芯片的正常工作温度范围。其次精度约为±1.5℃虽然不算特别精确但对于监控芯片温度变化趋势已经足够。最后它不需要任何外部元件使用起来非常方便。2. ADC配置的关键要点要让温度传感器正常工作ADC的配置至关重要。这里有几个容易踩坑的地方需要特别注意首先是采样时间的设置。由于温度传感器的输出阻抗较高官方推荐将采样时间设置为17.1μs以上。如果采样时间太短会导致采集到的电压值不准确。在STM32CubeMX中配置时建议选择ADC_SampleTime_239Cycles5这个选项它对应约17.9μs的采样时间假设ADC时钟为14MHz。其次是参考电压的选择。STM32F103的ADC参考电压通常是VREF引脚上的电压如果没有外接参考电压则会使用VDDA通常为3.3V。在计算温度时必须确保代码中使用的参考电压值与实际硬件一致。另外还需要注意ADC的校准。在初始化ADC后建议先执行校准程序HAL_ADCEx_Calibration_Start(hadc1);这个步骤可以消除ADC的零点误差提高测量精度。3. 温度计算的完整公式解析从ADC读数到实际温度的转换需要经过几个步骤我们来详细拆解这个计算过程第一步是将ADC的原始值转换为电压。STM32F103的ADC是12位的所以最大值为4095。电压计算公式为Vsense (ADC_Value / 4095.0) * Vref其中Vref是参考电压通常是3.3V。第二步是使用温度计算公式Temperature (V25 - Vsense) / Avg_Slope 25这里有几个关键参数V25芯片在25℃时的传感器输出电压典型值为1.43VAvg_Slope温度系数典型值为4.3mV/℃25参考温度对应V25的测量温度在实际代码中这个计算可以简化为float temperature (1.43 - voltage) / 0.0043 25.0;需要注意的是这个公式计算出来的温度是芯片内部的温度可能与环境温度有差异。4. UART输出温度数据的实现将温度数据通过UART输出可以方便我们实时监控芯片温度。这里给出一个完整的实现方案首先需要在STM32CubeMX中配置USART外设。建议使用115200的波特率8位数据位无校验位1位停止位的基本配置。配置完成后生成初始化代码。然后在主程序中添加数据发送逻辑。为了提高代码可读性建议将温度采集和发送封装成函数void SendTemperature(void) { uint8_t header[] 当前温度; char tempStr[10]; float voltage, temperature; HAL_ADC_Start(hadc1); if(HAL_ADC_PollForConversion(hadc1, 20) HAL_OK) { voltage (float)HAL_ADC_GetValue(hadc1) / 4095.0 * 3.3f; temperature (1.43f - voltage) / 0.0043f 25.0f; sprintf(tempStr, %.1f℃\r\n, temperature); HAL_UART_Transmit(huart1, header, sizeof(header)-1, 100); HAL_UART_Transmit(huart1, (uint8_t*)tempStr, strlen(tempStr), 100); } }在main函数的while循环中定期调用这个函数即可。建议采样间隔不要太短1秒左右比较合适这样可以避免频繁的ADC转换影响系统性能。5. 完整代码实现与优化结合前面的内容我们来看一个完整的实现方案。首先在STM32CubeMX中进行如下配置在ADC1中启用Channel 16温度传感器通道设置采样时间为239.5个周期配置USART1为异步模式波特率115200生成代码时选择生成单独的.c/.h文件生成的代码基础上我们添加温度测量功能。这里给出优化后的完整main.c代码#include main.h #include adc.h #include usart.h #include gpio.h #include stdio.h #include string.h ADC_HandleTypeDef hadc1; UART_HandleTypeDef huart1; void SystemClock_Config(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); MX_USART1_UART_Init(); // ADC校准 HAL_ADCEx_Calibration_Start(hadc1); while (1) { float voltage, temperature; char buffer[50]; HAL_ADC_Start(hadc1); if(HAL_ADC_PollForConversion(hadc1, 20) HAL_OK) { voltage (float)HAL_ADC_GetValue(hadc1) / 4095.0f * 3.3f; temperature (1.43f - voltage) / 0.0043f 25.0f; int len sprintf(buffer, 芯片温度%.1f℃\r\n, temperature); HAL_UART_Transmit(huart1, (uint8_t*)buffer, len, 100); } HAL_Delay(1000); } }这段代码做了几点优化增加了ADC校准步骤提高测量精度使用单个sprintf简化字符串处理添加了适当的延时避免频繁采样使用浮点运算确保计算精度6. 常见问题与调试技巧在实际项目中可能会遇到各种问题。这里分享几个常见问题的解决方法问题1温度读数不稳定波动很大 解决方法检查ADC采样时间是否足够建议≥17.1μs在ADC输入端添加0.1μF的滤波电容多次采样取平均值比如采样10次后取中值问题2温度值与实际环境差异较大 解决方法确认参考电压准确可以测量VDDA引脚电压检查V25和Avg_Slope参数是否使用正确值注意芯片自身发热的影响测量时需要保持稳定工作状态问题3UART输出乱码 解决方法检查波特率设置确保收发双方一致确认地线连接良好检查串口助手的设置特别是数据位和停止位调试时可以先用一个已知电压测试ADC比如用电阻分压产生1.5V输入到某个ADC通道验证ADC读数是否正确。这样可以先排除ADC部分的问题再集中精力解决温度计算的问题。7. 实际应用中的注意事项在实际产品中使用内部温度传感器时还需要注意以下几点上电后需要等待传感器稳定。建议在初始化后延迟至少10ms再进行第一次采样。由于传感器位于芯片内部测量到的是芯片结温通常比环境温度高。如果要监测环境温度需要考虑这个温差。在低功耗应用中需要注意ADC和温度传感器的功耗。不使用时可以关闭它们以节省电量。对于精度要求高的场合可以考虑进行两点校准在已知的低温点和高温点测量然后调整计算参数。长时间连续测量时建议间隔采样而不是连续采样这样可以减少传感器自热效应的影响。在计算温度时使用浮点运算会占用较多资源。如果需要在资源受限的场合使用可以考虑将公式转换为定点数运算int32_t temp (1430 - adc_value * 3300 / 4095) * 100 / 43 2500;这样计算得到的是放大100倍的温度值单位0.01℃可以避免使用浮点数。