ARTICLE DETAIL

资讯详情

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

74HC138译码器实战:从原理到级联,轻松扩展IO控制

74HC138译码器实战:从原理到级联,轻松扩展IO控制 刚接了个项目要用一颗51单片机控制32路继电器输出板上还要做8×8按键矩阵。数了一下IO主控总共才36个引脚扣除晶振、下载、串口、指示灯真正能自由分配的不超过20个。直接拿IO口怼肯定不够用这种时候我就知道该请出老朋友74HC138了。74HC138是一颗3线-8线译码器也是数字电路里最经典的组合逻辑芯片之一。它解决的问题非常朴素用3个IO口去控制8个输出通道把二进制编码变成独热码式的选通信号。你在自学单片机、做毕业设计、或者搞工控板卡时都会遇到它甚至在PLC的输入模块、存储器的地址译码电路里也到处能看到它的身影。这篇东西我就把自己这些年用74HC138的经验一次性写透从原理讲到级联再讲到真实项目里的接线、排错希望能帮你少走弯路。1. 为什么需要3线-8线译码器一个IO资源不够用的现实问题1.1 用8个IO直接控制是最自然的想法但最奢侈假设你要控制8个LED或者8个继电器初学者第一反应是每个设备接一个IO口单片机直接输出高/低电平去驱动。这个方法在小系统里完全没问题8个设备就8个IO口简单粗暴。但一旦设备数量涨到16路、24路、32路呢你不可能指望主控芯片的引脚数量跟着一起涨。以我常用的STC15W4K32S4为例LQFP48封装总共48个引脚真正能用作普通IO的大概在40个左右扣掉串口下载、晶振、复位、ADC参考电压系统里还需要显示、通信、存储、按键输入留给继电器的IO可能就剩10几个。16路继电器都吃紧更别提32路。1.2 3个IO表达8种状态信息论角度的关键转变这里的关键思路是1个IO口只能表达0和1两种状态但3个IO口组合起来能表达2³8种状态。译码器做的事情就是把这8种二进制组合翻译成8条独立的输出线。你可能会问那是不是我直接在软件里用3个IO口输出000、001、010……然后自己在代码里判断该拉高哪一路逻辑上成立但开环控制8个独立的功率开关时每一路都需要一个锁存信号才能保证稳定输出。74HC138的意义就在于它把地址到选通的翻译过程用硬件直接完成输出端天然就是唯一的低电平/高电平信号不需要单片机每切换一次就去重新刷新所有IO。1.3 译码和编码的关系别搞反方向编码器比如74HC148是8线-3线把8路输入压缩成3路二进制输出译码器74HC138正好反过来3线输入变成8线输出。两者在系统中经常配合使用比如按键矩阵的扫描侧用译码器轮流选通行读回侧用编码器/并转串芯片收回状态。记住这个方向后面看电路图会顺很多。2. 引脚、真值表与使能逻辑彻底看清74HC138的内部世界2.1 DIP-16封装的引脚功能速查74HC138最常见的封装是DIP-16和SOP-16。我做面包板实验用DIP做产品板子用SOP。引脚排布逻辑很对称你对着数据手册看一遍就能记住。引脚号名称功能说明1A地址输入最低位A02B地址输入A13C地址输入A2最高位4G2A使能端低电平有效5G2B使能端低电平有效6G1使能端高电平有效7Y7输出端低电平有效8GND电源负极9Y6输出端10Y5输出端11Y4输出端12Y3输出端13Y2输出端14Y1输出端15Y0输出端16VCC电源正极2V-6V2.2 真值表逐行拆解输出低电平才是选中很多第一次用74HC138的人最容易在这里栽跟头它被选中的输出端输出的是低电平不是高电平。也就是说当地址是000时Y0管脚被拉低其余Y1到Y7全部保持高电平。如果你脑子里默认选中高电平接LED时会把LED正极接输出口、负极接地结果LED永远不亮。下面这张真值表只看使能有效G11G2A0G2B0时的情况。C (A2)B (A1)A (A0)被拉低的输出端000Y0001Y1010Y2011Y3100Y4101Y5110Y6111Y7你可以把地址A、B、C当成一个3位的二进制数从000数到111对应Y0到Y7依次被点亮。所谓译码就是把二进制数翻译成第几号输出有效的过程。2.3 使能端G1、G2A、G2B的组合逻辑不止一个开关74HC138有3个使能端这是它的精髓。逻辑关系是G1必须为高电平G2A必须为低电平G2B必须为低电平三个条件同时满足芯片才进入译码工作状态。只要任何一个条件不满足所有输出端全部输出高电平也就是什么都不选。很多教程只把使能端当成总开关一句话带过但实际上这3个使能端在系统中承担的角色可以非常灵活。举个例子G1可以用来接地址高位G2A可以用来接读/写控制信号G2B可以用来接片选信号。这样一颗74HC138就能同时做地址译码和读写控制避免了额外的逻辑门。2.4 一个重要澄清74HC138输出没有高阻态我见过不止一个人把74HC138和三态缓冲器比如74HC245搞混以为不使能时输出是高阻态可以并联到数据总线上。这是一个严重的误解。74HC138的输出级是CMOS推挽结构要么输出高电平要么输出低电平不存在高阻态。禁止状态下输出全部为高这是静态高电平不是悬空更不是可以把多个输出端直接并在一起的那种状态。想做数据总线上的三态译码选通应该考虑74HC245这类专门的三态芯片138通常只用来生成片选/选通信号而不是直接挂在总线上输出数据。3. 级联扩展用两片74HC138把输出翻倍成16路3.1 为什么要级联4线-16线的需求场景单个74HC138只能输出8路。但继电器阵列、LED点阵扫描、多片存储器片选经常一上就是16路甚至32路。这时候可以用两片74HC138级联把输入从3位地址扩成4位地址输出变成16路。成本仍然很低两片芯片不到一块钱却能省下整整5个IO口。3.2 级联接法高位地址A3如何分配我用的接法是这样两片138的A、B、C引脚1、2、3全部并联接到系统地址线的A0、A1、A2。第一片负责输出Y0-Y7的G1接高电平VCCG2A、G2B接地。第二片负责输出Y8-Y15的G1也接高电平VCCG2A、G2B接地。新引入的地址线A3一路接第一片的某个使能端另一路经反相器接第二片的同一个使能端。为了贴实际操作我给你一个更具体的方案。第一片的G1直接接VCCG2A接A3地址第4位G2B接地第二片的G1接VCCG2A接A3经过反相器后的信号G2B接地。当地址A30时第一片G2A0第一片使能第二片G2A经过反相后等于1第二片禁止。此时A2A1A0从000到111输出Y0到Y7依次有效。当地址A31时第一片G2A1第一片禁止第二片G2A经过反相后等于0第二片使能。此时A2A1A0从000到111输出Y8到Y15依次有效。3.3 级联的地址编码表完整16路输出对应的4位地址规律如下A3A2A1A0有效输出0000Y00001Y10010Y2...............0111Y71000Y81001Y91010Y10...............1111Y15软件上只需要把通道号做个简单的位运算port (channel 0x07)给A0-A2A3 (channel 3) 0x01。其余都不用改代码里的通道号跟物理输出就是一一对应关系。3.4 再进一步4片级联做32路输出如果你觉得16路还不够可以继续用这个思路做32路。两片一组每组的使能端再交给上一级译码器。因为74HC138的扇出能力足够驱动同系列的CMOS输入二级级联时不需要额外加缓冲。但要注意整体传播延迟会累加高频扫描场合不能忽略常规的继电器控制、数码管扫描完全无所谓。4. 真实项目中的接线与驱动技巧别让芯片栽在细节上4.1 电源和去耦为什么VCC旁边必须放一个100nF电容这个问题我在面包板上栽过一次。用杜邦线插了一个138做LED跑马灯LED乱闪、芯片莫名发热。排查到最后是面包板电源线上纹波太大138在切换瞬间供电跌落导致逻辑混乱。后来在VCC和GND之间就近加了一颗100nF陶瓷电容问题立刻消失。去耦电容的位置和容值都有讲究。100nF0.1uF是标配必须物理上贴着芯片的VCC和GND引脚放走线越短越好。如果是多颗74HC138在一个板子上每一颗的电源引脚旁边都要单独放一颗不要指望一颗电容照顾整板。另外74HC系列的工作电压范围是2V到6V我习惯直接给5V跟单片机的VCC共用一组电源。4.2 CMOS输入禁忌任何输入引脚都不允许悬空74HC138是CMOS器件输入阻抗非常高栅极悬空时电位不定可能锁定在中间态造成输出乱跳还会增加静态功耗。工程上最稳妥的接法是G1高有效使能直接接VCC或者接高电平控制信号。G2A、G2B低有效使能直接接GND或者接低电平控制信号。A、B、C地址输入如果暂时用不到也要接固定电平不能悬空。哪怕是暂时性的调试阶段也不要用手捏杜邦线一堆乱碰的方式给地址线输入。CMOS输入悬空造成的故障最隐蔽因为表面上看芯片没坏但行为完全不可预测。4.3 输出端驱动能力低电平灌电流和高电平拉电流不是一回事74HC138的输出能驱动多少负载数据手册上写得很清楚。我归纳成一句经验它能直接驱动LED但驱动继电器、蜂鸣器、功率MOS管的栅极就必须外加驱动电路。以74HC138在5V供电下的典型参数来看输出低电平时的灌电流IOL大约4mA到25mA具体取决于你允许的VOL电压抬升幅度输出高电平时的拉电流IOH对称略低。这个电流驱动一颗普通LED加上合适的限流电阻比如1kΩ电流约3-5mA完全够用但驱动一个标称线圈电流70mA的继电器绝对不行。简单说138的输出级适合做信号选通不适合做功率输出。如果你用138选通之后要去驱动大负载中间必须加三极管、达林顿管ULN2003或者MOS驱动器。4.4 电平匹配3.3V单片机和5V的74HC138要谨慎这是我做低功耗手持设备时踩过的坑。STM32的IO口是3.3V电平74HC138工作在5V时输入高电平阈值VIH大约是0.7×VCC3.5V。STM32输出的3.3V高电平距3.5V只差了0.2V噪声一大就可能触发不了表现就是地址值对但输出乱跳。解决方案有三个方向5V系统里选74HCT138它是TTL输入电平兼容的CMOS版本VIH阈值只有2V左右3.3V电平可以直接驱动。3.3V系统里给74HC138供电3.3V此时VIH约2.31V3.3V电平驱动很稳。或者用一颗电平转换芯片/电阻分压网络把3.3V抬到5V再进138。4.5 软件驱动示例C51和Arduino各给一段参考C51环境下假设P1.0-P1.2接A、B、C三根地址线// 设置地址端口 sbit ADDR_A P1^0; sbit ADDR_B P1^1; sbit ADDR_C P1^2; void select_channel(unsigned char ch) { // ch取值范围0-7对应Y0-Y7 ADDR_A ch 0x01; ADDR_B (ch 1) 0x01; ADDR_C (ch 2) 0x01; }Arduino环境更简单直接用数字引脚int addrPins[3] {3, 4, 5}; void selectOutput(int idx) { for (int i 0; i 3; i) { digitalWrite(addrPins[i], (idx i) 0x01); } }实际项目中比这个稍微复杂一点切换通道前先把上一路的安全互锁处理好比如继电器切换前先确保负载已经断开。但核心的译码逻辑就这么简单。5. 典型应用实战数码管扫描、按键矩阵与片选译码5.1 动态扫描数码管用138做位选省下5个IOLED数码管显示位一多直接拿IO控制位选是最浪费的做法。4个数码管就要4个IO8个就要8个IO。用了74HC138之后3个IO就能选出8个位剩下的IO去买断码驱动比如74HC595或者直接上IO扩展就行。典型接法是这样的段选线a-g、dp接在锁存器或者IO扩展的输出上位选线接在74HC138的Y0-Y7上。由于138输出低电平有效数码管如果是共阴的位选端要接到138输出和地之间加PNP三极管做电平转换或者是共阴管直接接138输出、另一端接VCC。共阳数码管搭配138的低有效输出其实很顺手Y端直接接三极管基极或通过限流电阻驱动。软件扫描逻辑就是不断切换地址每切换一次刷新一次段码uint8_t digits[8] {0,1,2,3,4,5,6,7}; uint8_t segCode[10] {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; void scanDisplay() { for (int i 0; i 8; i) { selectOutput(i); // 138切换位选 sendSeg(segCode[digits[i]]); // 发送段码 delay(1); // 停留1ms靠人眼余晖 } }8位数码管扫描周期做到8ms以内看起来就没有闪烁感。5.2 矩阵键盘扫描138当行驱动器IO省出一大截标准8×8矩阵键盘需要8根行线和8根列线共16个IO。如果用138做行扫描行线从8根降到3根总共只需3811个IO省出5个。扫描思路138每次只让一行输出有效低电平其余行输出高电平。列线全部配置成上拉输入读到低电平的那一列就是按键所在列。循环8次就能得到全部64个按键的状态。这套方案的优点不仅仅是省IO还因为138行驱动天然保证同一时刻只有一行被选通不会出现多行同时导通的鬼键问题。5.3 存储器/外设片选译码多片并行设备的地址空间分配单片机扩展多个并行外设SRAM、Flash、ADC、LCD控制器时每一片都需要一个片选信号CE/CS通常低有效。地址总线的高位经过138译码生成这些片选信号每个外设就占用了不同的地址区间。举例一个16位地址总线低8位用来访问片内寄存器/数据高8位的高3位接138的A、B、C138的Y0-Y7分别接8个外设的片选。这样每个外设就独占了一个连续的地址块软件访问时只需用不同的基地址硬件上不用任何额外逻辑门。这里有个现实的细节外设芯片的片选信号很多是低有效跟138输出天然匹配。你不需要在138输出后面再加反相器直接接就行。6. 排错实录那几个让我排查到深夜的疑难杂症6.1 故障现象LED全部乱闪芯片温度升高排查过程先看电源5V正常。再看地址输入用万用表量A、B、C都有高低电平变化。最后用示波器看G1、G2A、G2B发现G2A引脚波形是正常的低电平但G1引脚电平是乱的——它居然悬空了。因为我在面包板上跳线时少插了一根从VCC到G1的杜邦线G1栅极静电荷积累导致电平漂移。根因和解决CMOS使能端悬空是最经典的138故障源。把G1直接接VCC后一切恢复正常。这个排查顺序值得记住先看电源再看使能端最后看地址输入大多数138异常都能在两步之内定位。6.2 故障现象LED常亮不随地址变化排查过程我觉得肯定是我程序写错了反复检查select_channel函数没错。用万用表量138输出所有Y端都是低电平。这时候才想起去查引脚——原来我把芯片插反了1脚和16脚对调电源和地完全接反。根因和解决DIP封装上有个半圆缺口和1脚圆点标记插芯片前一定要对齐。这类问题不属于技术难度但发生的概率比你想象的高。基本的检查动作是量一下VCC和GND之间有没有5V电压没有就先查封装方向。6.3 故障现象级联后高地址位部分正常低地址位全部失效排查过程这是一个16路继电器板上的真实问题。现象是Y8-Y15正常控制Y0-Y7完全没反应。检查了第一片的电源和G1、G2A、G2B发现第一片的G2B被我接到了A3信号上而G2A接了地。A31时第一片G2B1禁止A30时第一片G2B0应该使能才对。可是我又犯了个错误第一片的G1接的不是VCC而是A3的反相信号导致A30时G1反而是0两个条件矛盾第一片永远被禁止。根因和解决级联时的使能逻辑必须逐片核对。推荐接法第一片G1固定接VCCG2A接A3G2B接地第二片G1固定接VCCG2A接A3的反相信号G2B接地。这样每片的使能逻辑都只有一条路径依赖A3绝不会自相矛盾。6.4 故障现象3.3V驱动的板子偶发误动作冷启动必现排查过程这台设备用的是3.3V主控138用5V供电。示波器看地址引脚波形发现高电平只有约3.0V远低于5V供电138要求的3.5V门限。上电瞬间主控引脚驱动能力还没完全建立138偶尔把3.0V当成低电平输出就乱了。根因和解决电平不匹配。项目换成了74HCT138之后同样的3.3V输出驱动高电平阈值只有约2V余量非常充裕再也没出现过冷启动误动作。如果你的板子上已经固定了74HC138替代方案是加一颗电平转换缓冲器或者干脆把138的VCC也降到3.3V。6.5 故障现象继电器吸合瞬间138输出波形受干扰排查过程继电器线圈是感性负载断开瞬间会产生反向电动势。138和继电器共用5V电源继电器动作时电源轨被拉出很大的毛刺示波器上能看到138输出端出现几伏的尖峰。根因和解决首先138不能直接驱动继电器线圈必须加续流二极管和驱动三极管/ULN2003把感性负载和逻辑芯片的电源隔离。其次如果继电器和138共用电源在138的VCC处加一个10Ω100uF的RC滤波或者用DC-DC模块给逻辑单独供电问题就能彻底解决。7. 一点经验沉淀用了这么多年74HC138最深刻的体会是这颗芯片真正考验人的地方不在于原理有多深而在于三个容易被忽略的细节——低有效输出、使能端组合逻辑、CMOS输入不能悬空。你把这三点刻在脑子里面包板上基本不会翻车原理图也能一次画对。做个项目总结时我常对新人说74HC138是你从会用单片机点灯走向会做完整系统的一道分水岭。它会让你开始思考IO资源的分配、地址空间的设计、硬件逻辑和软件逻辑怎么配合。市面上也有一堆更新的译码器、IO扩展芯片但138那套以编码换引脚的思路至今没有过时反而在FPGA、CPLD的片上逻辑里以另一种形式活着。把这个思路吃透比单独记一颗芯片的引脚功能有价值得多。
返回列表