资讯动态

基于STC89C52的红外遥控温度报警器:原理图、源码与PCB全解析

发布时间:2026/9/16 6:13:23 来源:尧图企业网站定制
简介这套红外遥控报警器电子设计资料包内含电路原理图、PCB版图、单片机C语言源程序、Hex固件及配套说明文档面向电子竞赛备赛、课程设计、毕业设计以及个人项目开发等场景帮助用户快速理解并搭建红外遥控报警系统。压缩包共收录21个文件整体大小约320KB主要包含Sch原理图、PCB电路板图、C与A51源码、Keil工程文件、Word设计说明及工程备份文件既能直接查看电路连线与板级布局也能通过源码和烧录文件进行实物调试。资料还涉及红外控制温度报警的设计思路从遥控指令接收、温度检测到报警联动均有对应程序与硬件承载适合作为方案模板进行二次开发或功能裁剪。说明文档对系统架构、模块功能和调试要点进行了梳理即使缺少实训条件也能通过原理图与源码对照理解整体工作流程。该资源已有372人学习资料体量精巧但结构完整对需要快速上手的电子类学生和开发者而言具备较高的参考价值。1. 红外遥控报警器的板级拆解这套资料到底给你什么拆开这个压缩包的人大概率不是找原理图而是想找一份能烧进51单片机里跑起来的完整工程。这个红外遥控报警器本质上是三件事遥控器把设定值送进来单片机读温度超限就响。压缩包里最值得研究的不是报警器本身而是三者如何共用一颗STC89C52、一根串口、一块板。对正在做课设或毕设的人照着DDB画板和Keil源码走一遍等于把红外解码、传感器采集、报警驱动都过了一遍对已经工作的人这套结构可以改造成远程温控、小家电定时器甚至当通用遥控开发板的起点。接下来我按照看原理、读代码、改PCB、调实物的顺序把每个环节的坑和参数都摊开说。2. 电路原理红外接收头、DS18B20与STC89C52的接口设计与选型2.1 从DDB工程里先认清核心器件打开压缩包后最先接触的是“比赛原理图”目录下的DDB文件这是Protel 99SE的工程库格式。我个人的习惯是打开DDB后先看树形目录把Sheet1.Sch和PCB1.PCB留下Backup和Previous Backup类文件基本可以无视。真正决定整机性能的是主控和传感器选型。从源文件名和STARTUP.A51能确认主控是51系列单片机最常见的是STC89C52RC或AT89S52。测温部分既然叫“红外控制温度”最标准的做法是接一个DS18B20数字温度传感器单总线协议一根线就能把温度送进单片机精度做到0.5℃以内对报警器足够了。下面这张表是这套板子最常见的物料清单。器件型号/参数在本板中的作用主控STC89C52RC或AT89S52接收红外信号、读取温度、驱动报警红外接收头HS0038B等一体化38kHz接收头解调遥控器载波输出串行电平温度传感器DS18B20单总线数字测温量程-55~125℃报警输出有源蜂鸣器LED超限时声光报警驱动管9012或9013三极管放大IO口电流驱动蜂鸣器DS18B20与热敏电阻方案的选择会影响后续代码量。用热敏电阻需要ADC采样和查表用DS18B20则只是读16位温度值代码量少很多。这版资料既然把源程序单独命名为hongwaikongwendu.c里面一定会包含DS18B20的单总线时序后面读代码时直接找skip ROM和convert T两个函数就可以定位。2.2 三条信号路径决定布局优先级拿到原理图不要按网络标号顺序读而是找信号流向。这块板子有三条路径值得优先看红外解码、温度采集、报警输出。先看红外解码路径一体化接收头的OUT引脚输出的是解调后的串行数据空闲高电平收到信号时拉低这个下降沿可以接到P3.2外部中断0。再看温度采集路径DS18B20的数据线DQ接普通IO口即可但要确认有没有接4.7kΩ上拉电阻。单总线协议要求总线空闲时必须为高电平靠上拉电阻实现如果原理图上画了这根电阻程序里就不用在IO口内部上拉。最后是报警输出蜂鸣器不能直接挂IO口中间要加一级三极管放大。这三条路径确定后PCB布局的优先级也就出来了红外接收头靠边放DS18B20接口靠板边走短线蜂鸣器远离晶振。这时候可以打开Keil工程把接口定义和原理图网络标号对一遍。// 红外与温度接口定义Keil C51基于STC89C52 #include REG52.H sbit IR_IN P3^2; // 红外接收头输出接外部中断0 sbit DQ P3^7; // DS18B20数据线原理图网络标号必须一致 sbit BEEP P2^0; // 蜂鸣器控制脚经三极管驱动这里的IR_IN必须是P3.2因为NEC解码依赖外部中断0的下降沿DQ引脚可以任意选择但选P3.7这类带弱上拉的IO口会更稳。BEEP引脚选择时要避开P0口因为P0是开漏输出驱动三极管基极时还需要外接上拉多一个器件多一个坑。2.3 那些“加上就能用”的电阻电容参数怎么定DS18B20的上拉电阻短走线用4.7kΩ长线超过50cm可以换成2.2kΩ换取更陡的上升沿。红外接收头的VCC脚必须放一个100nF去耦电容位置尽量贴近电源引脚不然电机、继电器动作瞬间的电源毛刺会把解码数据打乱。蜂鸣器是感性负载三极管的集电极和蜂鸣器之间如果用的是无源蜂鸣器需要并联一个续流二极管有源蜂鸣器内部已经带振荡电路不需要续流但驱动管基极的限流电阻还是要保留典型值1kΩ到4.7kΩ。这里我一般直接用9012 PNP管IO口输出低电平时导通和LED指示灯共阳极接法一致逻辑更直观。提示如果是STC89C52RC冷启动电流会比较大电源入口的10μF电解电容不能省否则烧录时反复重启。3. NEC红外解码与温度阈值报警的程序实现3.1 NEC协议的时序参数与解码思路资料里的遥控器部分最核心的难点是NEC协议解码。NEC的一帧数据由9ms的高电平引导码开始接着是4.5ms低电平然后依次送入地址码、地址反码、命令码、命令反码最后以560μs的结束位收尾。每一位数据都是“560μs载波脉冲空闲时间”的组合逻辑0的空闲是560μs逻辑1的空闲是1690μs。因此解码时只需要测量两次下降沿之间的时间长度就能把数据位还原出来。信号段高电平时间低电平时间完整周期判断阈值引导码9ms4.5ms13.5ms时间差 13ms逻辑0560μs560μs1.12ms时间差 1.5ms逻辑1560μs1690μs2.25ms时间差 1.5ms重复码9ms2.25ms11.25ms后面无数据位这里的关键判断阈值不是固定的它取决于晶振频率和定时器分频系数。以11.0592MHz晶振为例标准51单片机机器周期是12个时钟周期定时器每加一需要1.085μs所以13ms对应的计数值可以近似取12000。代码里用十六位计数器测量能覆盖的最大时间约71ms足够容纳NEC的最大周期。3.2 解码代码中断服务函数加状态机解码实现我用的是“外部中断定时器清零重计”的状态机不用延时函数这样红外接收期间CPU还能去处理温度读取和显示刷新。外部中断0配置为下降沿触发每次触发时先读取TH0和TL0合成时间差然后把计数器清零重新开始计时。unsigned int ir_time; // 相邻两次下降沿的时间差 unsigned char ir_state; // 0等待引导码1接收数据位 unsigned char ir_bit_count; unsigned long ir_frame; // 存放32位原始帧 void timer0_isr(void) interrupt 1 { TH0 0; TL0 0; // 溢出后清零否则时间测量会漂移 } void int0_isr(void) interrupt 0 { unsigned char th, tl; unsigned int us_cnt; if (IR_IN 1) return; // 排除上升沿干扰 th TH0; tl TL0; // 先读TH0再读TL0避免高字节进位 us_cnt (th 8) | tl; TH0 0; TL0 0; ir_time us_cnt; if (ir_time 12000) { ir_state 1; ir_bit_count 0; ir_frame 0; // 收到引导码准备接收32位数据 } else if (ir_state) { ir_frame 1; if (ir_time 1500) { ir_frame | 0x80000000UL; // 大于1.6ms判定为逻辑1 } if (ir_bit_count 32) { ir_state 0; // 32位收完主循环里做校验 } } }这段代码有几个细节值得注意。第一读取定时器值时必须“先读TH0再读TL0”因为TH0是高8位如果先读TL0TH0刚好发生进位合成的时间差会多出256个计数导致红外键值偶发错乱。第二进入中断后先判断IR_IN的电平可以在硬件信号抖动时滤掉上升沿毛刺。第三ir_frame 1放在判断之前意味着最后一位命令反码的最低位会被移入最高位校验时取低8位即可。按这个写法逻辑1的判断阈值1500对应约1.6ms正好卡在逻辑0的1.12ms和逻辑1的2.25ms中间。如果换成12MHz晶振计数周期是1μs引导码阈值要调到13500数据位阈值调到1500附近。3.3 温度阈值设定与报警状态机解码得到32位帧后命令码是第16~23位同时要把命令码与命令反码做异或校验再把重复帧丢掉。键值映射不能写死我把常用遥控器的键码做成一张表按键按序对应0~9和加、减。温度报警阈值默认35℃红外接收到数字键时直接跳转到对应的10℃档位上下键做1℃微调。const unsigned char key_table[] { 0x45, 0x46, 0x47, 0x44, // 数字1~4 0x40, 0x43, 0x07, 0x15, // 数字5~8 0x09, 0x16, // 数字9、0 0x18, 0x52 // 加、减 }; int temp_set 35; // 默认报警温度 void handle_ir_command(void) { unsigned char cmd (ir_frame 8) 0xFF; unsigned char cmd_inv ir_frame 0xFF; unsigned char i; if (((cmd ^ cmd_inv) ! 0xFF) || (cmd 0xFF)) return; // 校验失败或重复码直接丢弃 for (i 0; i 12; i) { if (cmd key_table[i]) { if (i 10) temp_set (i 1) * 10; // 数字键设定档位 else if (i 10) temp_set (temp_set 100) ? temp_set 1 : temp_set; else temp_set (temp_set 0) ? temp_set - 1 : temp_set; break; } } }这一段代码里cmd ^ cmd_inv是为了验证命令码和反码一致正常情况下两者异或等于0xFF如果按键被干扰或帧长度不对这个校验会失败直接return避免误触发。数字键的档位设计适合比赛演示场景遥控器上按一次“5”报警值跳到50℃比反复按加减键更快需要精确到个位时再用加减键微调。温度采集在主循环中每500ms执行一次读取DS18B20得到16位温度值右移4位后得到整数部分。报警逻辑可以再加一次软件消抖连续两次采到超限才置位BEEP防止传感器偶发跳变导致蜂鸣器乱响。这样调试时遥控器调节阈值和蜂鸣器触发之间不会互相干扰因为两个功能分别跑在中断和主循环里。4. Protel DDB工程原理图导出、PCB布局与网络表检查4.1 在Protel 99SE里打开并导出原理图和PCB压缩包里的DDB文件是老版本Protel的工程容器双击直接打开有时会提示“文件格式无效”尤其是Win10以上的系统。我一般先在Protel 99SE里用File→Open找到DDB等它解析出Documents树之后找到Sheet1.Sch和PCB1.PCB右键Export到本地文件夹。导出后的Sch和PCB文件才能被新版本的Altium Designer或嘉立创EDA导入。如果手头只有DDB没有老软件也可以尝试用在线转换工具但转换后封装和网络表容易丢所以最稳妥的还是装一个Protel 99SE虚拟机一次导出后面改版都从这份干净的Sch开始。导出完成后删掉Backup和Previous Backup文件这些是自动保存的中间版本经常把人绕晕。真正的原理图是Sheet1.SchPCB是PCB1.PCB。源文件里的红外控制温度报警电路.ddb工程内部可能还有一份Bkp那只是DDB自身的备份不必理会。4.2 布局定江山红外接收头、晶振和报警电路的摆放次序PCB布局时优先级最高的是晶体振荡器。Y1和两个20pF负载电容必须紧贴STC89C52的XTAL1/XTAL2引脚晶振下方不要走任何信号线否则耦合噪声会导致串口乱码。其次是红外接收头它要放在板边和机壳开窗位置接收头顶部不能被元件遮挡。如果遥控距离不稳定多半是接收头的焊盘位置太靠里或者旁边走了一根高频信号线。报警电路里的蜂鸣器自带磁性线圈会改变附近磁通所以它和晶振、红外接收头的距离至少留5mm以上。电源入口的电解电容和去耦电容靠近电源座放置DS18B20的接线端子放在板子另一侧与红外接收头顶开这样传感器外接线不会从遥控接收头上方跨过。这四个位置定下来剩下的电阻电容按信号流就近摆放。布局优先级器件约束条件第一优先晶振负载电容紧贴MCU下方不走线第二优先红外接收头位于板边无遮挡第三优先蜂鸣器远离晶振和红外头第四优先DS18B20端子靠板边便于外接传感器4.3 用Python检查网络表别让PCB改坏连接关系PCB改版时最容易出的问题不是线宽而是漏连线。Protel在生成网络表时会把每个网络定义成文本块投板前用脚本粗查一遍电源网络能省掉一次打样成本。我习惯用Python写一个快速统计脚本只关注VCC和GND。# 快速核对电源网络是否完整Protel导出文本网络表 net_file Sheet1.NET expected {VCC: 8, GND: 12} # 按原理图统计的预期引用次数 with open(net_file, r, encodinggbk) as f: text f.read() for net, exp in expected.items(): actual text.count(net) # 网络名在文件中出现的次数 print(net, 实际出现:, actual, 预期约:, exp)这段脚本只做快速粗查因为网络名可能出现在注释或其他文本里actual值会比真正的引脚数大。更准确的做法是在Protel里打开Netlist Manager查看每个网络的连线数但那个界面不能批量导出。脚本的价值在于当expected和actual偏差超过3时马上能察觉到PCB和原理图不同步。之前我接过一块改版板就是GND网络少了两根飞线投板回来芯片和传感器所有引脚虚地整板不工作最后用这个脚本对比才发现是原理图导入时漏掉了两个接地端子。4.4 DRC与位号图检查投板前的最后一道关卡投板前必须跑一次Design Rule Check。Protel的DRC设置里安全间距Clearance最小可以设到8mil但老工艺厂建议10mil以上孔径不要小于0.3mm未布线网络必须为0。DRC一旦报“Un-Routed Net Constraint”不要直接在PCB上加飞线先回到原理图补网络标号再重新导入网络表。这能避免改了PCB但原理图不同步的问题。位号图问题更隐蔽。很多后期检查会忽略Silkscreen层投板回来后丝印叠成一团。我导出生产文件前会切换到Top Overlay层选中全部位号文本把字高改成40mil、字宽6mil再检查是否有超出板边的字符。如果PCB尺寸很小位号可以挪到元件附近空白区域不要压住焊盘和过孔。Altium Designer导出PDF时如果发现只有部分区域检查打印范围是否选择了All Sheets而不是Current Sheet多页图纸页码重复的问题则是在Document Options里重新编号。5. 烧录到实物用串口读码法校准红外按键5.1 先让硬件“说话”串口打印键值拿到程序先别急着设阈值我把解码结果通过串口打印出来确认每个按键对应的NEC命令码。做法是先用STC-ISP烧录一个测试固件晶振选11.0592MHz波特率9600。串口发送函数如下code unsigned char hex_tab[] 0123456789ABCDEF; void uart_init(void) { SCON 0x50; // 模式18位UART允许接收 TMOD 0x0F; TMOD | 0x20; // 定时器1做波特率发生器8位自动重装 TH1 0xFD; // 11.0592MHz下对应9600波特率 TL1 0xFD; TR1 1; } void uart_send_hex(unsigned char val) { SBUF hex_tab[val 4]; // 先发高4位 while (!TI); TI 0; SBUF hex_tab[val 0x0F]; // 再发低4位 while (!TI); TI 0; SBUF ; while (!TI); TI 0; }波特率参数0xFD是按11.0592MHz晶振算出来的如果换成12MHz晶振串口会乱码需要把TH1改成0xF3或0xF4具体用STC-ISP软件里的波特率计算器生成。发送逻辑中while (!TI)会阻塞等待发送完成标志位置位调试阶段这样没问题正式项目里如果主循环还要处理温度可以将TI置位作为中断标志但会额外占一个中断源小项目没必要。每次解码完成在中断里调用uart_send_hex(cmd)串口助手显示的就是该键对应的十六进制码。把遥控器上每个键按一遍记录下数字键和加减键的码值然后填回key_table。这里有一个常见的问题不同品牌的遥控器键码完全不一样甚至同一品牌不同型号也会不同所以用资料包里预设的key_table做实物调试时大概率对不上号。串口读码法能在一分钟内拿到真实键值表这是最省时间的校准流程。注意连接串口模块时一定要将CH340的TXD接单片机RXDP3.0RXD接单片机TXDP3.1并共地。接反了会收不到任何数据且长期接错可能烧芯片。5.2 重复码过滤与长按处理NEC协议在按键持续按住时会以110ms为周期发送重复码重复码帧格式是9ms引导码加2.25ms低电平后面不跟数据位。上一章的校验逻辑里加入cmd 0xFF丢弃后只有第一次按键会生效。如果希望长按连续加温可以保留重复码计数在每收到一个重复码时执行一次temp_set加1再配合延时这样长按也能快速调整阈值。实际使用中我建议把键值处理放在主循环重复码计数放在中断里两个变量之间加volatile修饰避免编译器优化导致主循环读到旧值。用胶带纸在遥控器上贴好“加”“减”“档位”标签测试时每按一次观察串口输出是否和预期档位一致。最后保留串口打印功能接上温度探头在设定值附近反复跨阈值测试观察串口输出值和蜂鸣器状态确认报警回差是否符合预期。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价