
数字万年历这个东西说穿了就是把时间流逝这件事翻译成一串电信号再让计数器把它拆成年、月、日、时、分、秒。用555加74LS160这套纯数字逻辑方案来做最大的好处是每一个环节都看得见摸得着——没有单片机里那层黑箱时钟脉冲从哪来、进位怎么传、数码管为什么亮全都能在示波器和万用表上验证。这套电路特别适合刚学完数电、想找个综合项目练手的人也适合那些玩腻了单片机、想回头补一补底层时序逻辑的老手。下面我把整个搭建过程拆开讲包括选型理由、级联计算、实际布线时踩过的坑以及最后怎么把它调稳。1. 为什么这套方案值得动手做一遍1.1 纯逻辑方案和单片机方案的本质区别很多人第一反应是一个单片机加个时钟芯片不就搞定了确实DS1302加个51单片机代码写几十行就能跑。但那样做你学到的是怎么调用库函数而不是时间是怎么被电路记住的。74LS160是同步十进制计数器它的进位输出RCO在计数到9时给出高电平这个信号直接驱动下一级计数器的使能端就构成了最朴素的级联进位链。你要理解的是秒个位每到9就产生一次进位秒十位才加1秒十位到5之后再进位分个位才加1。这种逢十进一、逢六进一的规则在纯逻辑电路里是靠反馈线硬接出来的不是靠if语句判断的。555在这里的角色是心跳源。它接成多谐振荡器模式输出一个频率极其稳定的方波这个方波就是整个系统的时间基准。如果555输出的频率是32768Hz经过分频后得到1Hz那这个1Hz就是一秒。整个万年历的精度本质上取决于555的振荡频率稳不稳。这就引出一个关键认知数字电路里所有的时间概念最终都追溯到某个振荡源的频率。1.2 这套电路能帮你建立哪些底层直觉做完这套东西你会对几件事产生肌肉记忆。第一是同步与异步的区别74LS160的使能端控制的是要不要计数而时钟端控制的是什么时候计数这两个信号必须配合好否则会出现竞争冒险。第二是进位链的延迟累积当秒个位从9翻到0、秒十位从5翻到0、分个位同时加1时这条链路上每一级都有纳秒级的传输延迟级数多了之后最后一级的响应会明显滞后。第三是显示译码的共阴共阳问题74LS47是共阳数码管驱动器它的输出是低电平有效如果你手头只有共阴数码管直接接上去会发现该亮的段全灭、该灭的全亮这个坑几乎每个人都会踩一次。提示如果你之前只做过单片机项目建议先用这套纯逻辑方案把时间是怎么被电路记住的这件事彻底搞明白再回头用单片机做你会发现对时序的理解完全不一样。2. 555振荡电路整个系统的心跳怎么调准2.1 多谐振荡器的频率计算公式与元件选型555接成多谐振荡器时频率由两个电阻和一个电容决定。充电路径是VCC经RA到RB再到C放电路径是C经RB到放电端。充电时间t1等于0.693乘以(RARB)再乘以C放电时间t2等于0.693乘以RB再乘以C总周期T等于t1加t2频率f等于1除以T化简后f约等于1.44除以[(RA2RB)×C]。我要的是1Hz的基准频率但直接让555输出1Hz有个问题RA和RB的阻值会很大电容也要很大电解电容的漏电流和容值误差会让频率飘得厉害。更稳妥的做法是让555先输出一个较高的频率比如1024Hz或者32768Hz再用CD4060或者多级74LS160做分频最后得到1Hz。这样555部分的RC取值可以落在比较舒服的范围内频率稳定性也好得多。假设我选C等于0.1微法想要输出大约1kHz代入公式反推RA加2RB约等于1.44除以(1000乘以0.0000001)算出来是14400欧姆。取RA等于6.8千欧RB等于3.9千欧那么RA加2RB等于14.6千欧实际频率约等于986Hz接近1kHz。这个频率再用CD4060做10级分频1024分频后得到约0.96Hz虽然不精确等于1Hz但作为练手项目完全够用。如果要精确到秒可以在CD4060的晶振输入端接32768Hz的晶振那样分频出来就是标准的1Hz。2.2 实际布线时555部分的三个坑第一个坑是控制电压端悬空。555的第5脚是控制电压端内部接在比较器的参考电压上。如果你让它悬空外界的干扰会直接耦合进来导致输出频率抖动。正确做法是在第5脚对地接一个0.01微法的瓷片电容把高频干扰旁路掉。这个电容不加示波器上看输出波形会有明显的毛刺。第二个坑是电源退耦没做好。555在输出翻转的瞬间会从电源抽取一个较大的瞬态电流如果电源线上没有就近的退耦电容这个电流会在电源内阻上产生压降影响同一电源上的其他芯片。我的做法是在555的电源脚旁边直接焊一个0.1微法的瓷片电容再并一个10微法的电解电容两个电容离芯片越近越好。第三个坑是RA和RB的取值不要太大。有些教程为了得到低频把RA和RB取到兆欧级别结果555的输入偏置电流在这么大的电阻上产生明显的压降频率根本算不准。经验值是RA和RB都不要超过1兆欧最好控制在几百千欧以内。如果确实需要很低的频率宁可先产生高频再分频也不要用大电阻硬凑。3. 74LS160级联计数逢十进一和逢六进一怎么接3.1 74LS160的引脚功能与计数逻辑74LS160是同步十进制计数器它的关键引脚有这么几个CLK是时钟输入上升沿有效CLR是异步清零低电平有效LOAD是同步置数低电平有效ENP和ENT是两个使能端只有两个都为高电平时才计数RCO是进位输出在计数到9且ENT为高时输出高电平。A、B、C、D是置数输入端QA到QD是计数输出端。做秒计数时个位计数器从0计到9RCO在9的时候变高。这个RCO接到十位计数器的ENT端同时十位计数器的ENP接高电平。这样当个位从9翻到0的瞬间RCO产生一个下降沿十位计数器在下一个时钟上升沿加1。注意这里有个细节RCO是在计数为9时就已经为高了而不是在翻转到0时才变高。所以十位计数器的加1动作实际上是在个位从9变0的那个时钟沿完成的因为那个时钟沿同时作用于个位和十位个位的RCO在时钟沿之前已经是高电平十位的ENT有效于是十位也加1。3.2 秒十位和分个位的逢六进一反馈设计秒十位只需要计到5到6就要清零并产生进位。74LS160本身是十进制计数器它不会自动在6的时候清零。所以要用反馈线把秒十位的QB和QC对应二进制0010和0100即2和4接到一个与非门当计数为60110时与非门输出低电平这个低电平接到秒十位的CLR端同时经过一个反相器接到分个位的ENT端。这里有个时序问题要特别注意74LS160的CLR是异步清零也就是说只要CLR变低计数器立刻清零不需要等时钟沿。当秒十位计到6的瞬间与非门输出变低秒十位立刻被清零同时这个低电平经过反相后变成高电平让分个位的ENT有效。但分个位要等到下一个时钟上升沿才会加1。所以实际效果是秒十位从5跳到6的瞬间被立刻拉回0分个位在下一个秒脉冲到来时加1。这个立刻拉回的过程会产生一个极窄的毛刺如果示波器带宽够能在CLR脚上看到这个毛刺。注意异步清零带来的毛刺是这套电路的固有特性一般不影响功能但如果后面要接更复杂的逻辑建议改用同步置数方式把6这个状态用LOAD端在下一个时钟沿置入0这样就没有毛刺了。3.3 从秒到分的进位链完整走线完整的进位链是这样的秒个位的RCO接秒十位的ENT秒十位的RCO接分个位的ENT分个位的RCO接分十位的ENT分十位的RCO接时个位的ENT时个位的RCO接时十位的ENT。每一级的ENP都接高电平CLK全部并联接到1Hz的时钟源上。但这里有个问题秒十位在计到5之后下一个脉冲应该让分个位加1同时秒十位自己清零。如果直接用秒十位的RCO去驱动分个位的ENT那分个位会在秒十位从5变6的时候加1而不是在秒十位从5变0的时候加1。所以正确的做法是秒十位的RCO不直接接分个位的ENT而是用秒十位计到6时的反馈信号经过反相后去驱动分个位的ENT。这样分个位在秒十位被清零的那个时钟沿加1时序才对得上。同理分十位计到5之后下一个脉冲要让时个位加1。时个位和时十位构成24进制时个位计到9之后时十位加1时十位计到2且时个位计到4时整体清零。这个24进制的反馈逻辑稍微复杂一点需要把时十位的QB2和时个位的QC4同时为高的状态检测出来用与非门输出低电平去清零时个位和时十位。4. 74LS47译码驱动共阳数码管怎么接才不翻车4.1 74LS47的输出特性与限流电阻计算74LS47是BCD到七段译码驱动器它的输出是低电平有效专门用来驱动共阳数码管。共阳数码管的公共端接正电源各段引脚接74LS47的输出。当74LS47的某个输出为低电平时对应的段导通点亮。限流电阻的计算很关键。假设数码管的每段正向压降是1.8伏工作电流取10毫安电源是5伏。那么电阻上的压降是5减1.8等于3.2伏电阻值等于3.2除以0.01等于320欧姆。实际取330欧姆的标准值就行。这个电阻要串在74LS47的输出和数码管的段引脚之间每一段都要单独串一个。有些数码管内部已经集成了限流电阻那种可以直接接但大多数便宜的数码管都没有必须外接。这里有个容易忽略的点74LS47的输出低电平电压不是0伏而是大约0.4伏左右。所以实际加在电阻和数码管上的电压是5减0.4等于4.6伏再减去数码管的1.8伏电阻上的压降是2.8伏电流约等于2.8除以330等于8.5毫安。这个电流对大多数数码管来说亮度足够也不会超过74LS47单脚25毫安的吸收能力。4.2 灭零和测试引脚的用法74LS47有几个控制引脚LT是灯测试低电平有效拉低时所有段全亮用来快速检查数码管有没有坏段RBI是灭零输入低电平有效当输入为0且RBI为低时输出全灭用来消掉前导零BI/RBO是灭零输出兼消隐输入既可以作为灭零级联的输出也可以拉低来强制消隐。实际做万年历时我建议把LT通过一个按钮接到地需要检查数码管时按一下。RBI和BI/RBO可以不用直接接高电平让所有位都正常显示。如果你想让08时05分显示成8时5分那就需要用到灭零功能把高位的RBI接低BI/RBO级联到下一级的RBI。但万年历通常习惯显示完整的两位数所以灭零功能可以省略。4.3 数码管共阴共阳的快速判别方法拿到一个数码管怎么快速判断它是共阴还是共阳用万用表的二极管档红表笔接某个段引脚黑表笔依次碰其他引脚。如果某个引脚能让段发光说明黑表笔接的是公共端且这个数码管是共阴的因为红表笔给的是高电平公共端接低电平才能导通。反过来如果黑表笔接某个引脚、红表笔碰其他引脚时发光那公共端就是黑表笔接的那个且是共阳的。更简单的方法看型号。常见的0.56英寸数码管共阳的型号通常带AS后缀共阴的带BS后缀。但不同厂家命名规则不一样最保险的还是用万用表测一下。我手头有一批数码管丝印模糊看不清就是用这个方法一个个测出来的。5. 整机联调从能亮到走得准要过几道关5.1 分级调试法先让每一级单独跑起来不要一上来就把所有芯片插上去通电那样出了问题根本不知道是哪一级的毛病。我的做法是分级调试先只焊555和分频部分用示波器确认1Hz信号干净稳定再焊秒个位和秒十位用手动按钮产生时钟脉冲看数码管能不能从00走到59再回到00然后焊分、时部分同样用手动脉冲验证进位逻辑最后把各级的时钟线连到一起让555自动跑。手动脉冲可以用一个按钮加一个RC消抖电路产生。按钮一端接地另一端通过10千欧上拉到5伏同时并一个0.1微法的电容到地。按钮按下的瞬间电容通过按钮放电产生一个干净的下降沿再经过施密特触发器整形就能得到质量不错的单次脉冲。没有施密特触发器的话用74LS14也行。5.2 时钟线并联带来的负载问题当所有计数器的CLK脚并联接到同一个1Hz信号上时每个CLK脚都有一定的输入电容大概几个皮法。如果有十几片74LS160总负载电容可能达到几十皮法。555的输出驱动能力有限如果直接驱动这么多负载上升沿会变缓严重时会导致计数器误触发。解决办法是在555输出后面加一级缓冲用74LS04或者74LS244做驱动增强。74LS04是六反相器把两个反相器串联就能得到同相缓冲驱动能力比555强得多。或者用74LS244这种专门的驱动器一片就能驱动八路负载。我实际做的时候用了两级74LS04缓冲示波器上看时钟沿从原来的几百纳秒缩短到了几十纳秒计数器工作明显稳定了。5.3 电源和地线的布局经验数字电路对电源和地的布局很敏感。我的经验是电源线走粗一点至少1毫米宽地线尽量走成网格状不要走成树枝状每个芯片的电源脚旁边都要有0.1微法的退耦电容位置越近越好。如果用的是洞洞板退耦电容可以直接焊在芯片的电源脚和地脚之间引线剪到最短。还有一个容易被忽略的点74LS系列是TTL电平输入高电平的最低要求是2伏输入低电平的最高要求是0.8伏。如果电源电压偏低比如只有4.5伏那输入高电平的余量就很小容易受干扰。所以电源最好稳定在5伏用7805稳压后再加滤波电容。我试过用USB口直接供电电压只有4.7伏左右计数器偶尔会跳错换成7805稳压后就再没出过问题。6. 精度和长期稳定性555方案能做到什么程度6.1 影响走时精度的几个因素555多谐振荡器的频率稳定性受温度、电源电压和元件精度的影响。普通碳膜电阻的温度系数是几百ppm每摄氏度瓷片电容的温度系数也不小。夏天和冬天室温差20度频率可能漂移千分之几换算成走时误差就是每天几十秒。这个精度对于看个大概时间够用但对于需要精确计时的场景就不够了。如果想提高精度有几个方向一是把RA和RB换成金属膜电阻温度系数能降到50ppm每摄氏度以下二是把定时电容换成涤纶电容或者聚丙烯电容温度稳定性比瓷片好得多三是在555的电源端加一个稳压二极管让振荡器的供电电压更稳定。这些措施加起来能把日误差压到几秒以内。6.2 用晶振替代555的升级路径如果对精度要求更高最彻底的办法是用32768Hz的晶振加分频芯片替代555。CD4060自带振荡器接上晶振和两个小电容就能产生32768Hz的方波再经过14级分频得到2Hz最后用一级触发器二分频得到1Hz。晶振的频率精度通常在20ppm以内换算成日误差不到2秒比555方案好两个数量级。这个升级路径的好处是后面的计数和译码部分完全不用改只需要把时钟源换掉就行。我后来就把555部分换成了晶振方案走了一个星期和手机对时只差了不到10秒。对于纯逻辑电路来说这个精度已经相当可以了。6.3 掉电之后时间归零的问题这套电路没有后备电池掉电之后所有计数器清零重新上电要从00时00分00秒开始。这是纯逻辑方案的天然局限因为74LS160没有非易失存储功能。如果想让掉电后时间不丢需要加一套电池供电的保持电路或者用带掉电保持的计数器芯片。但那样就复杂了失去了这套方案简单直观的优势。我的做法是接受这个局限把它定位成一个学习用的万年历而不是实用型的时钟。每次上电后手动校准一下或者干脆把它当成一个通电后开始计时的计时器来用。如果你确实需要掉电保持那还是回到单片机加时钟芯片的方案更合适。7. 常见故障排查数码管不亮、计数乱跳、进位丢失7.1 数码管完全不亮的排查顺序先查电源。用万用表量74LS47的16脚和8脚之间是不是5伏量数码管的公共端是不是接到了正电源。如果电源正常再查74LS47的LT脚是不是低电平如果是低电平所有段应该全亮不亮说明数码管或者限流电阻有问题。如果LT脚是高电平那就查输入端的BCD码是不是在0000到1001之间如果输入是1010到111174LS47会输出全灭这是正常行为。还有一个隐蔽的坑74LS47的BI/RBO脚如果悬空有些批次的芯片会把它当成低电平导致输出全灭。正确做法是把这个脚通过10千欧上拉到5伏或者直接接5伏。我遇到过一批74LS47BI/RBO悬空时数码管完全不亮查了半天才发现是这个原因。7.2 计数乱跳的几种典型原因计数乱跳最常见的原因是时钟信号不干净。用示波器看时钟线如果上升沿有振铃或者毛刺计数器就会在毛刺上误触发。解决办法是在时钟线靠近计数器的地方加一个几十皮法的小电容到地把高频毛刺滤掉。但电容不能太大否则上升沿会变缓反而影响计数。第二个原因是使能端悬空。74LS160的ENP和ENT如果悬空TTL输入会默认成高电平看起来好像没问题但实际上悬空的输入很容易受干扰。正确做法是把不用的使能端通过10千欧上拉到5伏或者直接接5伏。我习惯把所有不用的输入都明确接高或接低不留悬空。第三个原因是电源退耦不良。当多个计数器同时翻转时电源线上会产生较大的瞬态电流如果退耦电容不够电源电压会瞬间跌落导致计数器误动作。每个芯片旁边加0.1微法退耦电容是最低要求如果芯片比较多还要在电源入口处加一个100微法以上的电解电容。7.3 进位丢失的定位方法进位丢失通常发生在级联的边界上。比如秒个位能正常从0走到9但秒十位不跟着加1。这时候先查秒个位的RCO有没有在9的时候变高用万用表或者示波器量RCO脚。如果RCO正常再查秒十位的ENT脚有没有收到高电平。如果ENT正常但十位还是不加那就查秒十位的CLK脚有没有接到时钟线上以及CLR脚是不是被误拉低了。还有一种情况是进位偶尔丢失不是完全不进位。这通常是时序余量不够导致的。比如秒个位的RCO在时钟沿到来之前还没来得及变高十位的ENT就没准备好导致这次进位被漏掉。解决办法是换速度更快的芯片或者降低时钟频率给信号更长的建立时间。74LS160的传输延迟典型值是十几纳秒如果时钟频率在1Hz这个延迟完全可以忽略所以低速应用下进位丢失基本都是接线问题不是芯片速度问题。8. 从洞洞板到PCB把电路固化下来的经验8.1 洞洞板布线的实用技巧洞洞板适合验证阶段但布线有讲究。我的习惯是先用不同颜色的线区分功能红色走电源正黑色走地黄色走时钟绿色走数据蓝色走控制。这样查线的时候一目了然。芯片的电源脚和地脚先用粗一点的线连好再走信号线。信号线尽量走直线不要绕来绕去减少交叉。退耦电容直接焊在芯片的电源脚和地脚之间引线剪到最短。如果洞洞板的孔距是2.54毫米0.1微法的瓷片电容刚好能跨接在芯片两侧的电源和地之间。焊的时候先把电容引脚弯成合适的形状插进去再从背面焊接这样电容紧贴板面引线电感最小。8.2 画PCB时要注意的几个细节如果要把电路做成PCB有几个地方要特别注意。第一是时钟线的走线尽量短尽量远离其他信号线最好在时钟线两侧各走一条地线做屏蔽。第二是电源线的宽度至少1毫米如果电流大还要更宽。第三是数码管的限流电阻可以放在74LS47旁边也可以放在数码管旁边但一旦选定就不要混着放否则布线会很乱。还有一个经验把555和分频部分单独放在一个区域计数和译码部分放在另一个区域两个区域之间用地线隔开。这样555的振荡信号不会串到计数部分去。我第一版PCB没注意这个555的振荡波形耦合到了时钟线上导致计数器偶尔多计一个数。第二版加了地线隔离之后问题就消失了。8.3 外壳和面板的简单处理电路调通之后总要给它找个壳子。我用的是透明的亚克力板自己裁切钻孔用铜柱把PCB固定在里面。数码管的开孔用开孔器打尺寸比数码管外框大0.5毫米左右这样数码管能卡进去又不会太松。面板上可以贴一张打印的标签纸标出时分秒的位置。如果想让外观好看一点可以用黑色的亚克力做面板数码管后面贴一张红色的滤光片这样不亮的段看起来是黑色的亮的段是红色的对比度很高。滤光片用红色的透明塑料片就行文具店买的那种红色文件夹剪一块就能用。9. 这套电路还能怎么玩几个扩展方向9.1 加一个手动校时按钮最简单的扩展是加校时功能。在秒脉冲和分个位的时钟线之间加一个切换开关拨到手动位置时用一个按钮产生的脉冲代替秒脉冲每按一次分个位加1。这样就能快速把时间调到当前时刻。按钮的消抖电路和前面说的一样用RC加施密特触发器。如果想分别校时和校分可以加两个按钮一个接分个位的时钟一个接时个位的时钟。但要注意直接往时钟线上注入脉冲可能会和原来的时钟信号冲突所以最好用二选一的数据选择器比如74LS157在自动和手动之间切换。9.2 加一个整点报时功能整点报时需要在分和秒都为00的时候触发一个信号。可以用一个多输入与非门把分个位、分十位、秒个位、秒十位的所有输出脚中只有在00分00秒时才同时为低电平的那些脚接进去。具体来说分个位和分十位的QA到QD都为0秒个位和秒十位的QA到QD也都为0把这些脚全部接到一个与非门上当所有输入都为低时与非门输出高电平触发一个蜂鸣器响一声。这个逻辑用一片74LS30八输入与非门就能实现但需要检测的脚有16个一片不够可以用两片74LS30级联。或者用二极管构成一个与门阵列把所有需要为低的脚通过二极管接到一个上拉电阻上当所有脚都为低时这个节点才为低再经过反相器触发蜂鸣器。9.3 加一个温度显示如果想再加点功能可以加一个温度传感器比如LM35它的输出电压和温度成正比每摄氏度对应10毫伏。把LM35的输出接到一个电压比较器或者ADC上再驱动数码管显示温度。但这样就需要额外的译码和显示电路复杂度会明显增加。一个折中的做法是用LM3914点状/条状显示驱动器它可以直接驱动10个LED根据输入电压的高低点亮不同数量的LED。把LM35的输出接到LM3914上就能用一排LED粗略显示温度范围。这个方案不需要单片机也不需要BCD译码纯模拟加逻辑就能实现和整套电路的风格比较搭。10. 我在这个项目里踩过的几个真实坑第一个坑是74LS160的CLR脚不能悬空。我一开始以为不用清零功能就可以不管它结果发现计数器上电后有时候从0开始有时候从9开始完全随机。后来查手册才知道74LS160的CLR是低电平有效悬空时TTL输入会漂移到不确定的电平导致随机清零。正确做法是把CLR通过10千欧上拉到5伏不用清零功能时保持高电平。第二个坑是数码管的限流电阻不能省。我一开始觉得74LS47输出低电平数码管接上去应该不会太亮就直接连了。结果通电后数码管确实亮了但亮度很高而且74LS47的芯片明显发烫。用万用表一量每段电流超过了30毫安远超74LS47的25毫安吸收能力。赶紧断电加上330欧姆的限流电阻芯片温度才降下来。这个教训是不管看起来多简单限流电阻该加就得加。第三个坑是时钟线的分布电容。我第一版把时钟线走得很长绕了半个板子才接到所有计数器。结果计数器偶尔会多计一个数用示波器看时钟线发现上升沿有明显的台阶这是分布电容和驱动能力不足共同造成的。后来在时钟线中间加了一级74LS04缓冲并且把线走短问题就解决了。第四个坑是电源退耦电容的位置。我一开始把退耦电容都放在电源入口处觉得反正都是接在电源和地之间放哪里都一样。结果计数器在翻转密集的时候还是会误动作。后来把每个芯片旁边的退耦电容移到芯片的电源脚正旁边引线剪到最短问题才彻底解决。这个经验是退耦电容要就近放置离芯片越近越好引线越短越好。第五个坑是手动按钮的抖动。我用一个按钮产生手动时钟脉冲没有加消抖电路结果按一次按钮计数器有时候加1有时候加2甚至加3。后来加了一个0.1微法的电容和10千欧的电阻构成RC消抖再经过74LS14施密特触发器整形按一次就只加1了。这个经验是机械按钮的抖动是纳秒到毫秒级别的数字电路对抖动非常敏感消抖电路不能省。这套555加74LS160的数字万年历从画图到调通大概花了我两个周末的时间。中间烧过一片74LS47换过一批数码管也重新焊过好几次线。但每次解决问题之后对数字电路的理解都会深一层。如果你也在做类似的东西我的建议是不要怕出错出错的地方往往就是理解最薄弱的地方。把每一个错误都当成一次学习的机会做完之后你会发现那些曾经觉得抽象的时序图、进位链、竞争冒险全都变成了看得见摸得着的东西。