基于 51 单片机的 NTC 温度采样程序

一、硬件设计

1、典型 NTC 采样电路

 VCC (5V)
   │
   │
  [R1] 10kΩ(精密电阻)
   │
   ├─── ADC_IN(P1.0)
   │
  [NTC] 10kΩ @25℃
   │
   │
  GND

推荐参数

参数
NTC 型号 NTC 10kΩ B3950
分压电阻 10kΩ ±1%
滤波电容 0.1µF
ADC 参考电压 5V
采样通道 P1.0(ADC0)

二、NTC 温度计算原理

1、电阻计算

Vadc = Vcc × Rntc / (R1 + Rntc)
Rntc = R1 × Vadc / (Vcc - Vadc)

2、温度公式(Steinhart-Hart)

1/T = 1/T0 + (1/B) × ln(Rntc/R0)
T(℃) = T(K) - 273.15

简化计算(B3950)

R25 = 10kΩ
B = 3950
T25 = 298.15K

三、完整程序(Keil C51)

1、头文件与宏定义

#include <reg52.h>
#include <intrins.h>
#include <math.h>

#define uchar unsigned char
#define uint  unsigned int

/* 硬件引脚 */
sbit LED = P2^0;        // 状态指示
sbit KEY = P3^2;        // 校准按键

/* NTC 参数 */
#define R1        10000.0f   // 分压电阻 10k
#define R25       10000.0f   // NTC 25℃阻值
#define B_VALUE   3950.0f    // B值
#define T25_K     298.15f    // 25℃开尔文

/* ADC 参数 */
#define ADC_MAX   255        // 8位ADC
#define VCC       5.0f       // 供电电压

2、延时函数

void DelayMs(uint ms)
{
    uint i, j;
    for(i = ms; i > 0; i--)
        for(j = 110; j > 0; j--);
}

3、ADC 读取(STC89C52 内部 ADC)

/* ADC 初始化 */
void ADC_Init(void)
{
    P1ASF = 0x01;       // P1.0 作为 ADC
    ADC_RES = 0;
    ADC_CONTR = 0x80;   // 开启 ADC 电源
    DelayMs(1);
}

/* 读取 ADC 值 */
uint ADC_Read(uchar ch)
{
    uint val;
    
    ADC_CONTR = 0x88 | ch;   // 启动 ADC
    _nop_(); _nop_(); _nop_(); _nop_();
    
    while(!(ADC_CONTR & 0x10));  // 等待转换完成
    ADC_CONTR &= ~0x10;          // 清除标志
    
    val = ADC_RES;               // 8位结果
    return val;
}

如果是 AT89C51(无 ADC)
→ 用 RC 充放电法外部 ADC(PCF8591)


4、NTC 电阻计算

/* 计算 NTC 电阻值 */
float NTC_GetResistance(uint adc_val)
{
    float voltage, resistance;
    
    voltage = (float)adc_val * VCC / ADC_MAX;
    resistance = R1 * voltage / (VCC - voltage);
    
    return resistance;
}

5、温度计算

/* 电阻转温度(℃) */
float NTC_GetTemperature(float resistance)
{
    float temp_k, temp_c;
    
    temp_k = 1.0f / (1.0f / T25_K + (1.0f / B_VALUE) * 
                     log(resistance / R25));
    temp_c = temp_k - 273.15f;
    
    return temp_c;
}

6、滑动平均滤波(抗干扰)

#define FILTER_LEN 10

float Temperature_Filter(float new_temp)
{
    static float buffer[FILTER_LEN] = {0};
    static uchar index = 0;
    float sum = 0;
    
    buffer[index] = new_temp;
    index = (index + 1) % FILTER_LEN;
    
    for(uchar i = 0; i < FILTER_LEN; i++)
        sum += buffer[i];
    
    return sum / FILTER_LEN;
}

7、数码管显示

uchar seg_tab[10] = {
    0x3f, 0x06, 0x5b, 0x4f, 0x66,
    0x6d, 0x7d, 0x07, 0x7f, 0x6f
};

void Seg_Display(float temp)
{
    int t = (int)(temp * 10);
    P0 = seg_tab[t / 100];      // 十位
    P2 = 0xFE; DelayMs(2);
    P0 = seg_tab[t / 10 % 10];  // 个位
    P2 = 0xFD; DelayMs(2);
    P0 = seg_tab[t % 10];       // 小数
    P2 = 0xFB; DelayMs(2);
}

8、主函数

void main(void)
{
    float resistance, temperature, temp_filtered;
    uint adc_val;
    
    ADC_Init();
    EA = 1;        // 开总中断
    
    while(1) {
        adc_val = ADC_Read(0);              // 读取 ADC
        resistance = NTC_GetResistance(adc_val);
        temperature = NTC_GetTemperature(resistance);
        temp_filtered = Temperature_Filter(temperature);
        
        Seg_Display(temp_filtered);        // 显示
        
        if(temp_filtered > 50.0f)          // 超温报警
            LED = 0;
        else
            LED = 1;
        
        DelayMs(500);                      // 500ms 采样
    }
}

四、无 ADC 的 51 单片机方案(RC 充放电)

1、RC 测电阻原理

P1.0 ── Rntc ──┬── P1.1
               │
              C 100nF
               │
              GND

2、简易 RC 采样代码

uint RC_GetValue(void)
{
    uint count = 0;
    
    P1 = 0x00;          // 放电
    DelayMs(10);
    
    P1_0 = 1;           // 开始充电
    while(!P1_1 && count < 50000) {
        count++;
    }
    
    return count;
}

五、精度优化技巧

提高精度的方法

方法 效果
分压电阻用 1% ±0.5℃
多次采样平均 抗干扰
分段查表法 避免浮点误差
软件校准 消除系统误差
温度补偿 抵消自热

分段查表法(不用浮点)

code uint16_t ntc_table[21] = {
    32200, 24300, 18500, 14200, 11000,  // -10~10℃
     8600,  6800,  5400,  4300,  3500,
     2900,  2400,  2000,  1700,  1450,
     1250,  1080,   950,   840,   740
};

float Table_GetTemp(uint16_t r)
{
    uchar i;
    for(i = 0; i < 20; i++) {
        if(r > ntc_table[i])
            return (float)(i - 10);
    }
    return 20.0f;
}

参考代码 基于51单片机的NTC温度采样程序 www.youwenfan.com/contentcnv/72815.html

六、典型误差来源

误差来源 影响 解决
分压电阻误差 ±1℃ 用 1% 电阻
ADC 非线性 ±0.5℃ 软件校准
自热效应 ±0.3℃ 降低采样电流
导线电阻 ±0.2℃ 三线制
环境温度 ±0.5℃ 温度补偿

七、完整工程结构

NTC_Temp_51/
├── Src/
│   ├── main.c
│   ├── ntc.c
│   ├── adc.c
│   └── display.c
├── Inc/
│   ├── ntc.h
│   ├── adc.h
│   └── display.h
├── Doc/
│   ├── NTC_10K_B3950.txt
│   └── Schematic.pdf
└── Keil/
    └── NTC_Temp.uvproj
posted @ 2026-05-27 16:19  荒川之主  阅读(22)  评论(0)    收藏  举报