库函数NTC采样温度的方法(STC8)
STC8的NTC采样方法
硬件连接
- NTC电阻一端接VCC,另一端接GND,中间串联一个固定电阻(如10kΩ),连接至ADC输入引脚。
- 确保ADC参考电压稳定,通常使用VCC或外部基准电压源。
ADC配置
- 初始化ADC模块,选择对应的ADC通道和时钟分频。
- 配置ADC结果格式(左对齐或右对齐),STC8通常支持10位或12位分辨率。
- 启用ADC并等待稳定,可能需短暂延时。
温度计算
- 读取ADC原始值,计算NTC电阻值:
[
R_{ntc} = \frac{R_{fixed} \times ADC_{value}}{ADC_{max} - ADC_{value}}
]
其中 ( R_{fixed} ) 为固定电阻值,( ADC_{max} ) 为ADC最大值(如1023或4095)。 - 使用Steinhart-Hart公式转换电阻值为温度:
[
\frac{1}{T} = A + B \cdot \ln(R_{ntc}) + C \cdot (\ln(R_{ntc}))^3
]
参数A、B、C需根据NTC规格书提供的数据拟合。
代码示例
#include "GPIO.h"
#include "Delay.h"
#include "UART.h" // 串口配置 UART_Configuration
#include "NVIC.h" // 中断初始化NVIC_UART1_Init
#include "Switch.h" // 引脚切换 UART1_SW_P30_P31
#include "ADC.h"
#include <math.h> // log()// 定义一个结构体来存储NTC热敏电阻的参数
typedef struct {double r_naught; // 参考电阻值 R25 (Ohm)double b_25_50; // B值常数,适用于较低温范围 (e.g., < 50°C)double b_25_85; // B值常数,适用于较高温范围 (e.g., >= 50°C)
} NtcParameters;/*** @brief 根据NTC热敏电阻的阻值计算温度(摄氏度),支持分段B值以提高精度。** @param resistance_ohm 实际测量到的电阻值 (Ohm)。* @param params 一个指向NtcParameters结构体的指针,包含热敏电阻的所有参数。* @return 计算出温度,单位为摄氏度 (°C)。*/
double ntc_to_celsius_segmented(double resistance_ohm, const NtcParameters* params) {const double T_NAUGHT_K = 298.15; // 参考温度 T0 (25°C) 的开尔文值double b_selected; // 将被选择用于最终计算的B值double temp_kelvin_guess;double temp_celsius_guess;double temp_kelvin_final;// --- 步骤1: 使用默认的B值 (b_25_50) 计算初步温度 ---temp_kelvin_guess = 1.0 / ( (log(resistance_ohm / params->r_naught) / params->b_25_50) + (1.0 / T_NAUGHT_K) );temp_celsius_guess = temp_kelvin_guess - 273.15;// --- 步骤2: 根据初步温度选择更合适的B值 ---// 我们以50°C作为分段点if (temp_celsius_guess >= 50.0) {b_selected = params->b_25_85; // 温度较高,使用高温范围的B值} else {b_selected = params->b_25_50; // 温度较低,使用低温范围的B值}// --- 步骤3: 使用选定的B值进行最终的精确计算 ---temp_kelvin_final = 1.0 / ( (log(resistance_ohm / params->r_naught) / b_selected) + (1.0 / T_NAUGHT_K) );return temp_kelvin_final - 273.15;
}void GPIO_config() { GPIO_InitTypeDef info;// ===== UART1 P30 P31 准双向info.Mode = GPIO_PullUp; // 准双向info.Pin = GPIO_Pin_0 | GPIO_Pin_1; // 引脚GPIO_Inilize(GPIO_P3, &info);// P04 高阻输入info.Mode = GPIO_HighZ; // 高阻输入info.Pin = GPIO_Pin_4; // 引脚GPIO_Inilize(GPIO_P0, &info);
}// 串口配置函数的定义
void UART_config(void) {// >>> 记得添加 NVIC.c, UART.c, UART_Isr.c <<<COMx_InitDefine COMx_InitStructure; //结构定义COMx_InitStructure.UART_Mode = UART_8bit_BRTx; //模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTxCOMx_InitStructure.UART_BRT_Use = BRT_Timer1; //选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)COMx_InitStructure.UART_BaudRate = 115200ul; //波特率, 一般 110 ~ 115200COMx_InitStructure.UART_RxEnable = ENABLE; //接收允许, ENABLE或DISABLECOMx_InitStructure.BaudRateDouble = DISABLE; //波特率加倍, ENABLE或DISABLEUART_Configuration(UART1, &COMx_InitStructure); //初始化串口1 UART1,UART2,UART3,UART4NVIC_UART1_Init(ENABLE,Priority_1); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3UART1_SW(UART1_SW_P30_P31); // 引脚选择, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}/******************* AD配置函数 *******************/
void ADC_config(void)
{ADC_InitTypeDef ADC_InitStructure; //结构定义ADC_InitStructure.ADC_SMPduty = 31; //ADC 模拟信号采样时间控制, 0~31(注意: SMPDUTY 一定不能设置小于 10)ADC_InitStructure.ADC_CsSetup = 0; //ADC 通道选择时间控制 0(默认),1ADC_InitStructure.ADC_CsHold = 1; //ADC 通道选择保持时间控制 0,1(默认),2,3ADC_InitStructure.ADC_Speed = ADC_SPEED_2X1T; //设置 ADC 工作时钟频率 ADC_SPEED_2X1T~ADC_SPEED_2X16TADC_InitStructure.ADC_AdjResult = ADC_RIGHT_JUSTIFIED; //ADC结果调整, ADC_LEFT_JUSTIFIED,ADC_RIGHT_JUSTIFIEDADC_Inilize(&ADC_InitStructure); //初始化ADC_PowerControl(ENABLE); //ADC电源开关, ENABLE或DISABLENVIC_ADC_Init(DISABLE,Priority_0); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}void main() {u16 adc;float vol; // 电压float r; // 电阻double temp; // 温度// R25 = 10kΩ// B-Constant (25-50°C) = 3950// B-Constant (25-85°C) = 3950 // 这个如果没有,和(25-50°C)值一样NtcParameters params = {10000.0,3950.0,3950.0, // 这个如果没有,和(25-50°C)值一样};EA = 1; // 使能中断总开关GPIO_config(); // GPIO配置UART_config(); // 串口配置ADC_config(); // ADC配置while (1){// 读取ADC采样值,是采样值,不是电压值,但和电压有关系// 参数不能乱写,原理图 芯片手册 P04 对应的通道是 12 通道adc = Get_ADCResult(ADC_CH12);// 转换为电压vol = adc * 2.5 / 4095;// 计算出电阻r = vol * 10 / (3.3 - vol);// 通过查表得到温度temp = ntc_to_celsius_segmented(r * 1000.0, ¶ms);printf("r = %.2f, temp = %.1f°\n", r, temp);// 处理的太快delay_ms(250);delay_ms(250);}
}
注意事项
- 校准ADC参考电压,避免电源波动影响精度。
- 使用查表法替代复杂公式计算,提升实时性。
- 添加软件滤波(如滑动平均)减少噪声干扰。
- NTC的B值需与实际型号匹配,不同型号参数差异较大。