
做数字电子技术课程设计十有八九绕不开74LS161这个4位二进制同步计数器。网上一搜八进制计数器大部分方案都是拿它从0000数到0111然后反馈清零或者反馈置数套路很成熟。可一旦题目里多了一句话——计数器初值为0100照着网上那些图抄作业就容易翻车清零法只能回到0000置数法置什么状态、从哪里检测反馈都得重新设计。我这次要实现的就是从0100开始、走完8个状态、再自动跳回0100的循环计数完整状态序列是0100→0101→0110→0111→1000→1001→1010→1011→0100。表面上看只是初始值不是0这么点差别实际上整个设计的核心从怎么清零变成了怎么利用同步置数功能把预置值装进去反馈逻辑、引脚连接、仿真初始状态、实物调试的坑全都和标准八进制计数器不一样。这篇文章就把这个从初值0100出发的8进制循环计数完整复盘一遍。1. 先说清楚0100到1011这8个状态才是这道题的模8循环1.1 74LS161到底能数多大的数要理解这个题目先得把74LS161的老底摸清楚。74LS161是4位二进制同步加法计数器内部由4个D触发器级联组成所有触发器在同一个时钟上升沿同步翻转所以它不存在行波计数器那样的累计延迟问题。4个输出端Q3、Q2、Q1、Q0可以表示0000到1111共16个状态也就是天然的模16计数器。但这只是一个原始模数。工程上要用它实现模8、模10、模12这些小于16的计数器就得靠外部反馈电路在计满指定状态后让它跳回起始状态。这里有个关键认知74LS161本身并不知道你要数到几它只知道每个时钟上升沿加1。所谓八进制计数器完全由外部反馈决定——你想让它从0数到7再回0或者从4数到11再回4只要反馈逻辑写得对它都能做到。1.2 为什么从初值0100开始就排除了反馈清零法最常见的八进制计数器方案是反馈清零法计数到0111也就是十进制7时用逻辑门检测到这个状态给74LS161的异步清零端MR一个低电平让输出立刻回到0000。它的优点很明确只用检测一个状态电路简单。但它有一个先天短板——清零是异步的输出不等待时钟直接被打回0000。这个短板在做从0100开始的计数器时直接成了硬伤清零端只能把计数器复位到0000你想让它回到0100MR这个引脚根本做不到。有人会想那我把0000到0111数完清零再想办法从0000跳0100行不行可以但那样实际计数序列是0100到0111只有4个状态再加一个0000状态不伦不类而且需要额外的置数配合复杂度和直接做模8置数差不多完全没必要。另外异步清零还有一个众所周知的毛病0111这个状态在清零信号生效前只维持极短时间各触发器复位延迟不一致输出端容易出现毛刺这在后面的章节会细说。所以当题目明确要求初值0100时反馈置数法就是唯一的合理选择。74LS161带有一个同步置数端LD也叫PE低电平有效它不像MR那样直接清零而是等到下一个时钟上升沿到来时把D3D2D1D0四个数据输入端的电平装进计数器。这个特性决定了它能实现从任意指定状态继续跑。1.3 状态转移表一个时钟周期对应一个输出设计任何计数器第一步都是把状态转移表列出来。这个设计的序列是时钟脉冲序号状态输出 Q3Q2Q1Q0十进制00100410101520110630111741000851001961010107101111801004回到初值一共8个不同状态所以它确实是模8。和标准0000→0111的八进制计数器相比这里的4位输出全都要参与反馈而且最大值不是0111而是1011。1011就是整个循环里“要触发置数”的那个状态当计数器走到1011时下一个时钟上升沿不是变成1100而是被强制置成0100。这是整个设计的核心逻辑。2. 74LS161关键引脚行为置数LD才是本设计的真正主角2.1 异步清零和同步置数一字之差波形天差地别做这个设计之前必须把74LS161两个最重要的控制端搞清楚MR1脚和LD9脚。很多教材把MR叫作异步清零把LD叫作同步置数这两个词平时念起来顺口真正用在电路里区别非常大。异步清零的意思是只要MR引脚的电平变为低电平不管时钟处于什么状态输出立刻变成0000。它是电平触发、立即生效的不需要等待时钟边沿。同步置数则是LD引脚为低电平后计数器不会立刻改变输出要等到下一个时钟上升沿到来D0到D3的数据输入才会被装入输出端。这么说可能还不好理解举个粗浅的例子。MR像教室里的下课铃一按所有人立刻站起来往外走不需要等什么节拍器LD像一套排队指令你喊了按这个顺序排队之后大家不会马上动非得等体育老师吹一声哨子才按新顺序站好。这个吹哨子就是时钟上升沿。这个区别带来一个非常实际的好处使用LD置数时输出跳变是受时钟控制的不会在反馈电路产生信号的瞬间就乱跳天然规避了异步清零产生的毛刺问题。这也是为什么初值0100的设计必须用同步置数而不是清零的深层原因。2.2 D0-D3的接法和初值0100的来源74LS161的数据输入引脚是D36脚、D25脚、D14脚、D03脚高位在前。题目要求初值为0100从高位到低位那就是D3 03脚注意D0在3脚D1在4脚D2在5脚D3在6脚。接法如下数据引脚目标值接线方式D36脚0接GNDD25脚1接VCC5VD14脚0接GNDD03脚0接GND也就是说在整个电路里只有D2这一个引脚接高电平其他三个都接地。很多人栽在这里把0100当成低位在前的顺序接到D3D2D1D0上变成0010十进制2结果计数的起点完全错乱。接线之前先在芯片手册上确认引脚顺序然后按高位到低位从左往右写0100再一一对应到引脚。还要注意这些数据输入引脚的电平是持续有效的只要LD出现低电平下一个时钟沿就会把D3D2D1D00100装进去。不需要额外锁存也不需要单片机配合纯硬件就能完成。2.3 EP/ET、CP、CO的正确处理方式74LS161除了清零和置数还有两个计数使能端EP7脚和ET10脚。只有当EP1且ET1时计数器才允许在时钟上升沿加1任何一个为0时钟来了也不计数。在这个设计里我们要求它一直处于计数状态所以EP和ET直接接VCC。进位输出CO15脚在这个设计里不参与反馈。74LS161的进位输出逻辑是CO Q3·Q2·Q1·Q0·ET也就是只有计数到1111十进制15时CO才输出高电平。我们的状态序列最大只到1011整个循环里Q2始终是00100到1011中只有1011Q20所以CO永远不会为1。这一点特别容易搞混因为很多标准八进制计数器教程会教你把CO接到LD实现自动置数那是 模16计数到1111时置数 的特殊用法。我们这里是模8最大状态1011没有到1111CO用不上。**如果照着那个思路把CO接到LD端计数器会一直数到1111共12个状态才跳回0100那就变成模12了完全跑偏。**初学的时候最容易在这个地方翻车。至于时钟CP2脚接信号发生器、555定时器输出或者手动单脉冲按钮都行。需要注意CP是上升沿触发也就是说时钟信号从低电平跳变到高电平的那一瞬间计数器动作。3. 反馈路径推导检测1011、置入0100一个与非门就够了3.1 判别1011Q2为什么可以不用管现在到了整个设计最核心、也最需要动脑子的部分怎么让计数器在状态1011的下一个时钟沿跳回0100。接上一节LD端低电平激活。我们希望在1011状态下LD0在其他7个状态下LD1。所以需要设计一个组合逻辑电路输入是计数器的输出Q3Q2Q1Q0输出是LD端的电平。先直观地想1011这个状态Q31、Q20、Q11、Q01。最严谨的判别电路是检测Q31且Q20且Q11且Q01即四输入逻辑 F Q3·(非Q2)·Q1·Q0。这个可以用74LS20四输入与非门配合反相器实现也可以把非Q2的信号和Q3、Q1、Q0一起送进与非门。但在实际设计时很少有人这么干。仔细看整个循环序列0100、0101、0110、0111、1000、1001、1010、1011。在这8个状态里Q2只在1011这一个状态中为1吗不是0100到0111这几个状态Q2都是1等等这里要重新看清楚。0100 Q30, Q21, Q10, Q00 0101 Q30, Q21, Q10, Q01 0110 Q30, Q21, Q11, Q00 0111 Q30, Q21, Q11, Q01 1000 Q31, Q20, Q10, Q00 1001 Q31, Q20, Q10, Q01 1010 Q31, Q20, Q11, Q00 1011 Q31, Q20, Q11, Q01我上面自己列状态的时候逻辑有点糊了。好好核对0100代表二进制从高位到低位 Q3 Q2 Q1 Q0 0 1 0 0哦那Q21啊。这说明我用的高位顺序是对的01004确实Q30、Q21、Q10、Q00。之前我说Q20是错的。但1011十进制11Q31、Q20、Q11、Q01确实是11。那在序列0100-1011中Q2的值有1有0。所以检测1011时Q20这个条件不能随便忽略让我重新推一下。我们的检测目标是1011条件是 Q31, Q20, Q11, Q01。现在如果只用Q3、Q1、Q0三输入与F Q3·Q1·Q0。检查这个条件在哪些状态满足0111Q30 → 不满足1011满足1101Q31, Q21, Q10, Q01 → Q10 → 不满足1111满足Q31,Q11,Q01 → 满足 但序列里没有1101和1111。所以如果在我们的8状态循环中1111和1101永远不会出现就可以忽略Q2但要注意0100到1011循环中1101永远不会到1111也永远不会到。所以安全。等等还有一个问题1011状态之前是1010然后时钟沿变为1011此时反馈输出LD0但直到下一个时钟沿到来之前状态一直是1011。下一个时钟沿因为LD0置数0100。OK。在状态1011期间Q3Q1Q0111LD0。正确。其他状态比如1001Q31,Q10,Q01 → 不满足。1100不在序列中。所以只用Q3·Q1·Q0判断是够的Q2确实可以忽略因为我们整个循环里1111和1101这些潜在误判状态都不会出现。但这里要小心刚才验证序列时发现0100状态下Q21这没问题因为Q30所以F0。三输入与非只关心Q3、Q1、Q0。在标准序列中能实现1011时输出低电平、其余7个状态时输出高电平即可。为严谨我可以说明如果担心噪声或上电异常可以加Q2的反相信号做四输入检测保险但正常循环下三输入与非足够。所以反馈逻辑化简为LD NOT(Q3·Q1·Q0)。当Q3Q1Q01时LD0触发置数。等一下我再确认状态1011里Q1和Q01011从高位到低位 Q31,Q20,Q11,Q01没错。Q11,Q01。那Q1和Q0都为1的状态还有0111Q30。所以三输入条件下0111不误判。正确。我是很详细地推出来在0100~1011的8个状态循环中Q3Q1Q0同时为1的组合只出现在1011。这就是为什么可以在反馈逻辑里省掉Q2的原因。但去掉Q2是有前提的前提就是计数器只能在这8个状态里循环如果因为外部干扰或者上电随机状态进入1100以后的状态那三输入与非门可能会在1101?不对1101不满足Q11。1100? 不满足。1110? 不满足Q11、Q01? 1110中Q11,Q00 → 不满足。只有1111满足但1111不在正常循环里。所以风险很低。严谨版则把Q2非信号加进去只有1011这一个状态满足。3.2 门电路选型74LS10三输入与非门 vs 两级与非门逻辑表达式出来了LD NOT(Q3·Q1·Q0)这是一个三输入与非运算。实现它最直接的办法是用一片74LS10三输入与非门。74LS10内部有3个三输入与非门选其中一个用就行。接线方式74LS10的1脚A输入→ 74LS161的Q311脚74LS10的2脚B输入→ 74LS161的Q113脚74LS10的3脚C输入→ 74LS161的Q014脚74LS10的12脚Y输出→ 74LS161的LD端9脚为了便于面包板接线实际引脚号以具体芯片手册为准原理上就是把Q3、Q1、Q0送进与非门输出接LD。可能有人会说手上没有三输入与非门能不能用两输入与非门凑可以但要注意直接用两级与非门不能简单实现三输入与非的逻辑。如果第一个与非门做NOT(Q3·Q1)第二个与非门再和Q0做与非最后得到的是 (Q3·Q1)NOT(Q0)不是 NOT(Q3·Q1·Q0)。所以要么加一级反相器调整要么用一片74LS08与门加一片74LS04反相器要么老老实实用74LS10。我推荐直接用三输入与非门一个芯片搞定调试最简单。3.3 同步置数没有毛刺的波形机理为什么反复强调同步置数没有毛刺这要从异步清零的毛刺机理说起。反馈清零法检测0111时输出从0111向0000跳变是MR端电平一拉低就立即发生的这个跳变不等待时钟。而74LS161内部4个触发器的清零路径延迟并不完全一致有的触发器先复位、有的后复位Q0到Q3不是在同一瞬间变化。结果就是示波器上你会看到在0111附近出现一个极短的高频振荡尖峰严重时后面再接的级联电路会把这几个尖峰当成有效脉冲导致计数错乱。同步置数则不同当检测到1011时LD0确实出现了但输出并不会立刻从1011跳走它就像一个信号在门口等着直到下一个时钟上升沿来临时才把0100领进门。在这个时钟沿上所有触发器同时动作输出从1011直接变成0100中间没有亚稳态竞争也没有毛刺。这一点在实物上用示波器观察会非常明显——置数法波形干净利落。不过要从严格意义上说同步置数要求LD端的低电平信号在时钟上升沿之前就稳定就绪也就是满足触发器的建立时间要求。74LS161的建立时间典型值是20纳秒量级而我们用普通与非门搭的组合逻辑延迟也只有几十纳秒在实验用的低频时钟几百赫兹到几兆赫兹下完全没问题。这也是为什么这个反馈电路简单到一个与非门就能搞定却依然可靠。4. 从原理图到仿真Multisim/Proteus验证完整循环4.1 完整接线总表把前面所有内容汇总成一张接线总表照着这个在仿真软件或者面包板上连线即可。74LS161引脚功能接法1MR异步清零低有效接VCC保持无效2CP时钟输入接信号发生器或单脉冲3D0数据输入位0接GND4D1数据输入位1接GND5D2数据输入位2接VCC6D3数据输入位3接GND7EP计数使能接VCC8GND地接GND9LD同步置数低有效接74LS10输出Y10ET计数使能接VCC11Q3输出位3送74LS10 A输入可接LED12Q2输出位2可接LED13Q1输出位1送74LS10 B输入可接LED14Q0输出位0送74LS10 C输入可接LED15CO进位输出悬空16VCC电源接5V对地接0.1uF去耦电容注意数据输入端的接法为了让置数值为0100D2接高、D0/D1/D3接地。这句话再强调一遍因为实际接反的人太多了。D0、D1、D3统统接GNDD2接VCC就这么简单。74LS10的电源同样接5V和GND别漏了给一片芯片供电。所有芯片的VCC和GND之间就近放一个0.1uF瓷片电容这是TTL电路最基本也最容易被忽略的稳定性措施。4.2 仿真里怎么让初值从0100开始在Multisim或Proteus里放好芯片、连好线之后直接点运行大概率发现计数器不是从0100开始的。因为仿真器给芯片上电时状态是随机的可能是0000、0110乃至1111并不会自动停在0100等第一个脉冲。要让仿真从0100开始可以用一个手动的初始化操作。最简单的方式把74LS161的LD端9脚通过一个按钮开关临时拉到低电平同时确保D25V、D0D1D3GND按一下按钮再松开此时LD恢复高电平。然后给CP送一个上升沿计数器就会把D端的数据0100装进去注意操作次序先让LD为低再给CP上升沿才能完成一次置数。如果只拉低LD不送时钟数据并不会进去。在仿真软件里可以用一个单刀双掷开关模拟这个过程。实测中很多人在这里卡住因为给LD低电平之后没给时钟计数器纹丝不动于是怀疑接线错了。不是是同步置数必须等时钟沿。如果你希望一上电就自动从0100开始可以做一个上电自动置位电路用一个4.7uF电解电容和10kΩ电阻组成RC微分电路接在LD端上电瞬间产生一个几十毫秒的低电平脉冲正好覆盖第一个时钟上升沿。不过这个属于锦上添花做课程设计的话手动置位一次就够了。4.3 实测波形解读0100→0101→……→1011→0100仿真跑起来之后在示波器上看Q3、Q2、Q1、Q0四路波形。最容易验证的方法是把四个输出按顺序接到逻辑分析仪或者用示波器四通道观察。从波形上看Q0是频率最高的信号每个时钟沿翻转一次在本状态序列中不完全规律但整体周期是8个时钟Q1每两个状态翻转一次Q2在0100到0111期间为高到1000变低持续4个状态后又变高Q3则从1000状态开始拉高一直保持到1011然后在置数回0100时拉低。最关键的验证点是计数器到达1011之后必须跳过1100、1101、1110、1111这4个状态直接回到0100。在仿真波形里Q3、Q1、Q0三个输出同时为高的那一拍就是LD触发的时刻下一拍三个高电平同时消失Q2从低变高整体输出变成0100。整个循环周期正好是8个时钟周期不多不少。5. 实物搭建避坑清单时钟抖动、电平兼容和上电初值5.1 按键给时钟不加消抖会一次跳好几个数仿真跑通了上实物的时候第一个大坑往往出在时钟上。很多初学者直接拿一个按键接在CP端按一下想让计数器走一个数结果发现计数器像发疯了一样一口气跑了五六个状态。这是因为机械按键按下和松开的瞬间金属触点会发生多次弹跳持续时间几毫秒到十几毫秒每一次弹跳都形成一个上升沿74LS161就会把这些跳变全部当成有效时钟。解决方法是加消抖电路常见的有两种用RC积分电路消抖按键一端接5V另一端通过一个10kΩ电阻接地同时在按键输出端和地之间接一个10uF电容。利用电容的充放电把毛刺抹平得到干净的单脉冲。用施密特触发反相器消抖比如74LS14按键信号经过施密特整形之后再送给CP波形非常干净。如果你用的是信号发生器或者单片机输出的方波时钟那基本不用考虑消抖问题本身上升沿就很标准。5.2 TTL的74LS161和HC系列更换时的电平问题74LS161是TTL工艺工作电压5V。如果在某宝上买到的是74HC161或74HCT161要注意它们不是完全一样的器件。74HC161是CMOS工艺虽然引脚兼容、功能相同但输入高电平要求和输出驱动能力不一样。TTL电路的高电平阈值大约是2.0VCMOS的高电平阈值大约是3.5VVCC5V时。如果你前面的时钟信号来自TTL门电路输出的高电平在2.4V到2.7V之间驱动74HC161可能根本触发不了计数。反过来74HC161的CMOS输出驱动LED倒是比TTL强一些。实际项目里最好统一用同一种工艺的芯片别TTL、CMOS混着用。如果实在要混查一下数据手册的电平参数确认驱动能力足够。5.3 LED指示、示波器探头的负载效应在面包板上验证最常见的输出观测方法是接LED。每个输出端串一个330Ω到1kΩ的限流电阻。注意LED接法有两种一种是把LED阳极接VCC、阴极接芯片输出端输出低电平时LED点亮另一种是LED阳极接输出端、阴极经过电阻接地输出高电平时点亮。推荐用第一种低电平点亮的方式因为74LS161的灌电流能力典型8mA比拉电流能力0.4mA左右强得多低电平点亮更亮也更稳。如果你用示波器探头直接戳输出端会发现波形边缘变慢或者幅度轻微下降这是因为示波器探头本身有输入电容通常在15pF左右高频时会对信号形成负载。在实验用的几百赫兹到几兆赫兹时钟下影响不大但如果后面要把这个计数器接到其他高速电路上就要考虑缓冲级隔离。我一般会在Q端到下一级之间加一个74LS244或者74HC245做缓冲避免负载过重把计数波形搞坏。还有一个容易忽视的坑测量多个输出信号时要确保所有通道的探头地线夹都在同一个GND点。如果地线夹夹在不同的地会因为地环路引入噪声干扰观测结果。上电初值的问题在实物上也要重视。74LS161上电后的初始状态是随机的所以每次通电之后计数器可能从任意状态开始跑哪怕反馈逻辑正确也会出现第一圈状态不完整的情况。我的做法是在LD端并联一个按钮开关上电后先手动按一下把计数器置到0100再开始正常计数。如果是长时间自动运行的设备就用前面提到的RC自动置位电路保证上电瞬间自动完成初始化。做这个项目踩了一圈坑之后我的体会是74LS161这种经典中规模计数器其实并不难难的是把清零和置数这两种反馈策略的应用场景分清楚。常规八进制计数器用清零法顺手但一旦题目变了初值就必须切换到置数法思路而且置数法本身更干净、更可靠没有毛刺问题反而是一种更高级的做法。如果以后自己做分频器、流水灯或者状态机碰到不从0开始数的需求这个检测最大状态→同步置入初值的套路可以直接复用连参数都不用怎么改唯一要变的只是检测哪个状态、D端接什么数据罢了。