尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

51单片机与8155实现16路彩灯控制系统:原理图、仿真与源码详解

51单片机与8155实现16路彩灯控制系统:原理图、仿真与源码详解 简介基于51单片机的16路彩灯控制系统是一份以8155芯片作为外围扩展核心的完整设计方案面向单片机学习者和电子设计新手可实现至少16盏LED、4种灯光效果以及通过按钮切换灯光、暂停后全亮并再按继续等交互逻辑适用于课程设计或竞赛场景。压缩包共34个文件、仅2.22MB其中既有原理图及PDF文档、ISIS仿真图也有C/A51源程序与HEX烧录文件、元件清单Excel、流程图BMP以及实操录屏MP4覆盖从电路设计、程序编写、仿真调试到实物验证的全流程便于对照学习与二次开发。目前已有178人学习下载资料按功能归类查阅直观。借助其中的流程图和录屏可快速理解8155扩展接口的时序控制与LED花样切换逻辑参照元件清单和仿真图能复现硬件电路结合源代码还可进一步修改灯光效果、增加交互模式是一份边看边练的完整设计参考。1. 16路彩灯控制系统为什么绕不开8155当你需要在单片机课程设计里驱动16路LED并实现流水、交替、追赶这些花样时51单片机自己的IO口很快就会不够用。最直接的替代方案是换STM32但很多人会忽略另一个思路用一颗Intel 8155可编程接口芯片配合8051把P0总线扩展成三个并行口PA和PB各8位正好能挂16路彩灯。这个方案在课程设计和初版产品验证里非常常见因为它只用一条外部总线代码全靠XBYTE访问不占用额外IO。本文会从原理图、流程图、物料清单、Proteus仿真图到源代码把基于51单片机的16路彩灯控制系统完整拆解一遍重点讲透8155的片选地址、IO/M引脚设置、驱动电流计算和仿真下载细节。适合正在做51课程设计或者想用8155替代额外锁存器简化布线的开发者。2. 8155扩展16路彩灯的原理图设计与地址映射2.1 为什么用8155而不是8255或锁存器51单片机访问外部设备时P0口是地址/数据复用总线低8位地址靠ALE引脚锁存。8255本身不带地址锁存必须额外接74LS373这会让原理图多出至少一个芯片和一大片连线。8155则把地址锁存器集成在内部AD0~AD7直接接P0ALE直接接单片机的ALE省去了外部锁存器。对16路彩灯这种纯输出场景PA口和PB口分别提供8个输出一个8155刚好覆盖。再加上8155自带14位定时器虽然本文不强制使用但以后想扩展PWM调速也不需要再外挂芯片。原理图上还有一个常见误区很多人在网上找的518255电路里会看到373就会照着给8155也加一个373。实际上8155的ALE引脚就是用来锁存AD0~AD7低地址的加了外部锁存器反而会造成总线时序混乱。只要把8155的ALE接到51单片机的ALE引脚即可这个细节在仿真和实物中都会直接影响WR脉冲和地址写入。2.2 8155片选地址计算IO/M和CE的接法决定一切8155内部有命令/状态寄存器、PA口、PB口、PC口和两个定时器寄存器共6个地址。它的片选信号CE决定芯片是否被选中IO/M引脚决定访问的是IO寄存器还是外部存储器。实际工程里IO/M一般接P2.0CE接P2.7。当CE为低且IO/M为高时访问的是8155的IO寄存器。如果这样接一个比较顺手的外部地址基准是0x7F00。原因是P2.7对应A15P2.0对应A8。当MOVX指令访问0x7F00到0x7F05时P2口输出高字节0x7F即P2.70P2.01CE和IO/M正好满足选中条件。下面的连接表把关键信号列出来方便对着原理图核对。8155引脚51单片机引脚说明AD0~AD7P0.0~P0.7地址/数据复用总线ALEALE锁存低8位地址WRP3.6写选通RDP3.7读选通CEP2.7片选低电平有效IO/MP2.01IO访问0存储器访问RESETRST复位信号和51同步复位地址基准按0x7F00时内部偏移如下表寄存器相对偏移绝对地址命令/状态寄存器0x000x7F00PA口0x010x7F01PB口0x020x7F02PC口0x030x7F03定时器低8位0x040x7F04定时器高8位0x050x7F05在Keil C51里访问这些地址最省事的方法是用XBYTE宏。因为MOVX指令访问的是外部数据空间不能直接写在sfr定义里。#include reg52.h #include absacc.h #define uchar unsigned char #define I8155_CMD XBYTE[0x7F00] #define I8155_PA XBYTE[0x7F01] #define I8155_PB XBYTE[0x7F02] #define I8155_PC XBYTE[0x7F03] void init_8155(void) { I8155_CMD 0x03; // PA输出、PB输出、PC不使用等价于0b00000011 }这段代码的关键在第11行。控制字0x03的位0和位1为1分别把PA口和PB口设为输出模式。很多人在这一步把命令字写成0x7F导致8155的定时器中断打开、C口也被意外设成输出虽然看起来不影响亮灯但后面扩展按键或模拟量时会出问题。初始化完成后往I8155_PA和I8155_PB写数据LED就能被点亮。2.3 16路LED驱动电路灌电流和ULN2803取舍8051和8155的IO口拉电流能力都很弱但灌电流能力稍好。常见做法是把LED阳极接到5V阴极经过限流电阻接到8155的IO引脚让IO口输出低电平点亮LED。这种接法的好处是只有一路电阻省事但8155的IO口最大灌电流一般在2mA左右16个LED全亮时总灌电流要接近200mA以上直接接会拉低电平还会让芯片发烫。更稳妥的方案是在PA口和PB口后面各接一片ULN2803用达林顿管驱动LED。ULN2803内部有续流二极管适合驱动共阳LED。输入高电平时输出端吸收电流LED点亮。这样8155只负责输出控制信号不直接承受LED电流。如果你是做Proteus仿真可以直接把LED阴极接电阻到GND阳极接8155引脚仿真里不会烧芯片。但做实物时建议按ULN2803方案来画原理图。整个新增硬件部分只有两片ULN2803、16个LED、16个330Ω限流电阻和一个公共5V电源节点。代码层面如果用了ULN2803逻辑是写1点亮和灌电流接法的写0点亮正好相反这意味着同一套源代码在两种驱动电路下表现会完全不同切换驱动板时必须重新核对亮灯逻辑。3. 16路彩灯的流程图、定时器初始化与花样状态机3.1 主程序流程图和初始化顺序主程序的逻辑非常清晰先关中断设置堆栈初始化8155的控制字初始化T0定时器打开总中断然后进入while循环等待节拍标志。流程图里最容易被忽略的是8155复位和51复位是同步的如果分开控制8155可能还没完成复位你就写入了控制字导致PA/PB方向错乱。下面这段代码可以直接放到Keil工程里主循环用查表方式刷新16路LED。pattern数组每一帧占两个字节第一个字节给PA第二个字节给PB。#include reg52.h #include absacc.h #define uchar unsigned char #define uint unsigned int #define I8155_CMD XBYTE[0x7F00] #define I8155_PA XBYTE[0x7F01] #define I8155_PB XBYTE[0x7F02] uchar tick; bit beat 0; // 8帧数据每帧16bit对应16路LED code uchar pattern[8][16] { {0x01,0x00,0x02,0x00,0x04,0x00,0x08,0x00, 0x10,0x00,0x20,0x00,0x40,0x00,0x80,0x00}, {0x80,0x00,0x40,0x00,0x20,0x00,0x10,0x00, 0x08,0x00,0x04,0x00,0x02,0x00,0x01,0x00}, }; void timer0_init(void) { TMOD (TMOD 0xF0) | 0x01; TH0 0xD8; TL0 0xF0; ET0 1; TR0 1; } void main(void) { uchar i 0; uchar mode 0; init_8155(); timer0_init(); EA 1; while (1) { if (beat) { beat 0; I8155_PA pattern[mode][i]; I8155_PB pattern[mode][i 1]; i (i 2) 0x0F; } } }(i 2) 0x0F的作用是让帧索引在0、2、4、6、8、10、12、14之间循环每次取数组里的两个字节。如果直接用i (i 2) % 16效果一样但取模运算在51上比按位与慢。这个循环不会阻塞在delay函数里所以以后要加按键扫描也很方便。3.2 10ms定时器节拍与重载值计算流水灯的节奏感来自固定时间间隔。靠软件delay实现流水简单但一旦需要按键切换模式delay会让按键扫描变得迟钝。所以工程上一般用一个10ms的软件节拍每100ms刷新一次花样。上面的timer0_init用了定时器T0的方式1也就是16位定时器。如果晶振是12MHz机器周期是12/12MHz1μs定时10ms需要计数器从65536-1000055536开始计数55536的十六进制就是0xD8F0。在中断服务函数里必须重新给TH0和TL0赋初值。初值不重新装载第一次定时10ms后面就变成65.536ms灯的节奏整体会慢下来。void timer0_ISR(void) interrupt 1 { TH0 0xD8; TL0 0xF0; tick; if (tick 10) { tick 0; beat 1; } }如果你用的是STC89C52这类增强型51单片机因为大部分代码还是兼容标准8051上面这段程序直接烧录就能用。但晶振如果是11.0592MHz数学上会有偏差10ms对应的计数值是65536-921656320十六进制是0xDC00。这时候要改TH00xDCTL00x00不然流水速度会略偏快。3.3 花样扩展用状态机代替乱写地址16路彩灯的效果可以分成两类一类是位置变化比如单灯右移、双灯对跑、全亮后灭另一类是亮度变化比如呼吸灯。亮度变化需要PWM8155的定时器刚好可以承担PWM时基但占空比计算会更复杂。普通课程设计只要求花样多建议用状态机配合查表数组把每种花样的数据提前算好放进code区。这样做有三个好处第一切换花样时不需要在代码里做移位运算直接拷贝两字节就行第二数组存放在程序Flash里不占宝贵的内部RAM第三修改花样只需要改数组不需要改主函数逻辑。需要留意的是8155的PA口和PB口都是单向锁存输出写入一次会保持输出状态。如果一个花样在显示过程中不更新某一口上一次的数据会一直留在那个口上。所以写花样表时最好把不变化的那一路也写成0x00或0xFF避免出现残留状态。残留状态在仿真里不明显但实物上会表现为某一颗LED不跟随节奏闪烁而是常亮或微亮。4. 制作硬件前必须确认的物料清单与PCB排错顺序4.1 器件选型和BOM表做这个16路彩灯系统物料清单不复杂但每一样选型都会影响最终稳定性。下面是完整BOM表按采购顺序排列编号名称型号/规格数量说明1单片机STC89C52RC或AT89C511课程设计爱用STC下载方便2可编程接口芯片Intel 81551DIP40封装别买成82553达林顿驱动阵列ULN28032每路最大500mA足够16路LED4发光二极管φ5mm共阳红色或蓝色16若做其他颜色修改限流电阻5限流电阻330Ω或470Ω16驱动ULN2803后给LED限流6P0上拉排阻9脚10kΩ排阻1实物必须加Proteus可省7晶振12MHz1配合30pF负载电容8陶瓷电容30pF2晶振对地9电解电容10uF/16V1复位电路10电解电容100uF/25V1电源入口滤波11瓷片电容0.1uF2分别放8155和单片机VCC旁12电源接口USB座或DC5.5座15V输入这里有一个容易忽略的点P0口上拉。51单片机的P0口是开漏输出做总线访问时必须通过排阻拉到5V。仿真里经常忽略这一步但拿到实物后没有上拉排阻会导致访问外部RAM时数据不稳定表现为同一段代码在Proteus里正常在实物板上随机丢字节。4.2 16路负载电流估算和电源余量16颗LED如果每颗按10mA计算总电流只有160mAUSB供电完全没问题。但如果选高亮LED限流电阻取太小电流可能冲到30mA以上整板电流就会到480mA。再加上51单片机、8155和ULN2803的静态功耗USB口供电实际余量已经不大。建议把限流电阻按目标电流10-15mA来算红色LED压降约1.8VULN2803饱和压降约0.2V电源5V电阻值R(5-1.8-0.2)/0.01300Ω标称选330Ω。如果用的是灌电流方案把ULN2803去掉LED直接接8155引脚时电阻计算必须把8155低电平时的VOL也算进去。8155的VOL在灌电流4mA时可能到0.6V甚至更高实际亮度会明显偏低。这就是要加驱动芯片的根本原因。4.3 从零焊接和上电排查顺序焊接建议先做最小系统单片机、晶振、复位、电源然后写一个P1口闪灯程序确认最小系统没问题。接着焊8155和排阻用一段最简单的测试代码写PA口例如I8155_PA0x55再用万用表量PA0和PA1引脚应该一个高一个低。确认地址映射正确后再焊ULN2803和LED。如果一上电整片LED全亮多半不是程序问题而是PA口方向没输出或者焊接把AD0和AD1短路了。最后焊完要检查地线。ULN2803驱动LED时LED电流从5V经过LED、ULN2803、GND回流这根地线如果太细公共阻抗会把噪声耦合到51单片机上。实物板常见症状是流水跑到一半LED闪一下就复位大多不是因为程序而是地线压降导致单片机电源瞬间跌落。5. 在Proteus里复现8155彩灯仿真图并排查异常5.1 新建Proteus工程并加载源代码Proteus里实现这个系统很快但有一个关键选择单片机型号。如果你手头是STC89C52Proteus库里的STC模型不一定完整很多版本会提示模型不存在。更稳妥的做法是在仿真里放AT89C51或AT89C52程序编成HEX文件直接烧进这个仿真芯片。AT89C52和STC89C52在8155访问方面完全兼容仿真通过后再把HEX下载到实际STC单片机里。操作步骤可以按下面这个顺序走先放置AT89C51、8155、两个LED排组、电阻和电源。然后双击单片机把Clock Frequency设为12MHz在Program File里选Keil生成的HEX文件。再放两个逻辑输出探头到PA口和PB口或者直接放16个LED。连线时特别注意8155的引脚编号很多版本Proteus的8155引脚顺序是AD0~AD7分布在芯片两侧CE和IO/M靠近RD/WR连错一根就会访问不到内部寄存器。5.2 仿真常见现象和排查方法仿真里出现的问题往往和时序无关更多是模型或地址设置导致的逻辑错误。下面这张表整理了最常遇到的四种情况现象可能原因排查方法LED毫无反应命令字没写入或地址没映射到0x7F01检查XBYTE地址是否为0x7F01只有PA口受控PB口无输出控制字0x03被误写成0x01初始化改成0x03全亮但LED非常暗直接把LED阳极串电阻接8155且仿真模型带负载改用ULN2803或降低电阻仿真运行极慢或死机8155复位脚悬空模型一直处于复位态将8155 RESET接51单片机的RST另外提醒一点Proteus的8155模型在某些版本里没有内置上拉AD0~AD7需要额外接一个上拉排阻否则XBYTE访问可能读到0xFF。排阻放在仿真里不影响速度但能极大减少“地址写不进去”的错觉。5.3 用虚拟示波器验证WR和ALE时序如果代码看起来没问题但8155就是不工作可以用Proteus的虚拟示波器看ALE和WR脚。运行下面这段测试代码它会把PA口写成0x55然后改成0xAA形成一个方波输出。void test_8155(void) { init_8155(); while (1) { I8155_PA 0x55; I8155_PA 0xAA; } }把示波器探针接在8155的ALE和PA0上运行后应能看到ALE频率约为系统时钟的六分之一到八分之一。如果ALE引脚一直为低或恒为高说明8155模型没有收到ALE时钟检查AD0~AD7宽口是否正确连接。示波器上还可以看到PA0引脚在0.55V附近摆动的波形这样就能确认输入输出方向没问题再回去查命令字地址。6. 实物联调与16路IO逐一验证的进阶技巧上电之前先用万用表电阻档量一下5V和GND之间的阻抗正常应该大于100Ω。如果接近0先别通电重点查ULN2803是否焊反、LED是否装反、电源滤波电容是否短路。这个问题在制作洞洞板时非常高频尤其是ULN2803的9脚是GND8脚才是输出公共端两者如果误连电源直接短路。从程序角度不建议直接跑完整花样代码。写一个最基本的IO扫描程序让PA口和PB口按0x01、0x02、0x04的顺序跑一遍。每一颗LED亮灭时用万用表量一下8155对应引脚电压确认是低电平或者高电平。ULN2803方案下输入为高时输出低LED点亮。如果发现某个引脚电平正常但LED不亮大概率是LED极性或者限流电阻焊接问题。验证完IO之后再把完整花样程序的节拍从100ms改到500ms方便肉眼观察。流水速度变慢时如果出现某一路没有按顺序亮而是跟着相邻路一起闪这是PCB走线耦合或漏电流导致的。可以把这个通道的限流电阻调大比如从330Ω换成1kΩ漏电流的影响就会降到最低。最后测一下8155和ULN2803的工作温度。16路全亮时ULN2803有一定温度很正常但如果烫手说明流过LED的电流太大应该把限流电阻往大调。8155主要处理逻辑信号正常工作温度不应该明显升高。通过测量每一路LED的实际压降和工作电流把电流值记录在BOM表旁边后续复制这套设计时就不需要再猜参数了。本文还有配套的精品资源点击获取
返回列表