资讯详情

资讯详情

单片机光电计数器设计全解析:从信号整形到外部中断计数

简介这是一份面向电子信息、自动化类专业学生及单片机初学者的课程设计参考文档完整介绍基于单片机的光电计数器设计原理与实现方法。文档涵盖传感与检测技术基础、数字式电子计数器分类、光电计数发展现状并重点讲解系统整体设计方案由光电传感电路、运算放大电路、电压比较电路、AT89S51单片机系统电路、显示计数电路、报警与键盘电路、电源电路等八部分组成。同时详细阐述了硅光电池2CR的结构、光电效应原理及关键参数为读者理解硬件选型和电路搭建提供依据。资源为单个doc格式文档压缩包大小318KB内容结构清晰、文字叙述详实适合作为课程设计、毕业设计或自学参考。目前已有235人学习下载可作为快速入门光电检测与单片机应用的实用资料。 翻旧硬盘的时候翻出了自己早年带学生做的一个课设题目——基于单片机的光电计数器设计越看越觉得值得单独写一篇文章。这个题在单片机课程设计、电子竞赛训练和本科毕设里都很常见核心就一句话让单片机通过光电传感器统计经过检测区的物体数量再把结果显示出来。但奇怪的是网上能搜到的参考资料要么只给一张原理图要么程序注释少得可怜照着做最常见的结局就是“数不准”没人经过乱跳、一个物体被数两次、跑快了漏计。这篇文章我会把光电计数器从检测原理、信号整形、单片机程序到实物调试的完整链路拆开讲重点解释每个设计选择背后的理由希望能帮正在做课设或毕设的朋友少走几个月弯路。1. 项目本质与整体架构光电计数器的每一步在做什么1.1 检测原理与典型应用光电计数器的工作原理并不复杂用红外发射管和接收管组成一个检测区物体经过时接收管收到的红外光强发生变化光电传感器把这个变化转换成电平跳变单片机检测到跳变边沿就计一次数。真正“数数”的是单片机传感器的任务只是把“光有没有变化”翻译成“电平有没有变化”。这个题目之所以是单片机项目里的经典款是因为它的应用场景非常明确流水线上产品装箱计数、包装计数出入口人流统计配合两个检测探头还可以判断进出方向电机转速测量在转盘上开孔或贴反光片每转一圈输出一个脉冲纸张、卡片、胶囊、小五金件的批量计数实验装置里的触发记录比如动物活动轨迹统计。无论哪个场景系统框架都一样光电传感器负责感知信号整形负责把传感器信号变成干净方波单片机负责在方波边沿上计数数码管或LCD负责把数字显示出来。想清楚这条链路后面每一步都不会走偏。1.2 硬件模块划分与选型思路模块职责课设/毕设常见选型光电检测感知物体通过检测区ST-188反射式传感器、E18-D80NK反射式光电开关、槽型对射传感器信号整形把缓慢变化、带噪声的传感器信号整理成标准方波LM393电压比较器加滞回电阻主控计数、显示、按键处理、报警STC89C52RC51内核显示实时显示计数结果4位共阳数码管或LCD1602电源提供干净的5VUSB供电配100uF电解电容加100nF陶瓷电容退耦主控选51系列不是因为51有多强而是这个项目对算力几乎没有要求。51单片机的外部中断响应足够快内部资源、教程、例程也最丰富对没有太多嵌入式经验的人来说用STC89C52做是最容易把问题定位清楚的。STC89C52还内置了看门狗、内部振荡器和ISP下载功能外围元件少用面包板或洞洞板都能搭起来。传感器这块要单独说一下想最快跑通并交差选E18-D80NK这类带开关量输出的光电开关最省事它内部已经把比较电路做进去了输出直接是集电极开路接上拉就能给单片机。但如果你想真正理解信号处理建议用ST-188或槽型对射传感器配LM393自己搭整形电路因为光电计数器这个项目最大的分值不在“数数”而在你把模拟信号处理干净的能力。2. 信号整形环节传感器输出为什么不能直接接单片机2.1 传感器输出的真实形态与噪声来源很多人第一次做这个题目时最不理解的一步就是传感器不是已经输出高电平/低电平了吗为什么还要加一个比较器实际上光电接收管输出的是一路随光强连续变化的模拟电压不是一脚踢到高/低电平的数字信号。物体进入检测区时输出电压是缓慢爬升或下降的过渡过程往往持续几毫秒而且叠加着各种噪声。单片机的输入引脚在内部是一个固定的电压门限信号慢慢从门限附近爬过去的时候任何一点微小的扰动——电源纹波、环境光波动、空间电磁干扰——都会让引脚电平在门限附近来回抖动于是单片机看到的就是一串连续的脉冲边沿本来一个物体通过计数器直接给你变成五六个。打个比方这就是声控灯为什么要有两个触发阈值的原因只设一个“多大声亮”的阈值夜里环境噪声一大灯就会不停闪设了“亮起来要高音量、灭下去要低音量”两个阈值中间留一段缓冲区灯才不会乱闪。电子上管这个叫滞回比较也叫施密特触发。2.2 LM393滞回比较器用“两个阈值”消灭抖动LM393是双路电压比较器价格几毛钱开集电极输出非常适合做光电信号的整形。我推荐的接法是接收管转换出来的信号接比较器的反相输入同相输入端接一个10k电位器分压出来的基准电压基准先调到2.5V左右输出端与同相输入端之间跨接一只正反馈电阻形成一个滞回窗口输出再接一只10k上拉电阻到5V然后才接到单片机的P3.2口。正反馈电阻的取值直接影响滞回窗口大小。基准分压网络的等效内阻约5k当反馈电阻取100k时窗口大约只有±0.12V把反馈电阻换到56k窗口能拉到±0.2V上下。经验值是先装100k如果现场还是有抖动就往小换56k或47k通常能解决如果发现该计的数没计上怀疑是窗口把真实信号也吞了就往大换回100k甚至220k。注意正反馈电阻越小滞回窗口越大这一点很容易记反。输出端还可以对地加一个0.1uF小电容把极高频率的振铃毛刺滤掉。但电容不能加太大否则输出边沿会被拉得很缓反而影响单片机判断边沿一般0.01uF到0.1uF就够。2.3 对射式和反射式在电路上的差异对射式传感器发射管和接收管面对面安装物体从中间穿过遮断光束。无物体时接收管受光输出一个状态物体挡住后光强突变输出翻转到另一个状态。反射式则是发射管和接收管装在同一侧物体靠近时把红外光反射回接收管产生信号。这两种方式有一个关键差别信号的变化方向是相反的。对射式是“挡住才有反应”反射式是“有反射才有反应”。所以接LM393时如果发现逻辑反了——比如该计数的时刻输出没有翻转反而空闲状态一直在翻转——最简单的方法是把比较器的两个输入对调或者改一下单片机中断的触发边沿。对射式中物体进入和离开会产生一高一低两个边沿我一般只在下降沿计数一个物体只对应一个脉冲不会重复。2.4 环境光与物体颜色对计数的实际影响环境光对光电传感器的干扰是躲不开的。阳光、白炽灯和节能灯的光谱里都含有不少红外成分会改变接收管的静态工作点让基准阈值失效。廉价的解决方案是给发射管和接收管做遮光处理用黑色热缩管或手工做一个遮光筒套在管子上让它只“看”到有效检测区安装位置尽量避开窗户和强光。物体颜色也是个容易忽略的坑。反射式传感器对白色、浅色物体很灵敏对黑色物体几乎无能为力因为深色表面会吸收红外光。如果你数的对象是黑色橡胶件、黑色PCB、深色包装盒不要犹豫直接换成对射式。这点在项目验收前最好确认清楚不然等到验收现场才发现物体材质不对会非常被动。3. 程序核心逻辑外部中断计数、软件去抖与动态扫描3.1 为什么计数必须交给外部中断有人会觉得主程序里写一个if(P3_2 0) count不也能计数吗表面看可以但主循环一旦去刷新数码管、扫描按键一次循环可能需要几毫秒物体快速通过时脉冲只有几毫秒宽轮询很容易漏掉。51单片机的外部中断INT0就是干这个的先把计数引脚接在P3.2上把INT0配置为下降沿触发一旦检测到边沿不管主循环在干什么处理器都会立刻跳进中断服务函数。配置INT0只需要三句IT0 1; // 外部中断0设为下降沿触发 EX0 1; // 使能外部中断0 EA 1; // 开启总中断ET0、TR0是定时器的控制位和外部中断是两套东西别弄混。STC89C52的下降沿触发要求引脚上的低电平至少保持一个机器周期12MHz晶振下大概是1微秒机械传送带上物体的遮挡时间通常是好几毫秒完全够用。3.2 可用的中断计数例程中断服务函数里要做两件事软件去抖和计数。我常用的写法是进中断后先延时几百微秒再确认一次引脚仍然为低电平才认为这是一个有效脉冲。这样能滤掉窄毛刺又不至于漏掉正常物体信号。#include STC89C5x.H unsigned long g_count 0; // 计数值 /* 外部中断0服务函数物体通过下降沿触发 */ void Int0_ISR(void) interrupt 0 { unsigned char i; for(i 0; i 100; i); // 大约0.5~1ms去抖具体长度和晶振、编译器有关 if(P3_2 0) // 再次确认引脚确实是低电平 { g_count; // 只计一次 } } void main(void) { IT0 1; EX0 1; EA 1; while(1) { DisplayScan(); // 数码管动态扫描 KeyScan(); // 按键扫描例如清零、预置 } }注意在INT0中断里做延时去抖意味着这段时间内同优先级或低优先级的中断都得等着。如果物体不只是缓慢通过而是很快地连续通过去抖延时就不宜太长否则可能出现漏计。判断标准是去抖延时必须小于物体相邻两次触发的最小间隔。比如物体间隔50ms去抖1ms完全没问题如果间隔只有几毫秒就要把延时缩短或者干脆靠硬件的滞回和RC滤波来完成去抖。3.3 数码管动态扫描与中断的时序协调4位共阳数码管动态扫描的原理是利用人眼视觉暂留轮流点亮每一位。整个扫描刷新周期一般控制在20~40ms以内也就是每位大约每隔5~10ms要刷新一次否则肉眼能看到明显闪烁。扫描函数不长void DisplayScan(void) { static unsigned char pos 0; static unsigned char code seg[] {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; P0 0xFF; // 先关段选防止拖影 P1 P1 0xF0; // 关闭所有位选具体端口按自己接线改 switch(pos) { case 0: P0 seg[g_count % 10]; break; case 1: P0 seg[(g_count / 10) % 10]; break; case 2: P0 seg[(g_count / 100) % 10];break; case 3: P0 seg[(g_count / 1000) % 10];break; } P1 (P1 0xF0) | (1 pos); // 点亮当前位 pos; if(pos 4) pos 0; }这段代码放在主循环里不断调用即可。其实你不需要用定时器专门定时刷新只要主循环转得够快肉眼就看不到闪烁。要注意的是因为INT0中断随时可能打断主循环如果物体连续快速通过数码管的扫描间隔会被零零散散地拉长所以中断服务函数里千万别放太长的延时。4. 实物调试的完整排查链路四种典型故障4.1 没人经过乱跳数的排查流程我第一次实调这个项目的时候也遇到过这问题通电没人碰数码管自己跳得飞快。这个现象的排查顺序很重要可以按下面链路走先断开传感器信号只给LM393一个固定电平看显示还跳不跳。如果不跳说明问题在传感器或前面如果还跳问题在比较器、电源或单片机。用万用表量比较器两个输入端的电压确认无物体遮挡时和有物体遮挡时信号电压各是多少。把基准电位器调到这两个值的正中间必要时重新校准滞回窗口。检查比较器输出端的空闲状态。如果无物体时输出正好卡在翻转临界点说明基准调得太靠近信号静止电平。再把传感器接回去检测电源电压有没有明显波动。很多时候所谓“没人经过也在跳”本质是5V电源上叠加的高频纹波让比较器在临界点附近反复翻转。这套流程的核心思路是逐级隔离从后往前先把单片机从信号链路上摘出去再把比较器摘出去最后单独看传感器。按这个顺序走半小时内基本能定位。4.2 一个物体被数成两个的三个常见原因这类问题是最让人抓狂的因为看起来程序没错、电路也“能亮”。实际排查时我会优先怀疑三个地方第一中断边沿配置问题。如果外部中断被配成了电平触发或者程序里对高低边沿都做了响应一个物体经过就可能被计两次。确认IT0 1只在下降沿计数。第二物体运动时产生了多个脉冲。比如反射式传感器测到物体边缘反射率突变信号在过程中掉了好几个来回。对策是加强对射或反射的光路设计让物体沿稳定轨道通过同时把滞回窗口调大、软件去抖延时适当加长。第三比较器输出振铃。物体快速通过时信号变化很快输出边沿会伴随过冲和振荡一次翻转变成一串窄脉冲。如果没有示波器最简单的方法是给比较器输出对地加0.1uF电容同时缩小正反馈电阻两个动作一起做大多数振铃都能压住。4.3 高速通过漏计检测区宽度与去抖时间的权衡漏计往往是高速场景下的问题。物体遮挡检测区的总时间大致等于“物体尺寸光束宽度”除以速度光束越窄遮挡时间越短单片机越容易抓不到。很多人以为把光束做得越细越精准其实细光束会让脉冲变窄反而增加漏计风险。如果实测确定是脉冲太窄可以从两个方向解决一是增大检测区在运动方向上的尺寸比如把对射槽的开口开大一点物体经过时遮挡时间会变长二是压缩软件去抖延时去抖目的是滤毛刺不是增加一个硬性时间门槛。我建议用示波器看一次真实脉冲宽度再去微调中断里的延时循环长度不要让去抖吃掉有效脉冲的绝大部分。还有一个容易被忽略的点如果物体在通过过程中发生抖动脉冲可能被切成了好几段。这时单纯缩短去抖延时没用正确做法是先保证物体运动轨道稳定再谈去抖参数。4.4 电机一启动就乱计电源与布线的硬仗把计数器放在传送带旁边实验电机一转数码管就开始乱跳十有八九是电源问题。电机、继电器这类感性负载启停时会在电源线上产生很大的尖峰地线上也会出现反弹电压单片机和传感器对电源毛刺极其敏感。这已经不是光电信号本身的问题了而是整个系统的电磁兼容问题。我的处理顺序是先给传感器和单片机的供电与电机供电做隔离最简单的是共用一个电源时在单片机这路串一个磁珠或二极管再并联100uF电解电容和100nF陶瓷电容然后重新整理布线信号线用双绞线或屏蔽线尽量远离电机线和继电器线最后如果INT0引脚还受到残余干扰在引脚对地加一个10nF左右的电容把极窄毛刺滤掉。实际做下来这两步就能让乱跳现象基本消失。4.5 没有示波器时的土办法不是每个人都有示波器。一个非常实用的替代方案是在比较器输出端临时接一个LED和限流电阻物体每通过一次LED应该只闪一次。如果LED闪烁次数和实际物体数量对不上问题一定出在比较器之前或比较器本身这时候用万用表直流档分别测无物体和有物体时比较器输出端的电压值。两个状态都能量出稳定电压说明整形电路正常量出来数值在中间漂移说明信号或电源有问题。这套土办法在学校实验室里帮过我很多次比盲改程序有效得多。5. 验收测试与扩展方向让课设变成“能用的设备”5.1 一组可以写进报告的系统测试很多人的课设报告只写“经测试系统运行正常”这是很单薄的表述。我建议按下面这张表做一组正式测试把过程和结果写进报告老师一眼就能看出你是真做过实物测试项操作方法合格标准静态精度单件物体逐次通过100次记录显示值误差为0连续计数100个物体以0.5~1s间隔连续通过做3组最大误差≤±1速度上限逐步加快通过速度直到出现首次漏计记录可承受的最大通过速率抗干扰在旁启动电钻、继电器等干扰源观察显示计数不乱跳举个实际例子用100张白纸卡片做静态测试显示值应该严格停在100连续测试做三组记录值分别可能是100、100、99那误差就算出来了。测完之后把测试数据整理成表格比什么描述都有说服力。5.2 低成本、高性价比的三个扩展方向如果时间允许给这个题目加一两个扩展小功能项目完成度会明显提高。第一个是掉电保存。STC89C52内部自带EEPROM把计数值在每次变化后写入重新上电时读回来实现“断电不丢数”。这个对生产现场计数其实很实用实现起来只需要了解一下STC的EEPROM读写库函数。第二个是双向识别。在检测区前后错开一点距离放两个光电传感器通过两个信号的先后顺序判断物体是进入还是离开。人流统计、机房进出记录这类场景就用得上。第三个是批量报警。加一个按键设定目标数当计数到达目标值时让蜂鸣器响2秒。这个功能对包装计件特别有用等于把一个计数器做成了小型批产辅助设备。蜂鸣器要用三极管驱动直接接IO口会带不动。5.3 带完这个题目后我最想提醒的一句话带这个题目带了几轮我最大的体会是这项目真正的难点从来不是51编程而是你愿不愿意耐心地把传感器信号处理干净。很多同学半夜还在调计数最后问题都出在比较器阈值、滞回电阻和电源退耦这三件事上程序本身反而很少出错。所以我一直建议拿到这个题目先别急着写代码用面包板把LM393电路搭出来确认比较器输出在物体通过时是干净的一次方波再打开Keil写中断。你在信号调理上多花一个上午后面能少熬三个通宵。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →