ARTICLE DETAIL

资讯详情

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

基于74LS190与555定时器的交通灯设计:从选型到调试的完整实践

基于74LS190与555定时器的交通灯设计:从选型到调试的完整实践 1. 为什么我选择74LS190而不是单片机来做这个交通灯1.1 一个新手最容易犯的选型错误刚接触数字电路那会儿我跟大多数人的想法一样做个交通灯而已拿块51单片机几十行代码就搞定了何必用一堆74系列芯片搭得满面包板都是线这个想法本身没错单片机方案确实简单、灵活、可扩展。但问题在于如果你正在学数字电路与逻辑设计这门课或者想真正搞懂计数器、定时器、状态机是怎么在硬件层面跑起来的那用单片机就相当于把最核心的东西全部交给了一行delay()函数你什么都没学到。我当时的处境很典型数字电路实验课要求做一个交通灯控制器老师明确说可以用Multisim仿真也可以用实物搭。我一开始在Multisim里用555加74LS190搭了一版仿真跑通了但总觉得心里没底——因为仿真里很多时序问题被理想化了实际搭出来大概率会翻车。后来我决定用实物面包板复刻一遍结果果然踩了一堆坑。这篇文章就是把我从选型、设计、搭建到调试的完整过程记录下来重点讲那些仿真里看不出来、只有实际搭电路才会遇到的问题。74LS190是一块同步十进制可逆计数器它的核心能力就是计数和方向控制。交通灯的本质是什么就是两个方向的红绿黄灯按照固定的时间序列循环切换。这个“固定时间序列”用计数器来实现是最自然的——每个方向倒计时就是一个减法计数过程倒计时到零就切换状态。555定时器负责提供稳定的时钟脉冲让计数器按固定频率递减。整个系统的逻辑非常清晰555产生秒脉冲74LS190做倒计时74LS系列组合逻辑做状态译码LED灯做输出指示。1.2 74LS190和74LS160/161到底有什么区别很多人会问同样是74LS系列计数器为什么不用74LS160或74LS161这两个是十进制和四位二进制同步计数器功能上也能做倒计时。关键在于74LS190有一个非常实用的特性它是可逆计数器而且有独立的加/减计数控制端U/D引脚。这意味着你不需要额外的逻辑电路就能实现减法计数直接拉低U/D引脚就进入减计数模式。而74LS160/161只有加法计数要做减法得自己设计补码逻辑对于新手来说复杂度直接翻倍。另外74LS190还有一个最大/最小值输出端RCO/MAX/MIN当计数器减到0时这个引脚会输出一个低电平脉冲可以直接用来触发状态切换。这个特性在交通灯设计里简直是量身定做的——每个方向的倒计时归零时RCO信号直接驱动状态机切换到下一个灯态省去了大量译码逻辑。我实际对比过两种方案在面包板上的连线复杂度用74LS190做双向倒计时两个方向各一片加上状态译码和时钟电路总共用了4片74系列芯片如果用74LS160做减法光补码转换和借位逻辑就要多出两片芯片面包板上的线直接翻倍故障排查难度指数级上升。1.3 555定时器在这个系统里到底扮演什么角色555定时器在交通灯系统里的作用非常单一但极其关键产生一个频率稳定的方波信号作为整个系统的时钟源。交通灯的核心是“时间”而时间的基准就是时钟脉冲的频率。如果时钟频率不稳定倒计时的秒数就会忽快忽慢整个系统就失去了意义。555工作在无稳态多谐振荡器模式下输出频率由外接电阻和电容决定。标准公式是f 1.44 / ((R1 2*R2) * C)我需要的频率是1Hz也就是每秒一个脉冲。选C10μF代入公式反推1 1.44 / ((R1 2*R2) * 0.00001) (R1 2*R2) 144000取R147kΩR247kΩ则R12*R2141kΩ实际频率约为1.02Hz非常接近1Hz。这个精度对于交通灯来说完全够用因为人眼对1%的时间误差几乎无感知。但这里有一个新手极易忽略的坑555的输出频率会随电源电压波动而漂移。我在面包板上用9V电池供电时电池从9V降到8V的过程中频率从1.02Hz漂到了1.15Hz倒计时明显变快。后来换成稳压电源才解决。所以如果你要做实物一定要用稳压电源给555供电或者至少在电源端加一个100μF的电解电容做滤波。2. 系统架构设计从需求到框图的完整推导过程2.1 交通灯的状态定义与时间分配在动手画电路图之前必须先把交通灯的工作逻辑定义清楚。我采用的是最常见的十字路口双向控制模型状态编号方向A东西方向B南北持续时间S0绿灯红灯30秒S1黄灯红灯5秒S2红灯绿灯30秒S3红灯黄灯5秒整个循环周期是70秒。这个时间分配可以根据实际路口流量调整但在数字电路实现中调整时间意味着改变计数器的模值所以最好在设计初期就确定好。这里有一个设计决策需要解释为什么黄灯时间要单独用一个状态而不是在绿灯倒计时的最后5秒直接变黄从逻辑上讲两者都可以实现。但单独设一个状态的好处是黄灯期间另一个方向仍然是红灯不会出现两个方向同时放行的危险情况。如果用“绿灯最后5秒变黄”的方案那么绿灯倒计时到5秒时就要触发黄灯同时另一个方向的红灯倒计时还在继续状态机的复杂度反而更高。2.2 计数器模值的计算与实现方式每个状态的持续时间对应计数器的模值。以1Hz时钟为例30秒就是计数30次5秒就是计数5次。74LS190是十进制计数器单片的计数范围是0到9。要计到30就需要两片级联组成一个00到99的计数器。级联的方式很简单低位片的RCO输出接到高位片的CTEN计数使能端。当低位片从0减到9时减计数模式下9是最大值RCO会输出一个脉冲高位片减1。这样两片合起来就是一个00到99的减法计数器。但这里有一个关键问题74LS190的RCO在减计数模式下的行为。根据数据手册减计数时当计数器减到0时RCO会输出一个低电平脉冲宽度等于一个时钟周期。这个脉冲正好可以用来触发状态切换。但如果你直接把RCO接到下一级的CTEN会发现高位片在低位片从0跳到9的时候也会减1导致计数错误。正确的做法是低位片的RCO经过一个反相器后接到高位片的CTEN或者使用74LS190的进位/借位输出端的正确极性。我实际测试发现74LS190的RCO在减计数到0时输出低电平而CTEN是低电平有效。所以如果直接连接低位片每次减到0高位片就会减1这看起来是对的。但问题在于低位片从0跳到9的那个时钟周期RCO也会输出脉冲导致高位片多减一次。解决方案是用低位片的RCO经过一个D触发器同步后再驱动高位片或者更简单的方法——用状态机的输出直接控制计数器的置数而不是依赖级联计数。我最终采用的是后者每个状态开始时用状态译码信号给两片74LS190并行置数低位片置入个位高位片置入十位。这样就不需要级联计数两片计数器独立工作只是共享同一个时钟。2.3 状态译码与灯控逻辑状态译码的任务是把计数器的当前值翻译成对应的灯控信号。具体来说当方向A的计数器减到0时需要触发状态从S0切换到S1当方向B的计数器减到0时触发S2切换到S3。我用了一片74LS138译码器来实现状态译码。74LS138是3-8线译码器输入是3位二进制码输出是8个低电平有效的信号。我把状态编号S0到S3编码为00到11用两个D触发器组成2位状态寄存器输出接到74LS138的A0和A1输入端。74LS138的Y0到Y3输出分别对应四个状态。灯控逻辑就更直接了每个状态的灯态是固定的用74LS138的输出信号直接驱动LED即可。但要注意LED的驱动电流。74LS系列芯片的输出电流能力有限一般只能提供几毫安的拉电流。我一开始直接把LED接在74LS138的输出端结果亮度非常暗。后来加了限流电阻和晶体管驱动LED才正常亮起来。具体的灯控逻辑表如下状态74LS138输出方向A绿灯方向A黄灯方向A红灯方向B绿灯方向B黄灯方向B红灯S0Y0低亮灭灭灭灭亮S1Y1低灭亮灭灭灭亮S2Y2低灭灭亮亮灭灭S3Y3低灭灭亮灭亮灭这个表看起来简单但实际连线时每个LED都需要一个独立的限流电阻而且要注意74LS138的输出是低电平有效所以LED的接法是阳极接VCC阴极通过限流电阻接74LS138输出端。这样当输出为低电平时LED导通发光。3. 面包板搭建实录从零到跑通的完整步骤3.1 元器件清单与选型注意事项在开始搭建之前先把所有需要的元器件列出来。这份清单是我实际用到的不是理论上的最小系统元器件型号/参数数量备注同步十进制可逆计数器74LS1902方向A和方向B各一片3-8线译码器74LS1381状态译码双D触发器74LS741状态寄存器定时器NE5551时钟源四2输入与非门74LS001逻辑组合六反相器74LS041信号反相红色LED5mm2方向A和B的红灯黄色LED5mm2方向A和B的黄灯绿色LED5mm2方向A和B的绿灯限流电阻330Ω6每个LED一个电解电容10μF1555定时电容电阻47kΩ2555定时电阻电阻10kΩ若干上拉/下拉面包板830孔1建议用两块拼在一起稳压电源5V/1A1必须稳压这里重点说几个选型上的坑第一74LS190一定要买正品。我在某平台上买过一批便宜的74LS190结果发现RCO输出极性不对减计数到0时RCO不动作。后来换了正规渠道的芯片才正常。74LS系列芯片的假货率很高尤其是190这种相对冷门的型号。第二555定时器的电容要选钽电容或电解电容不要用瓷片电容。瓷片电容的容量随温度变化很大会导致时钟频率漂移。我用10μF的电解电容频率稳定性明显好于瓷片电容。第三LED的限流电阻不要省。我一开始觉得74LS138输出电流小直接接LED应该没问题结果LED亮度不均而且长期工作后74LS138发热严重。加了330Ω限流电阻后LED亮度一致芯片温度也正常了。3.2 555时钟电路的搭建与频率校准555时钟电路是整个系统的心脏必须首先搭好并校准。我采用的是标准无稳态振荡电路引脚1接地引脚2接引脚6引脚3输出引脚4接VCC引脚5通过0.01μF电容接地引脚6接引脚2引脚7通过R2接VCC同时通过R1接引脚6引脚8接VCC具体连接VCC→R1(47kΩ)→引脚7→R2(47kΩ)→引脚6→C(10μF)→GND。引脚2和引脚6短接。引脚3是输出接后续计数器的时钟输入端。搭好之后用示波器或者频率计测量引脚3的输出频率。如果没有示波器可以用一个LED串联电阻接在输出端观察闪烁频率。正常应该是每秒闪一次。我实测的频率是1.02Hz误差在可接受范围内。如果频率偏差太大可以通过调整R2来校准。比如频率偏快就增大R2频率偏慢就减小R2。但要注意R2的变化会影响占空比。555无稳态电路的占空比公式是D (R1 R2) / (R1 2*R2)当R1R247kΩ时占空比约为66.7%。这个占空比对计数器来说完全没问题因为74LS190是上升沿触发只要时钟信号的上升沿干净利落就行。注意555的输出端一定要加一个0.1μF的瓷片电容到地滤除高频噪声。我在实际调试中发现不加这个电容时计数器偶尔会多计一次导致倒计时跳变。3.3 计数器级联与置数电路的连线细节两片74LS190的连线是整个系统中最复杂的部分。我采用的是并行置数方案而不是级联计数方案。具体连线如下方向A的计数器两片74LS190低位片的D0-D3接状态译码器的个位输出高位片的D0-D3接状态译码器的十位输出两片的LOAD端并联接状态切换脉冲两片的CTEN端接地始终使能两片的U/D端接VCC减计数模式两片的CLK端并联接555的输出低位片的RCO接状态切换逻辑方向B的计数器连线方式与方向A完全相同只是置数值不同。这里有一个非常关键的细节LOAD信号的时序。74LS190的LOAD是异步置数只要LOAD为低电平输出就会立即变为D0-D3的值。这意味着如果LOAD信号持续时间过长计数器会在置数状态停留无法正常计数。正确的做法是用状态切换脉冲的上升沿触发一个单稳态电路产生一个窄脉冲作为LOAD信号。我一开始直接把状态译码器的输出接到LOAD端结果计数器根本不计数一直停在置数值。后来用74LS00搭了一个简单的单稳态电路把LOAD脉冲宽度控制在100ns左右问题才解决。3.4 状态机与译码器的联调过程状态机部分我用了一片74LS74双D触发器。两个D触发器级联组成2位状态寄存器输出Q0和Q1接到74LS138的A0和A1输入端。D触发器的时钟端接状态切换脉冲D端接下一个状态的编码。下一个状态的编码逻辑是S0→S1→S2→S3→S0循环。用D触发器的特性方程可以推导出D0 Q0 * Q1 Q0 * Q1 (简化后) D1 Q0 * Q1 Q0 * Q1这个逻辑用74LS00就可以实现。我实际搭的时候用了一片74LS00和一片74LS04连线不算太复杂。联调时最容易出问题的地方是状态切换的时机。理想情况下当计数器减到0时RCO输出脉冲触发状态切换同时LOAD信号给计数器置入新状态的倒计时值。但实际电路中RCO脉冲的宽度只有一个时钟周期而LOAD信号需要更窄的脉冲。如果直接用RCO触发LOAD计数器会在置数状态停留一个时钟周期导致倒计时少一秒。我的解决方案是用RCO的下降沿触发一个RC微分电路产生一个窄脉冲作为LOAD信号。具体是用一个0.01μF电容和一个10kΩ电阻组成微分电路RCO信号经过微分后再经过74LS04整形得到干净的窄脉冲。4. 调试过程中踩过的五个坑与排查思路4.1 坑一计数器不计数LED一直停在初始状态这是我最先遇到的问题。上电后LED显示的是初始状态但555的输出明明在正常闪烁计数器就是不动。排查过程先用万用表测量74LS190的CLK引脚确认时钟信号是否到达。测量结果显示CLK引脚有正常的方波信号频率约1Hz。检查CTEN引脚发现电压为高电平。74LS190的CTEN是低电平有效高电平意味着计数使能关闭。追查CTEN的连线发现我误将CTEN接到了VCC。改成接地后计数器开始正常计数。这个坑的教训是74LS190的CTEN引脚必须接地才能计数。数据手册上写得很清楚但实际连线时很容易忽略。4.2 坑二倒计时跳变从30直接跳到27计数器开始工作后我发现倒计时不是逐秒递减而是偶尔会跳变。比如从30直接跳到27中间少了两个数。排查过程用示波器观察555的输出波形发现波形上有明显的毛刺。检查555的外围电路发现引脚5的0.01μF电容没有接。引脚5是控制电压端不接电容时容易受到噪声干扰。补上0.01μF电容后波形变得干净跳变问题消失。这个坑的教训是555的引脚5一定要接0.01μF电容到地这个电容的作用是滤除控制电压端的噪声对输出波形的稳定性至关重要。4.3 坑三状态切换时两个方向同时亮绿灯这是一个非常危险的逻辑错误。在状态从S0切换到S1的瞬间方向A的绿灯还没有完全熄灭方向B的绿灯就亮了导致两个方向同时放行。排查过程用逻辑分析仪抓取状态译码器的输出信号发现Y0和Y2在切换瞬间有重叠。分析原因74LS138的输出切换存在竞争冒险。当状态寄存器从00变为01时A0和A1的变化不是同时的导致译码器输出出现短暂的错误状态。解决方案在74LS138的输出端加一个RC滤波电路滤除切换瞬间的毛刺。同时在状态寄存器的输出端加一个锁存器确保状态编码同时变化。这个坑的教训是组合逻辑电路存在竞争冒险是常态尤其是在状态切换的瞬间。对于交通灯这种安全相关的系统必须加滤波或锁存来消除毛刺。4.4 坑四LED亮度不均红灯明显比绿灯暗这个问题困扰了我很久。同样的限流电阻同样的LED红灯就是比绿灯暗。排查过程测量LED两端的电压发现红灯的导通电压是1.8V绿灯是2.1V。计算电流红灯电流(5V-1.8V)/330Ω9.7mA绿灯电流(5V-2.1V)/330Ω8.8mA。电流差异不大不应该导致明显的亮度差异。进一步检查发现红灯的限流电阻实际是470Ω而不是330Ω。我拿错了电阻。换成330Ω后红灯亮度恢复正常。这个坑的教训是焊接或插接电阻前一定要用万用表确认阻值。色环电阻的读数容易出错尤其是红色和棕色容易混淆。4.5 坑五系统工作几分钟后死机这是最诡异的一个问题。系统刚上电时工作正常但运行几分钟后状态机就卡死在某个状态不再切换。排查过程测量电源电压发现从5V降到了4.3V。电源带载能力不足。计算总电流6个LED约60mA4片74LS芯片约40mA555约10mA总计约110mA。我的稳压电源标称1A不应该带不动。检查电源连线发现面包板的电源线用的是很细的跳线线阻较大。在大电流下线上压降明显。换成粗铜线后电源电压稳定在5V死机问题消失。这个坑的教训是面包板的电源线一定要用粗线尤其是当系统中有多个LED同时工作时。细跳线的电阻可能达到几欧姆在100mA电流下就会产生0.5V以上的压降。5. 从面包板到Multisim仿真与实物的差异对比5.1 仿真里跑通不代表实物能跑通我在Multisim里仿真的时候一切都很完美时钟频率精确1Hz计数器逐秒递减状态切换干净利落LED亮度一致。但实际搭出来之后问题一个接一个。这不是Multisim的问题而是仿真软件默认所有元器件都是理想模型忽略了实际电路中的寄生参数、噪声、电源波动等因素。具体来说以下几个差异是仿真里完全看不出来的差异点Multisim仿真实物电路时钟信号质量理想方波无毛刺有毛刺需要滤波电源电压恒定5V随负载波动芯片输出电流理想驱动有限驱动能力导线电阻零电阻有电阻大电流下压降明显竞争冒险无状态切换时有毛刺温度影响无芯片发热导致参数漂移5.2 仿真作为验证工具的正确用法虽然仿真和实物有差异但仿真仍然是非常有价值的工具。我的经验是用仿真验证逻辑用实物验证电气特性。具体来说在仿真阶段重点验证状态机的状态转换是否正确计数器的模值是否准确译码逻辑是否与灯控表一致整体时序是否满足设计要求在实物阶段重点解决电源滤波和去耦信号完整性驱动能力竞争冒险散热5.3 从仿真到实物的迁移检查清单如果你也在做类似的数字电路实验从仿真迁移到实物时建议按照以下清单逐项检查电源是否使用稳压电源是否加了足够的滤波电容电源线是否足够粗时钟555的外围电路是否完整引脚5是否接了0.01μF电容输出端是否加了滤波芯片所有芯片的VCC和GND是否都接了去耦电容是否加了使能端所有使能引脚是否都接到了正确的电平LED限流电阻是否合适LED极性是否正确连线是否有虚接跳线是否插紧电源线和地线是否分开走6. 这个项目还能怎么扩展6.1 加入倒计时数码管显示目前的设计只有LED灯没有倒计时显示。如果要加数码管可以用74LS190的输出直接驱动共阳数码管。但74LS190的输出电流不足以直接驱动数码管需要加74LS48译码驱动器或者晶体管驱动阵列。具体方案两片74LS190的输出接到74LS48的BCD输入端74LS48的输出接共阳数码管。74LS48内部有上拉电阻可以直接驱动共阳数码管。这样每个方向需要两片74LS48个位和十位总共四片。6.2 用拨码开关实现时间可调如果想让绿灯时间可调可以用拨码开关设置计数器的置数值。具体做法是用8位拨码开关4位接低位片的D0-D34位接高位片的D0-D3。这样通过拨码开关就可以设置0到99秒的倒计时时间。但要注意拨码开关的输出需要加上拉电阻否则悬空时逻辑电平不确定。我一般用10kΩ的排阻做上拉。6.3 加入夜间模式和黄闪功能夜间模式下交通灯通常变成黄灯闪烁。实现方法很简单用一个开关控制555的输出当开关切换到夜间模式时555的输出直接驱动黄灯同时断开状态机的时钟。这样黄灯就会以1Hz的频率闪烁。具体电路用一个74LS157数据选择器正常模式下选择状态译码器的输出夜间模式下选择555的时钟信号。选择端用一个拨动开关控制。6.4 从74LS系列迁移到FPGA的思路如果你已经用74LS系列搭通了交通灯想进一步学习FPGA这个项目是一个非常好的迁移案例。FPGA实现交通灯的核心是把状态机和计数器用硬件描述语言重新描述一遍。74LS190对应的是一个减法计数器模块74LS138对应的是一个3-8译码器模块74LS74对应的是一个状态寄存器模块。用Verilog实现时可以用一个always块描述状态机用另一个always块描述计数器。时钟分频可以用一个计数器实现把50MHz的系统时钟分频到1Hz。这样整个设计就从一个面包板电路变成了一个可综合的RTL模块可以下载到FPGA开发板上验证。我在实际迁移时发现FPGA方案的最大优势是修改逻辑不需要重新连线。比如想把黄灯时间从5秒改成3秒只需要改一个参数重新综合即可。而74LS系列方案需要重新计算置数值重新连线非常麻烦。6.5 用单片机方案做对比的体会后来我又用51单片机做了一版交通灯代码不到100行一个定时器中断就搞定了所有时序。从工程效率的角度看单片机方案完胜。但从学习的角度看74LS系列方案让我真正理解了计数器、状态机、译码器是怎么在硬件层面协同工作的。这种理解是写多少行代码都换不来的。我的建议是如果你是在学数字电路一定要用74LS系列搭一遍如果你是在做产品直接用单片机或PLC。两者不矛盾只是目的不同。最后分享一个我在调试时总结的小技巧用LED指示灯监测关键节点的信号。我在状态寄存器的Q0和Q1输出端各接了一个LED这样不用示波器就能直观地看到状态的变化。当状态机卡死时一眼就能看出是状态寄存器的问题还是计数器的问题。这个方法帮我省下了大量排查时间。
返回列表