基于STC89C52的温度采集与监控系统设计与实现

一、项目概述

本项目基于 STC89C52 单片机,实现了一个温度采集与监控系统。上位机通过串口与单片机通信,可以实现以下功能:

  • 读取 DS18B20 采集的温度
  • 控制 LED 灯和蜂鸣器
  • 设置温度上下限阈值
  • 切换手动/自动工作模式
  • 自动模式下超限告警

这个项目适合 51 单片机入门进阶,涉及单总线通信、串口协议、定时器中断、数码管动态扫描等知识点。

二、硬件清单

器件 型号/参数 数量
单片机 STC89C52RC 1
温度传感器 DS18B20 1
数码管 4位共阴 1
LED 普通发光二极管 2
蜂鸣器 无源蜂鸣器 1
晶振 11.0592MHz 1
USB转TTL CH340 1
电阻 4.7kΩ(DS18B20上拉) 1

三、硬件连接

1. DS18B20

DS18B20 单片机
GND GND
DQ P3.7(并接4.7kΩ上拉到VCC)
VCC VCC

注意:DQ 必须接 4.7kΩ 上拉电阻,否则读不到数据。

2. 数码管(普中51-MS开发板)

数码管 单片机
位选 P1.0 ~ P1.3
段选 P0

3. LED 与蜂鸣器

外设 引脚 有效电平
LED1 P2.0 低电平亮
蜂鸣器 P2.1 方波驱动(无源)

4. 串口

单片机 USB转TTL
P3.1 (TXD) RXD
P3.0 (RXD) TXD
GND GND

波特率 2400,8 数据位,1 停止位,无校验。

四、通信协议设计

1. 上位机 → 单片机(7字节定长帧)

text 复制代码
AA 01 CMD P1 P2 SUM BB
字节 含义
AA 帧头
01 地址
CMD 命令码
P1 参数1
P2 参数2
SUM 校验和(前5字节之和)
BB 帧尾

命令码定义:

CMD 功能 P1 P2
0x01 读温度 - -
0x02 控制外设 设备号 状态
0x03 设阈值 上限 下限
0x04 设为自动 - -
0x05 设为手动 - -

设备号:

设备号 设备
0x01 LED
0x02 蜂鸣器

状态:0x00=关,0x01=开

2. 单片机 → 上位机(7字节应答帧)

text 复制代码
AA 01 CMD DATA_H DATA_L SUM BB

五、软件架构

工程共 3 个文件:

text 复制代码
项目/
├── ds18b20.c    (主文件,含 main 函数 + DS18B20 驱动 + 串口)
├── timer.c      (数码管扫描 + 蜂鸣器方波 + 1s 计时)
└── timer.h      (头文件,声明共用变量和函数)

模块划分:

模块 功能
串口收发 收 7 字节命令,回 7 字节应答
DS18B20 驱动 复位、读写字节、读温度
数码管 定时器中断动态扫描
蜂鸣器 定时器中断输出方波
命令解析 根据命令码执行对应动作
自动控制 1s 定时读温度,超限告警

六、关键代码解析

1. 串口接收中断

c 复制代码
void UartHandler(void) interrupt 4
{
    if (RI)
    {
        RI = 0;
        if (RecvLen < sizeof(RecvBuff))
        {
            RecvBuff[RecvLen] = SBUF;
            RecvLen++;
            if (7 == RecvLen)
            {
                IsCommandLine = 1;
            }
        }
        else
        {
            RecvLen = 0;
        }
    }
}

要点:

  • 用 RI 判断接收中断
  • 收满 7 字节置标志,主循环处理
  • 加越界保护

2. DS18B20 读温度

c 复制代码
int ReadTemp(void)
{
    unsigned char LSBVal = 0;
    unsigned char MSBVal = 0;
    int Val = 0;

    DQ = 1;
    Delay480us();
    Delay480us();

    EA = 0;              // ★ 关中断,保护时序
    DQReset();
    ReadDQRespone();
    SendByte(0xCC);
    SendByte(0x44);
    EA = 1;

    Delay800ms();

    EA = 0;
    DQReset();
    ReadDQRespone();
    SendByte(0xCC);
    SendByte(0xBE);
    LSBVal = RecvByte();
    MSBVal = RecvByte();
    EA = 1;

    Val = (MSBVal << 8) | LSBVal;
    Val >>= 4;           // 取整数摄氏度
    return Val;
}

要点:

  • 读写时关中断 EA = 0,防止定时器打断时序
  • 读回后右移 4 位,得到整数°C
  • 加超时防止死循环

3. 定时器中断(数码管 + 蜂鸣器 + 1s计时)

c 复制代码
void Timer0Handler(void) interrupt 1
{
    static unsigned char scan = 0;
    static unsigned char buzzCnt = 0;
    
    TH0 = 0xFF;
    TL0 = 0x48;          // 200us

    if (BuzzerOn)
        BEEP = ~BEEP;    // 蜂鸣器方波
    else
        BEEP = 0;

    buzzCnt++;
    if (buzzCnt >= 4)    // 800us 扫一位
    {
        buzzCnt = 0;
        DisplayNum(scan);
        scan++;
        if (4 == scan) scan = 0;
    }

    Timer1msCnt++;
    if (Timer1msCnt >= 5000)   // 1s
    {
        Timer1msCnt = 0;
        AutoFlag = 1;
    }
}

要点:

  • 200us 中断一次
  • 蜂鸣器每次中断翻转 → 2.5kHz 方波
  • 每 4 次中断扫一位数码管
  • 5000 次中断 = 1s

4. 命令解析

c 复制代码
if (RecvBuff[2] == 0x01)        // 读温度
{
    CurTemp = ReadTemp();
    SetDisplayNum(CurTemp);
    SendResponse(0x01, CurTemp);
}
else if (RecvBuff[2] == 0x02)   // 控制外设
{
    if (RecvBuff[3] == 0x01) SetLed(RecvBuff[4]);
    else if (RecvBuff[3] == 0x02) SetBuzzer(RecvBuff[4]);
    SendResponse(0x02, 0x0000);
}
else if (RecvBuff[2] == 0x03)   // 设阈值
{
    TempHighLimit = RecvBuff[3];
    TempLowLimit  = RecvBuff[4];
    SendResponse(0x03, 0x0000);
}
else if (RecvBuff[2] == 0x04)   // 自动模式
{
    WorkMode = 1;
    SendResponse(0x04, 0x0000);
}
else if (RecvBuff[2] == 0x05)   // 手动模式
{
    WorkMode = 0;
    SetLed(0);
    SetBuzzer(0);
    SendResponse(0x05, 0x0000);
}

5. 自动控制逻辑

c 复制代码
if (WorkMode == 1 && AutoFlag)
{
    AutoFlag = 0;

    CurTemp = ReadTemp();
    SetDisplayNum(CurTemp);

    if (CurTemp > TempHighLimit)          // 超上限
    {
        SetLed(1);
        SetBuzzer(0);
    }
    else if (CurTemp < TempLowLimit)      // 低于下限
    {
        SetLed(1);
        SetBuzzer(1);
    }
    else                                   // 范围内
    {
        SetLed(0);
        SetBuzzer(0);
    }
}

七、完整工作流程

flowchart TD A[上电] --> B[UartInit + Timer0Init 数码管显示 0] B --> C{while 1} C --> D{收到命令?} C --> E{自动模式+1s到?} D -- 是 --> F[解析命令并执行] E -- 是 --> G[读温度并超限告警] F --> C G --> C
相关推荐
极客 - L U15 分钟前
卡尔曼滤波从零到精通
c语言·数据结构·单片机·嵌入式硬件·mcu
AMASENSYS艾马斯1 小时前
变频器滤波器选型与EMC合规建议
驱动开发·单片机·其他·硬件工程·精益工程
2501_922639585 小时前
率能半导体 SS6628E直流双向马达驱动芯片:20V/7A,覆盖电子锁、玩具、无线充电、机器人四大应用场景
单片机·嵌入式硬件·硬件工程
硅基造物主5 小时前
STM32 从 0 到 1 做智能家居(五):工程结构与代码骨架
stm32·单片机·嵌入式硬件·智能家居
深圳老胡5 小时前
STM32F103 硬件 SPI 与软件 IO 模拟 SPI 最高速度差异详解
笔记·stm32·单片机·代码规范·1024程序员节
smartpi_ai5 小时前
机芯智能离线语音模块实战问答:SU-03T、CI-03T、SU-63T 与 JX-A7T 高频问题排查
人工智能·单片机·嵌入式硬件·ci/cd·语音识别
2501_922639586 小时前
率能半导体 SS6635E直流双向马达驱动芯片:30V/4.5A,覆盖电子锁、玩具、无线充电、机器人四大应用场景
单片机·嵌入式硬件·硬件工程
wuyk5556 小时前
TinyML 初探:在 MCU 上部署异常检测模型,实现本地振动故障诊断
stm32·单片机·嵌入式硬件·重构
新晨单片机设计6 小时前
S031A-基于STM32单片机指纹考勤系统【Proteus仿真+Keil程序+原理图】
stm32·单片机·嵌入式硬件·proteus·指纹考勤系统
新时代牛马6 小时前
`arch_timer`、`IPI5`、`HRTIMER`、`ksoftirqd` 的关系
网络·单片机·tcp/ip