尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

基于74LS164的51单片机串转并驱动数码管显示实战

基于74LS164的51单片机串转并驱动数码管显示实战 简介本资源是一份面向电子类专业学生及单片机初学者的74LS164串转并驱动数码管显示的完整实践项目包聚焦数字电路与嵌入式基础应用解决串行控制多位数码管动态显示这一典型硬件扩展难题。压缩包共20个文件含Keil C51工程核心文件.c、.uv2、.hex、编译中间产物.obj、.lst、.m51、原理图设计文件.dsn、.dbk及调试辅助文件.plg、.opt、.bak全面覆盖从电路设计、C语言编程、编译烧录到仿真验证的全流程。资源体积仅90KB轻量易用结构清晰便于快速导入Keil环境运行调试。学习者可直接复现74LS164时序控制逻辑、数码管段码/位码协同驱动机制并掌握动态扫描消隐、时钟频率匹配等关键实践要点是理解移位寄存器在显示系统中实际落地的优质入门范例。 手头有块STC89C52想让它驱动一位数码管显示数字直接接的话一个数码管要8根段选线单片机IO口瞬间被占掉大半于是翻出了这个经典项目74LS164串转并扩展驱动数码管显示。这个项目在51单片机入门圈里属于必做的小实验核心就是用两三个IO口通过移位寄存器扩展出8个并行输出去点亮数码管的各个段让显示功能不再被IO数量卡脖子。适合刚学完C51基本语法、想做显示类小作品或者还在纠结怎么用最少的线控制数码管的初学者。今天我就把这个项目的完整思路、硬件原理、代码实现和踩坑经验一次性讲清楚。1. 项目整体设计与技术选型1.1 这个经典小项目到底解决了什么问题在51单片机系统里最常用的显示器件就是数码管。一个8字形的数码管本质上就是8个LED7个段加一个小数点驱动它显示数字本质就是控制这8个LED的亮灭。如果直接由单片机IO驱动一个数码管就要占用8个IO。项目里如果用4位甚至8位数码管IO资源会非常紧张而且IO通常还要兼顾按键、传感器、串口通信等功能。74LS164的作用就是把“串行数据”转换成“并行输出”。单片机只需要用两根线一根数据线、一根时钟线把数据一位一位“推”进去164的输出端就会同时出现一组8位并行信号去控制数码管的8个段。这样一来2根IO替代了8根IO省下来的6根口子可以干更多事情。对资源紧张的51平台来说这个性价比非常实在。有些同学会觉得直接买带锁存的数码管驱动芯片不是更省事确实有这类芯片但那个是另一套思路。用164驱动数码管的好处在于它把移位寄存器的概念讲透了而且电路结构非常直观对理解单片机通信时序帮助很大。做这个项目不仅是让一块数码管亮起来更是为将来接触SPI、I2C、串口这些通信协议打底子。1.2 为什么选用74LS164而不是更常见的74HC595这里有个常见疑问市面上更流行的是74HC595带输出锁存器为什么老教程还在用164我自己这两个芯片都用过说说体会。第一164便宜一片几毛钱做实验焊坏了不心疼。第二164逻辑更简单没有锁存端只需要数据、时钟、清零三个控制端对新手来说更容易理解移位寄存器的本质。第三像Proteus仿真、老版C51教材、大量竞赛例程都默认用164资料好找照着抄也能跑起来。当然164也有明显短板输出端直接跟随移位过程如果在数据发送过程中有干扰数码管会出现瞬间乱码而595多了一个RCLK锁存引脚可以等所有数据全部移位完成后再一次性输出显示稳定得多。所以我的建议是个人学习阶段先用164把原理吃透以后做产品或者追求显示稳定性的场景再切595。一步到位直接上595也不是不行但少了对比对为什么需要锁存器的理解会差一点。1.3 项目前置知识与适用读者想做这个项目默认需要一点C语言基础会定义变量、写循环、用数组知道单片机引脚怎么拉高拉低。至于8051的内部结构、定时器、中断这些刚开始用不到后面扩展功能才涉及。所以这个项目的定位很清晰至少学完单片机GPIO输出和基本循环结构的同学第一周就能把它跑起来。如果你完全零基础建议先把C语言的for循环、按位操作搞明白再来做这个项目。按位操作尤其关键因为串行发送数据的过程本质上就是“每次取出一个二进制位把它放到数据线上”这一步绕不开。2. 硬件原理与电路设计2.1 74LS164引脚功能与串转并原理74LS164是一个8位串入并出移位寄存器典型封装是14脚DIP。引脚不多但每个都很有讲究。VCC和GND是电源5V供电。A和B是串行数据输入端这两个引脚在芯片内部是一个与门只有A和B同时为高输入数据才算1任意一个为低数据就是0。实际使用中常常把A、B接到一起只用一个数据口控制否则容易绕晕。CLK是时钟端数据在CLK的上升沿移入寄存器也就是说时钟从低变高的瞬间芯片会把当前数据线上的电平锁进第一位。Q0到Q7是8位并行输出端Q0对应最先进入的数据Q7对应最后进入的数据。CLR是清零端低电平有效把这个引脚拉低所有输出立刻清零正常工作时必须接高电平。注意CLR引脚不接或者悬空输出状态会变得随机这是很多人第一次做这个项目显示乱码的头号原因。建议CLR通过一个10kΩ电阻接到VCC防止上电瞬间误触发清零。串转并的原理用一句话概括想象8个空盒子排成一排每来一个时钟脉冲就把新数据放到最左边的盒子原来盒子里的东西依次往右挪一格。8个脉冲之后8个盒子里就存了一组完整的8位数据从Q0到Q7同时输出。这个过程叫移位寄存器是串口通信、SPI协议、LCD驱动等一大堆技术的底层思想。还有一点很多人忽略74LS164是TTL类型的芯片工作电压范围大约是4.5V到5.5V。如果你用的是3.3V的STM32必须对外置芯片提供5V电源同时IO电平需要做转换或者直接改用74HC164、74HCT164这类兼容3.3V逻辑的型号。不然数据线上的高电平不够164可能识别不出有效信号。2.2 共阴共阳数码管的识别与连接数码管按公共端分共阴和共阳两种。共阴数码管所有LED的阴极接到公共端要显示某段就在对应段引脚给高电平。共阳数码管所有LED的阳极接到公共端要显示某段就要给低电平。在74LS164这个项目里选择不同数码管代码里的段码表完全不同所以连接前一定要判断清楚。怎么判断常用的土办法拿一节1.5V电池串联一个1kΩ电阻电池正极接公共端先假设它是共阳电阻碰某个段引脚如果LED亮了说明这是共阳管段引脚低电平点亮如果不亮反过来电池负极接公共端再试。用万用表的二极管挡也可以判断红表笔接公共端、黑表笔碰段引脚有压降说明是共阳反过来有压降就是共阴。不过最靠谱的还是看数据手册或者商家标注。市面上常见的双位一体数码管引脚顺序往往是公共端在中间段引脚分列两边每家厂商的排列还不一样。我之前买过一批杂牌数码管丝印和引脚顺序跟手册对不上只能靠这个方法一个个试出来。这种经验在硬件调试里非常常见别嫌麻烦。2.3 限流电阻选择与亮度调节数码管的本质是LED不能直接接5V电源必须串限流电阻。阻值怎么算假设供电5V红色LED压降约1.8V到2V数码管典型工作电流5mA到15mA。用欧姆定律R (VCC - V_LED) / I取V_LED等于2V、I等于10mA算出来就是(5减2)除以0.01等于300Ω。市面上常用220Ω、330Ω、470Ω都能用。阻值越大电流越小亮度越低阻值太小则会过流时间长了数码管会发烫甚至烧段。实际经验是5V系统用330Ω比较平衡亮度清晰又不会太刺眼。限流电阻可以放在数码管的段引脚上也可以放在公共端上。放在公共端虽然电阻数量少但多位显示时电流会变化亮度不均放在每个段引脚上更规范电流一致。这个项目里一个数码管8个段就接8个电阻别嫌多。另外实物连线较长时建议在74LS164的电源引脚附近就近放一个0.1uF去耦电容否则时钟边沿容易引入毛刺出现偶发性的数据错乱。这类问题排查起来非常头疼不如提前加电容。2.4 常见硬件连接方案对比驱动数码管硬件方案其实有好几种我把常见路子放在一起对比方便理解164在这个体系中的位置。方案IO占用优点缺点适用场景单片机IO直接驱动每位数码管8个IO代码最简单无附加芯片IO浪费严重1位数码管实验74LS164串转并驱动2个IO加1个清零线原理清晰成本低资料多移位过程输出不稳定学习移位寄存器原理74HC595串转并驱动3个IO有输出锁存显示稳定可级联多一个锁存控制稍微复杂产品化、多位显示74LS48译码器驱动4个IO直接输出段码简单只能显示0到9无法显示字母纯数字显示实际选型时纯粹做显示实验选164或595都行做课程设计、电子时钟这类功能较多的我建议595想省事只显示数字的译码器也够用。今天这个项目围绕164展开因为它结构最简单最能讲清楚移位寄存器的原理。3. 软件实现C51代码逐段拆解3.1 段码表的生成手工与取模软件两种方式软件部分的核心是段码表。所谓段码就是让数码管显示某个字符时8个段引脚上高低电平的组合。以共阴数码管为例段引脚a、b、c、d、e、f、g、dp分别接到74LS164的Q0到Q7要显示数字0点亮的是a、b、c、d、e、f这6个段g和dp不亮。高电平为1低电平为0从Q7到Q0排列就是0111 1110十六进制就是0x3F。数字1只点亮b和c对应0x06。这个表网上到处都是但建议自己推导一遍0到9这样以后换引脚顺序就不会被表坑了。如果觉得手推麻烦可以用取模软件。网上常见的“数码管取模软件”或者字模软件选7段或8段数码管模式输入字符自动生成段码。取模软件的好处是支持自定义段顺序、自定义共阴共阳还能一次生成A-F、小数点、横杠等字符的码。我自己早期是手推后来项目多了确实是取模软件效率高。有一点必须提醒不同工具生成的段码顺序可能不一样有的从a开始有的从dp开始用之前一定要和硬件接线严格对应。很多乱码问题不是芯片坏了而是段码表顺序和引脚接线对不上。3.2 串行发送时序与核心函数串行发送的核心是把一个字节的8个二进制位依次放到数据线上每放一位给时钟一个上升沿。有的代码先发低位再发高位有的先发高位两种都可以但必须和硬件接线一致。我习惯先发高位位7到位0因为这样Q0输出对应数据的最高位数码管段码从左到右排列比较直观。发送函数可以写成sbit DATA P1^0; sbit CLK P1^1; void HC164_SendByte(unsigned char dat) { unsigned char i; for (i 0; i 8; i) { DATA (dat 0x80) ? 1 : 0; // 取出最高位放到数据线 CLK 0; // 时钟先拉低 CLK 1; // 产生上升沿数据移入 dat 1; // 左移处理下一位 } }为什么用0x80判断最高位因为一个字节8位最高位对应Q0输出和段码表从左到右排列正好对应。如果改用先发低位判断条件就变成dat与0x01段码表需要反过来排列否则显示出来的字形就是镜像的。这段代码最关键的是“先置数据、后拉时钟”的顺序。如果在时钟上升沿的同时改变数据线电平芯片采到的就可能不是想要的数据这是时序问题。虽然51单片机主频低指令执行慢一般不至于出错但养成“数据先就绪时钟后再来”的习惯以后驱动SPI器件时会省很多事。3.3 完整示例代码下面是一份完整的C51示例功能是让一位共阴数码管循环显示0到F#include reg52.h sbit DATA P1^0; sbit CLK P1^1; unsigned char code segCode[] { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71 }; void HC164_SendByte(unsigned char dat) { unsigned char i; for (i 0; i 8; i) { DATA (dat 0x80) ? 1 : 0; CLK 0; CLK 1; dat 1; } } void delay_ms(unsigned int ms) { unsigned int i, j; for (i 0; i ms; i) for (j 0; j 120; j); } void main(void) { unsigned char num 0; while (1) { HC164_SendByte(segCode[num]); delay_ms(500); num; if (num 15) num 0; } }这里把段码表用code关键字放到程序存储器里能省下宝贵的片内RAM。51单片机的RAM一共才128字节或256字节16个字节的查找表看起来不多但项目大了能省一点是一点这也是老C51程序里的常见习惯。如果用的是STC89C52编译环境用Keil C51注意把单片机型号选对。STC系列需要先用STC-ISP软件下载程序步骤是先点“下载”按钮再给板子上电否则会出现下载失败。3.4 为什么这里建议静态显示而非动态扫描多位显示时有两种思路静态显示和动态扫描。静态显示就是每位数码管都配一片164数据写一次就保持住显示稳定占用IO稍微多点。动态扫描则是所有数码管共享8根段选线再用位选线轮流点亮每一位利用人眼视觉暂留形成“同时亮”的错觉。在这个用164的项目里如果只有一片164那就只能做动态扫描把164的段输出接到所有数码管的段引脚用额外IO轮流拉低位选。听起来没问题但因为164没有输出锁存每次发送新数据的过程中输出状态一直在变扫描过程会看到明显的闪烁和拖影。所以我的建议是用164驱动多位尽量采用“每片164固定驱动一位”的静态显示方案代码简单可靠。如果非要动态扫描那就把164换成595借助输出锁存把移位过程隔离开。我踩过这个坑当时图省事用一片164扫4位数码管结果是数字乱跳后来换回一片164对应一位问题立刻消失。4. 实操调试与问题排查4.1 Proteus仿真中的搭建细节如果不想一上来就动烙铁Proteus仿真是一个很好的起点。搭建步骤大概是从元件库搜74LS164放到原理图上再放一个共阴数码管比如7SEG-COM-CAT-8。74LS164的A、B接在一起接到单片机一个IOCLK接另一个IOCLR通过一个10kΩ电阻接到VCC也可以直接接VCC。数码管的公共端接GND8个段引脚通过电阻分别接到164的8个并行输出。单片机选AT89C51或STC89C52加载编译好的HEX文件点运行。仿真的好处是方便观察时序。我一般会在DATA和CLK引脚上放虚拟示波器或逻辑分析仪配合单步运行来看数据波形。如果发现输出不对先在仿真里查时序仿真通过了再动手做实物能省下不少烧坏元件的时间。仿真跑通了以后把程序下载到开发板上大概率能直接工作。如果实物不亮优先查接线不要怀疑仿真错了。仿真和实物之间最常见的差异是引脚顺序特别是数码管这种多引脚元件Protues里的默认引脚顺序和实际封装的引脚顺序经常对不上务必以实物的器件手册为准。4.2 实物接线与调试顺序谈到实物我的建议是按模块分步调试第一步只接电源和164把CLR拉高用万用表测Q0到Q7都是接近0V确认芯片能正常工作。第二步不接数码管用单片机发送0x00多打几个时钟脉冲观察Q0到Q7的电平变化。这个阶段用LED灯观察输出端能确认串行发送代码是否正常。第三步接上一个限流电阻和一个LED到Q0发送数据0x01看LED是否点亮。如果亮了说明数据线、时钟线和代码基础逻辑都没问题。第四步接上数码管发送0x3F看是否显示0。如果不显示检查公共端接法、段码表顺序。这个顺序的好处是把“芯片问题”、“代码问题”、“数码管接线问题”三个阶段隔离开哪个环节出错都能快速定位。很多人一上来就把所有器件焊完一旦不亮排查起来头大。焊接时注意DIP封装的74LS164插入IC座时要对齐缺口方向焊完先用放大镜检查有没有焊桥。万能板连线尽量短数据线和时钟线不要绑在一起走太长距离不然高速翻转时很容易互相干扰产生误触发。4.3 常见问题速查表这里整理一份我在实际调试中和带新手过程中反复遇到的故障清单可以直接对照排除现象可能原因排查方法数码管完全不亮164未正常工作CLR悬空或拉低电源接反用万用表测164的VCC和GND确认CLR接高电平检查数码管公共端接法显示内容乱码共阴共阳搞反、段码表不对、引脚顺序接错确认数码管类型核对段码表与接线顺序数据和时钟对不上发送位顺序与输出引脚对应错误先发0x01观察Q0和Q7再调整代码位顺序显示一边亮一边暗限流电阻未加或数值差异大8个段全部串相同阻值电阻选330Ω左右多个164级联时数据错位级联顺序接反或Q7接错确认前一片Q7接后一片A和B按反向顺序发送数据数码管明显发烫限流电阻太小或未接立即断电串接入合适的限流电阻这张表建议收藏做任何LED显示类项目都能用得上。尤其是“级联时数据错位”这个问题后面做多位显示时几乎必然遇到。5. 扩展应用与进阶思考5.1 多片级联驱动多位数码管要驱动两位或更多位数码管可以一片164对应一位也可以把多片164级联起来只占用两个IO。级联方法很简单第一片的Q7并行输出脚接到第二片的A和B第二片的Q7再接第三片以此类推所有164的CLK并联在一起。发送数据时注意顺序是反的先发“最后一片要显示的数据”再发“倒数第二片的数据”最后才发“第一片的数据”。为什么反着发因为每个时钟脉冲会把数据往后推一格最先进入的数据最终会跑到最末尾那一片。这和74HC595级联的套路一样。我最早做8位滚动时钟时就是4片164级联共用了两个IO加一根清零线驱动4位数码管逻辑清晰显示稳定。如果把CLR统一接到一个IO还可以实现全部输出同时清零这个功能在刷新整个显示画面时非常有用。5.2 移植到Arduino与STM32的要点这个项目换到别的平台核心逻辑完全一致。到Arduino上只需要把sbit换成digitalWrite或者用SPI库直接发数据。注意Arduino的SPI默认是MSB先发和上面代码一致可以直接把段码表发过去。如果用SPI库记得选好时钟极性和相位74LS164要求空闲时时钟为低数据在上升沿采样对应SPI模式0。到STM32上可以用GPIO模拟时序也可以用硬件SPI。用硬件SPI时把段码表作为发送缓冲注意发送速率不要太高先观察示波器确认时序再逐步提速度。无论哪个平台我都建议先用逻辑分析仪看一遍收发波形确认时序没问题再调显示。这是嵌入式调试的通用经验放之四海而皆准。5.3 与74HC595的对比与选型建议回到选型这个话题。74LS164和74HC595的区别主要有三点。第一164没有输出锁存器输出随移位过程实时变化可能在更新数据时出现短暂乱码而595有RCLK锁存脚可以数据全部移完后再更新输出。第二164的串行输入是A与B两个脚接起来用就行595的输入是单脚的SER另有OE输出使能引脚可以控制输出关闭方便低功耗管理。第三595可以直接级联驱动能力往往略强适合做长距离多字节传输。如果你是做正式项目我建议直接用595如果是学习原理或应付课程实验164依然是性价比极高的选择。我个人会把这两个都写熟因为很多老式设备、竞赛题里仍然大量使用164看得懂老图纸也是一种能力。最后再分享一个我自己实验中常做的小动作每次给164烧录前先全速运行一遍自检程序让数码管依次点亮a、b、c、d、e、f、g、dp这8个段确认每一段都正常再运行正式显示程序。这样能提前发现段引脚虚焊、限流电阻开路这类硬件问题避免在功能调试时反复怀疑代码。这种“先自检硬件再调逻辑”的习惯我用了很多年对提高调试效率帮助很大也建议你从这个项目开始就养成。本文还有配套的精品资源点击获取
返回列表