ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

51单片机高压锅安全联锁系统设计:DS18B20测温与ADC0832状态机控制

51单片机高压锅安全联锁系统设计:DS18B20测温与ADC0832状态机控制 简介基于51单片机的高压锅检测系统是一套完整的嵌入式课程设计/毕业设计资源面向单片机初学者与电子竞赛学生解决压力、温度、水位多参数检测与自动控制问题。系统支持压力和水位阈值通过按键调节超限时报警并联动排气阀泄压水位过低自动停止工作启动前还需检测锅盖开关是否闭合配合LED状态指示整个运行流程。压缩包共49个文件约639KB包含Proteus仿真工程、原理图、流程图、物料清单以及C语言源码ADC0832负责压力/水位采集DS18B20测温度LCD1602显示数据各模块代码与仿真对应清晰方便边调试边理解硬件连接和软件流程。已有258人学习下载。读者可完整获得从硬件选型、电路连接、程序逻辑到仿真验证的整套方案既适合作为课程设计、毕业设计参考也可作为单片机综合应用项目的实战练习。1. 高压锅安全联锁51 单片机如何把“能加热”和“该泄压”理顺这套高压锅检测系统真正难的不是把温度、压力、水位读出来而是把“锅盖有没有盖好”“能不能加热”“要不要泄压”这几个状态串成一个可靠的联锁逻辑。很多 Proteus 仿真的温度计和压力表都能单独跑通一旦接入电磁阀和启动按钮就露馅锅盖没盖好加热照样启动压力过限只报警不动作。项目资料里同时给了原理图、仿真图、流程图和源代码核心是 51 单片机采集 DS18B20 温度、ADC0832 采样压力和液位LCD1602 显示继电器驱动排气阀。适合正在做 51 课程设计或者想弄清楚多传感器联锁怎么用状态机实现的人。下面从硬件选型开讲。2. 硬件架构与原理图DS18B20 测温、ADC0832 双通道采集与 LCD1602 显示2.1 传感器选型依据为什么温度和模拟量分开处理先说选型。温度用 DS18B20因为它是数字单总线不需要再占 ADC 通道量程 -55℃ 到 125℃高压锅在标准大气压和额定压力下锅内温度一般在 100℃ 到 120℃ 附近留有余量。水位和压力则不同实际传感器输出多半是 0~5V 电压或者 4~20mA 电流必须过 ADC。项目里用了 ADC0832因为它双通道串行输出只占用 3 个 IO相比之下 ADC0809 的 8 路并行口在 51 上要占掉大半个 P1 口。Proteus 的元件库中 ADC0832 有完整模型仿真时用两个电位器就能同时模拟压力和水位信号。这里有一点值得注意8 位 ADC 的分辨率是 5V / 256 ≈ 19.5mV。如果一个压力变送器量程是 0~400kPa对应 0~5V一位大约对应 15.6kPa。课程设计只用来判断“过限”和“过低”这个分辨率完全够用。但如果你想要更细的压力显示就不能靠提高 ADC 位数解决而是要把压力信号先经过运放放大到合适的区间否则系统里最大的误差源是传感器自身和放大电路。2.2 引脚分配与原理图绘制要点拿到资料后先看原理图。压缩包里给出的是 Altium Designer 的 .SchDoc 和 PDF 预览仿真用 Proteus 的 .DSN 和 .pdsprj。对照源代码头文件可以整理出一张引脚分配表后续接实物或重画原理图都以这张表为准功能器件引脚51 单片机引脚说明LCD1602 数据D0~D7P0.0~P0.7外部 10k 排阻上拉LCD 寄存器选择RSP2.60 命令1 数据LCD 使能EP2.7下降沿锁存DS18B20DQP3.7单总线4.7k 上拉ADC0832 片选CSP1.4低有效ADC0832 时钟CLKP1.5上升沿写入/读出ADC0832 数据DI/DOP1.6写通道选择读转换结果锅盖开关OUTP3.2低电平表示已闭合排气阀继电器INP2.0低电平驱动开启蜂鸣器负极P2.1高电平报警状态 LED阳极P2.2/P2.3运行/故障指示画图时最容易漏的是 P0 口上拉和 DS18B20 的 4.7k 上拉。P0 口是开漏输出LCD1602 数据端如果不接上拉仿真里偶尔正常实物上会出现“第一行能显示、第二行是暗块”的问题。DS18B20 是单总线器件总线上所有设备都是开漏没有上拉电阻读回来全是低电平温度会固定显示 85℃ 或 0℃。源代码工程里一般会抽一个 main.h 统一管理引脚定义避免在几个 .c 文件里到处写同一个 sbit#ifndef __MAIN_H__ #define __MAIN_H__ #include reg52.h // LCD1602 控制脚 sbit RS P2^6; sbit EN P2^7; // DS18B20 单总线数据脚 sbit DQ P3^7; // ADC0832 串行接口 sbit CS P1^4; sbit CLK P1^5; sbit DIO P1^6; // 执行机构与指示灯 sbit RELAY P2^0; // 排气阀继电器0 表示接通打开 sbit BUZZ P2^1; // 蜂鸣器 sbit LED_RUN P2^2; // 运行指示 sbit LED_ERR P2^3; // 故障指示 // 锅盖开关输入低电平有效 sbit LID_SW P3^2; #endif这段代码的逻辑说明sbit 定义的是位寻址寄存器编译后直接对应单片机端口引脚。RELAY 0使继电器导通是把“故障时输出低电平”这种安全逻辑固定下来就算 51 单片机死机前把所有 IO 复位成低电平排气阀也会因为低电平而打开属于一种简易的失效保护。ADC0832 的 DIO 是双向信号线在写通道选择时是输出读取转换结果时切回输入普通 51 的准双向口可以直接在一个引脚上来回切不需要额外控制方向寄存器。2.3 元件清单与电源/驱动细节压缩包里的“元件清单.xls”应该是从原理图导出的 BOM。实际制版前至少要检查三样东西晶振电路、7805 稳压输入、继电器驱动。Proteus 仿真里继电器可以直接接单片机因为你不用担心电流实物不行P2.0 输出驱动能力有限必须用 NPN 三极管做开关继电器线圈两端再反向并联一只 1N4007 续流二极管否则继电器断电瞬间的反向电动势可能把单片机打复位。高压锅的控制对象是加热盘和排气阀。加热盘用继电器控制排气阀如果用常闭电磁阀断电时靠弹簧保持关闭单片机给继电器通电才打开泄压。这样一来如果系统异常断电电磁阀保持关闭反而不安全。所以我在实物里把排气阀改成“得电关闭、失电打开”的常开阀并把安全逻辑写成“一旦检测到过压立即失电”。这个细节在仿真里看不出来但做实物时很重要。电源部分建议用 7805 从 12V 降压给单片机供电继电器单独用 12V 驱动不要和单片机共用 5V。原因很简单继电器吸合瞬间电流在 50~70mA会让 7805 输出产生跌落DS18B20 在电压不稳时会出现温度跳变。原理图上把数字地和功率地用 0 欧电阻单点相连可以减少这个干扰路径。3. 软件状态机与阈值控制main.c 中的联锁逻辑3.1 状态定义与切换条件这套系统的软件核心不是传感器读取而是状态机。原因在需求里已经写明启动高压锅以前必须先闭合锅盖开关如果测量参数不正常禁止启动压力过限时停止并报警停止状态时排气阀打开。这些要求如果写成相互独立的 if 判断很容易出现“压力过限后排气阀打开但停止指令又被误触发放掉”这类矛盾。我建议把 main.c 里的主循环组织成五态模型状态进入条件执行动作迁出条件IDLE上电复位、故障复位排气阀开等待锅盖锅盖闭合且参数正常READY锅盖闭合、温度/压力/水位正常排气阀关LED 指示可启动启动键按下RUN启动键按下加热器工作排气阀关压力过限、水位过低、停止键ALARM压力过限或水位过低停止加热排气阀开蜂鸣器报警人工复位STOP正常停止或异常停止停止加热排气阀开压力回落到安全值这张表里最容易写错的是 ALARM 和 STOP 的关系水位过低引起的停止从安全角度看是“停止状态”排气阀应该打开不能因为报警标志位存在就把排气阀锁死。代码里我一般把“排气阀打开”这个动作独立出来不跟具体状态绑定只要满足state STOP || pressure press_limit || !lid_closed就打开。3.2 ADC0832 读取与阈值比较ADC0832 的时序是典型的串行控制CS 拉低后先发送起始位再发送通道选择位然后由单片机提供时钟把转换结果一位一位读出来。下面是通用的读取函数代码里加了关键注释#include intrins.h unsigned char adc0832_read(unsigned char ch) { unsigned char i, val 0; CS 0; CLK 0; _nop_(); DIO 1; // 起始位 CLK 1; _nop_(); CLK 0; DIO 1; // 前导位固定为 1 CLK 1; _nop_(); CLK 0; if (ch) // 通道选择0 为 CH01 为 CH1 DIO 1; // CH1 适合接水位 else DIO 0; // CH0 适合接压力 CLK 1; _nop_(); CLK 0; CLK 1; _nop_(); CLK 0; DIO 1; // 释放数据线由输入方向读取 for (i 0; i 8; i) { val 1; CLK 1; _nop_(); if (DIO) val | 0x01; CLK 0; _nop_(); } CS 1; return val; }这段代码的逻辑说明通道选择位发送后还需要两个时钟周期的延时等待内部采样保持所以我在通道位之后又拉高了两次 CLK。读取时先把 val 左移一位再判断 DIO 是否为高如果为高就把最低位置 1。这个顺序决定了返回的字节是 MSB 先出和 ADC0832 的数据手册一致。如果发现转换结果最大只有 128 左右大概率是通道选择位写反了两个通道交叉了。阈值比较我放在安全检测函数里不放在主循环中方便按键调试#define PRESS_LIMIT_DEFAULT 0xC0 // 对应约 3.75V #define LEVEL_LIMIT_DEFAULT 0x30 // 对应约 0.94V低于该值判定缺水 void safety_check(void) { unsigned char press, level; press adc0832_read(0); level adc0832_read(1); if (press press_limit) { RELAY 0; // 打开排气阀 BUZZ 1; // 报警 state ALARM; } else if (level level_limit) { RELAY 0; // 水位过低同样打开排气阀停止加热 BUZZ 1; state ALARM; } }为什么压力阈值用“大于”而水位阈值用“小于”因为压力传感器输出电压随压力升高而增大水位传感器输出电压随水位下降而减小。如果传感器选型不同这两个比较方向要反过来。拿到原理图后先看传感器信号调理电路确认运放是同相放大还是反相放大再写比较符号否则仿真时能把阈值调到边界上反复触发报警。3.3 按键调阈值与参数存储资料要求“压力和水位的阀值可调”最简单的实现是用两个按键一个切换调节项一个加减。下面这段按键扫描代码配合状态机使用短按切换长按进入调节后自动跳出void key_scan(void) { if (!SET_KEY) { // 设置键按下 delay_ms(20); // 去抖 if (!SET_KEY) { if (adjust_item 1) adjust_item; else adjust_item 0; } } if (!UP_KEY) { // 加/减键 delay_ms(20); if (adjust_item 0 press_limit 0xFF) press_limit; else if (adjust_item 1 level_limit 0x10) level_limit--; } }按键去抖的延时不能放在定时器中断里否则会阻塞状态机的扫描。我建议主循环每 5ms 调一次 key_scan使用状态机的 state 变量判断当前能不能进入设置运行状态不允许改阈值只有 IDLE 或 READY 状态才允许。至于掉电保存如果只是课程设计放 RAM 变量就够了要做实物可以用 STC 单片机的片内 EEPROM把调整后的阈值存在独立扇区每次上电读出来避免每次重新标定。4. Proteus 仿真、原理图与流程图的联合调试4.1 工程文件组织与加载顺序拿到压缩包后不要急着打开 .pdsprj。先把整个目录按 proteus、keil、sch 三个文件夹分开源代码工程和仿真工程放在同级目录这样 Keil 编译出的 main.hex 路径不会因为中文目录产生奇怪问题。Proteus 用 8.6 以上版本打开 .pdsprj如果只有 .DSN就用 ISIS 打开。打开后第一件事是双击单片机确认 Program File 指向 Keil 输出目录下的 main.hexCrystal Frequency 改成 12MHz。很多仿真不跑不是因为程序有问题而是单片机默认频率是 1MHzDS18B20 的时序计算全部错位。原理图 PDF 和流程图 BMP 在这个阶段是调试依据。我会把流程图打印出来在仿真开始之前先对着流程图走一遍从 IDLE 到 READY 需要哪些条件从 RUN 到 ALARM 是哪个传感器触发。如果代码里的状态表和流程图对不上先用纸改再改代码能省很多反复仿真时间。4.2 传感器模型与虚拟仪器的使用Proteus 里 DS18B20 是现成模型双击它可以设定一个模拟温度值拖动滑块看 LCD 变化。这个模型对时序要求比实物更严仿真速度太快时经常出现“第一次读到了温度第二次显示 85℃”。常见做法是在主循环里加一个 1ms 的软件延时或者把状态机扫描周期拉长到 10ms。注意这不会影响实物因为实物的 DS18B20 转换时间本身就大于 750ms仿真模型反而需要人为减速。ADC0832 的两个通道我分别接了一个电位器CH0 模拟压力CH1 模拟水位。压力过限的测试方法是把压力电位器滑到 4.5V水位过低则把水位电位器滑到 0.5V。为了确认 ADC 读到的值和 LCD 显示的压力一致可以写一个小函数把原始值直接显示在 LCD 第二行void display_raw_value(unsigned char ch) { unsigned char val adc0832_read(ch); lcd_write_command(0x80 0x40); // 第二行行首 lcd_write_data(0 ch); // 通道号 lcd_write_data(:); lcd_write_hex(val); // 十六进制原始值 }这段代码的逻辑说明lcd_write_command(0x80 0x40)把光标定位到 LCD1602 第二行第一列lcd_write_hex自己实现一个把字节拆成两个 ASCII 字符的函数。在仿真中拖动电位器如果显示的十六进制值从 0x00 到 0xFF 线性变化说明 ADC0832 接线正确如果只有几个跳变值说明 CLK 时序太快或者 DIO 引脚在读写切换时没有释放。4.3 常见仿真故障定位做一个常见问题表比反复试错高效现象可能原因排查方法LCD 无显示或花屏P0 口未加上拉或对比度脚电位不对加 10k 排阻调节 VL 脚电压温度固定 85℃DS18B20 上拉缺失或时序过快加 4.7k 上拉降低仿真速度按键没有反应端口方向或引脚接反对照原理图确认低有效还是高有效排气阀继电器不吸合P2.0 逻辑电平不对先点亮 LED 验证程序流程仿真运行极慢中断频繁或 LCD 刷新太快把 LCD 刷新间隔提高到 100ms压力过高不报警ADC0832 通道选择反了用 display_raw_value 检查两个通道4.4 与流程图对照检查泄压时序流程图里通常会把“压力过高”“停止状态”两个条件合并成一个菱形框然后连到“打开排气阀”。这代表排气阀的控制条件是或逻辑而不是某个状态的内部动作。代码里如果写成if (state ALARM) RELAY 0;会漏掉“用户手动停止”这种情况。我建议把排气阀控制放主循环末尾和状态机并列if (state STOP || press press_limit || !LID_SW) RELAY 0; // 打开排气阀 else RELAY 1; // 关闭排气阀“停止”这个状态建议做成瞬态。按停止键后最好让系统在 STOP 状态停留 2 秒让排气阀完成泄压再回到 IDLE而不是立即回到 IDLE 把排气阀关掉。这个 2 秒的保持逻辑在仿真里不一定看得出来但接实物时会发现如果泄压时间不够打开锅盖会冒热气存在烫伤风险。5. 阈值按键调参、排气阀时序验证与防误动作5.1 三段式按键短按切换、长按进入、加减实时生效前文提到的 key_scan 只做了短按切换。对实物我更推荐三段式设置键短按在“压力阈值、水位阈值、温度显示”之间切换设置键长按 1 秒进入调节调好后按一次设置键保存并退出。加减键在非设置状态不起作用避免煮饭过程中误碰导致阈值漂移。阈值默认值最好按传感器量程换算不要拍脑袋写。比如压力变送器输出 0~5V 对应 0~400kPaADC0832 满量程 5V。如果希望在 250kPa 报警那么电压阈值为 250 / 400 × 5V 3.125VAD 值 3.125 / 5 × 255 ≈ 160即 0xA0。水位阈值按锅体实际标定水位探针完全浸没时电压约 3.5V露出水面时降到 1.2V低于 1.2V 视为缺水AD 值大约 0x3D。仿真里用电位器模拟这些电压正好可以通过 LCD 上的阈值数值直接校验。5.2 排气阀安全时序先开阀再断加热最后说排气阀时序。很多人在代码里只写“报警时置位继电器”但这会导致加热和泄压同时切换继电器触点有电弧还可能让压力瞬间波动。我一般会在状态进 ALARM 后做一个小延时void enter_alarm(void) { RELAY 0; // 第一步立刻打开排气阀 delay_ms(50); // 等排气阀完全打开 HEATER 0; // 第二步再切断加热回路 BUZZ 1; state ALARM; }这样做的原因是电磁阀的动作时间一般在 20~50ms如果先断加热再开阀中间会有几十毫秒既没有加热也没有泄压压力继续维持反过来先开阀让高压蒸汽有出路再切加热锅体的压力上升趋势会立刻被制住。这个顺序也能降低继电器带载切断的电流因为排气阀打开后锅内压力开始释放加热腔内的温度不会再急剧升高。把相同的顺序用到“锅盖未闭合禁止启动”上启动按钮按下后如果锅盖开关为高系统不进入 RUN同时点亮故障 LED但排气阀保持打开。等到锅盖闭合并且压力、液位都正常才允许加热。这套逻辑在 Proteus 仿真中用按键替代锅盖开关时很容易验证不闭合开关直接按启动LCD 上显示状态不会切换到 RUNLED 保持红色闭合后再按启动才开始正常加热。所有阈值建议在 0.5~4.5V 范围内校准给 ADC 两端留 0.5V 的线性余量这样信号接近满量程时也不会出现截断。本文还有配套的精品资源点击获取
返回列表