库函数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_BRTx
    COMx_InitStructure.UART_BRT_Use   = BRT_Timer1;			//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
    COMx_InitStructure.UART_BaudRate  = 115200ul;			//波特率, 一般 110 ~ 115200
    COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLE
    COMx_InitStructure.BaudRateDouble = DISABLE;			//波特率加倍, ENABLE或DISABLE
    UART_Configuration(UART1, &COMx_InitStructure);		//初始化串口1 UART1,UART2,UART3,UART4

  	NVIC_UART1_Init(ENABLE,Priority_1);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
    UART1_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(默认),1
	ADC_InitStructure.ADC_CsHold    = 1;		//ADC 通道选择保持时间控制 0,1(默认),2,3
	ADC_InitStructure.ADC_Speed     = ADC_SPEED_2X1T;		//设置 ADC 工作时钟频率	ADC_SPEED_2X1T~ADC_SPEED_2X16T
	ADC_InitStructure.ADC_AdjResult = ADC_RIGHT_JUSTIFIED;	//ADC结果调整,	ADC_LEFT_JUSTIFIED,ADC_RIGHT_JUSTIFIED
	ADC_Inilize(&ADC_InitStructure);		//初始化
	ADC_PowerControl(ENABLE);				//ADC电源开关, ENABLE或DISABLE
	NVIC_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, &params);
        printf("r = %.2f, temp = %.1f°\n", r, temp);

        // 处理的太快
        delay_ms(250);
        delay_ms(250);
    }
}

注意事项

  • 校准ADC参考电压,避免电源波动影响精度。
  • 使用查表法替代复杂公式计算,提升实时性。
  • 添加软件滤波(如滑动平均)减少噪声干扰。
  • NTC的B值需与实际型号匹配,不同型号参数差异较大。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值