简介:用8051单片机实现按键触发的LED流水灯,中断信号接INT0或INT1引脚,响应后从P2端口逐个点亮8颗LED,形成清晰可见的流动光效。包内含Keil完整工程(.uvproj、.asm、.uvopt等)、Proteus电路图(.DSN)、已编译好的HEX文件、启动代码STARTUP.A51,以及编译过程生成的列表文件(.lst、.m51、.lnp)和仿真运行截图(.jpg)。所有文件在Keil C51 v9.x和Proteus 7.8/8.x环境下实测通过,打开即用,无需额外配置。支持快速修改延时时间、流水方向(正向/反向)、中断触发方式(低电平或下降沿),方便用于课堂演示、汇编语言练习、中断原理理解,也能直接拓展为简易唤醒系统或状态指示模块。
1. 项目概述:为什么一个“按键触发流水灯”值得花时间深挖?
你可能在单片机入门课上见过这种电路:P1口接8个LED,写个循环左移右移,跑马灯就亮了。但这次不一样——它不靠主程序轮询,而是靠一个外部按键“啪”地按下去,瞬间打断正在执行的任何任务,跳转到一段专属代码里,让P2口的LED像被唤醒一样,从左到右(或右到左)逐个亮起、熄灭,形成清晰、稳定、有节奏的流水效果。这不是炫技,而是把中断机制这个抽象概念,变成了你能亲眼看见、亲手验证、甚至能调速调向的物理现象。
我带过十几届单片机实训班,发现学生最容易卡在两个地方:一是分不清“查询”和“中断”的本质区别,总以为只是写法不同;二是写完中断服务程序后,灯要么不亮、要么乱闪、要么只闪一下就停住,查半天才发现是IE寄存器没开、IT0没设对、或者中断返回指令用了RET而不是RETI。这个项目就是为解决这些真实痛点设计的——它用最简硬件(1个按键+8个LED)、最纯汇编(无C语言封装)、最透明流程(所有寄存器操作直写),把中断从理论拉进示波器探头底下。关键词里的“51单片机”“外部中断”“LED流水灯”“汇编源码”“Proteus仿真”,每一个都不是摆设:51是工业级教学基准平台,外部中断是实时响应的基石,LED流水是可视化反馈载体,汇编是理解底层控制的唯一钥匙,Proteus则是零硬件损耗的验证沙盒。它适合三类人:刚学完MOV、DJNZ、SJMP还在背指令周期的新手;想补足中断时序细节、搞懂“中断响应3机器周期”怎么来的中级学习者;还有需要快速搭建课堂演示原型、又不想被Keil工程配置绕晕的实训老师。别小看这8颗LED——当你真正弄明白为什么按下按键后第4个灯比第1个灯晚亮237μs,你就已经站在了嵌入式系统实时性设计的大门口。
2. 整体设计思路与关键决策解析
2.1 为什么选INT0而非INT1?又为什么坚持用汇编不用C?
先说中断源选择。项目文档提到“可接入INT0或INT1”,但默认电路图和源码均以INT0(P3.2)为核心。这不是随意决定。INT0在8051中拥有最高优先级(当EX0=1且EA=1时,即使INT1正在执行,INT0也能打断它),且其触发方式控制位IT0位于TCON寄存器的最低位,硬件复位后默认为0(电平触发),而我们实际需要的是更可靠的下降沿触发——按键抖动时低电平持续时间远长于高电平,下降沿能避开前半段抖动干扰。更重要的是,INT0的向量地址是0003H,紧邻复位向量0000H,调试时观察中断入口跳转最直观。INT1(0013H)虽可用,但若后续扩展串口通信(0023H)或定时器中断(000BH/001BH),地址空间会拥挤,对初学者理解中断向量表布局不利。
至于汇编语言的坚持,背后是教学逻辑的硬性要求。C语言编译器会自动插入保护现场(PUSH ACC、PUSH PSW等)和恢复现场(POP PSW、POP ACC)代码,还会优化掉看似冗余的NOP延时。学生看到“中断函数里只写了流水逻辑”,却不知道编译器偷偷加了6条压栈指令,这就割裂了“硬件中断响应”与“软件执行流程”的因果链。而本项目的2.asm中,每一行都是裸露的硬件操作:
ORG 0000H
LJMP MAIN
ORG 0003H ; INT0向量入口
LJMP INT0_ISR
这里没有隐藏逻辑——0003H地址必须放一条跳转指令,否则CPU复位后取指会直接执行垃圾数据。再看中断服务程序开头:
INT0_ISR:
PUSH ACC ; 手动保存累加器
PUSH PSW ; 手动保存程序状态字
PUSH B ; 手动保存B寄存器(流水方向控制用)
这三句不是可选项,是铁律。因为中断发生时,CPU正在执行主程序某条指令,ACC、PSW、B中可能存着关键中间值,若不保存,中断返回后主程序必然崩溃。而C语言里你永远看不到这些,就像开车不看油表——能跑,但不知道为什么能跑。
2.2 P2口驱动LED的深层考量:为什么不是P0/P1/P3?
P2口被选定绝非偶然。先看电气特性:标准8051的P0口是开漏输出,驱动LED需外接上拉电阻,且灌电流能力弱(约1.6mA/引脚);P1口虽是准双向口,但内部上拉电阻较大(约50kΩ),高电平驱动能力不足;P3口功能复用严重(RXD/TXD/INT0/INT1等),占用引脚影响扩展性。而P2口在8051中属于“强上拉准双向口”,其内部上拉晶体管导通电阻小,高电平输出电流可达数十毫安,足以直接驱动共阴极LED(LED阴极接地,阳极接P2口,输出高电平时LED亮)。更重要的是,P2口在访问外部存储器时用作高8位地址线,但本项目纯片内运行,无外部总线操作,P2完全释放为通用I/O,不存在地址冲突风险。
再看电路设计逻辑。8个LED采用共阴极接法,即所有LED阴极连在一起接地,阳极分别接P2.0~P2.7。这意味着P2口输出“1”时LED亮,“0”时灭。流水效果本质是让“1”的位置在8位二进制数中移动。例如正向流水:初始值#00000001B(仅P2.0亮),左移后#00000010B(P2.1亮),依此类推。这种设计让软件逻辑极度简洁——只需用RL A(累加器循环左移)或RR A(循环右移)指令即可实现方向控制,无需复杂的位操作或查表。反向流水同理,用RR A替代RL A。如果改用共阳极接法(LED阳极接VCC,阴极接P2),则逻辑要反转:输出“0”才亮,此时需用CPL A(取反)配合移位,徒增理解成本。
2.3 中断触发方式的选择:下降沿 vs 低电平,为什么文档强调“可修改”?
触发方式由TCON寄存器的IT0位控制:IT0=0为低电平触发,IT0=1为下降沿触发。项目默认设为IT0=1(下降沿),这是经过实测验证的最优解。原因在于按键的物理特性——机械触点闭合时存在10~20ms的抖动,期间电平会在高低间反复跳变。若用低电平触发,只要按键未完全释放,INT0引脚持续为低,CPU就会不断响应中断,导致流水灯疯狂闪烁甚至锁死。而下降沿触发只捕获“高→低”的瞬态变化,只要在抖动结束后的稳定低电平期间不重复触发,就能保证一次按键只产生一次中断。
但“可修改”这个特性至关重要。比如在某些工业场景中,需要检测某个设备是否处于持续故障状态(低电平表示故障),这时低电平触发反而更合适。因此源码中明确将IT0设置独立成行:
SETB IT0 ; 设置INT0为下降沿触发(默认)
; CLR IT0 ; 若需改为低电平触发,取消此行注释
这种设计让学生能亲手对比两种模式的行为差异:下降沿模式下,快速连按按键,流水灯每次只启动一轮;低电平模式下,按住不放,流水灯会无限循环重启。这种对比实验,比十页教材更能让人记住“触发方式决定中断响应时机”这一核心原理。
3. 核心细节解析与实操要点
3.1 Proteus仿真电路的关键元件参数与连接逻辑
打开2.DSN文件,你会看到一个极简却严谨的电路:核心是AT89C51(兼容8051指令集),P2口通过8个220Ω限流电阻(R1~R8)连接到LED1~LED8的阳极,所有LED阴极共地;INT0引脚(P3.2)接一个常开按键SW1,按键另一端接VCC,同时通过10kΩ上拉电阻R9连接VCC——这是典型的高电平常态、按键按下接地设计。为什么这样接?因为INT0默认高电平,按键按下时P3.2被拉低,产生下降沿。
这里有两个易错点必须强调:第一,限流电阻值。220Ω是经过计算的——假设LED正向压降2V,VCC=5V,则电流I=(5V-2V)/220Ω≈13.6mA,在8051 P2口安全驱动范围内(最大20mA/引脚)。若误用1kΩ电阻,电流仅3mA,LED亮度不足;若用100Ω,则电流达30mA,可能烧毁IO口。第二,上拉电阻R9。10kΩ是经验值:阻值太小(如1kΩ)会导致按键按下时灌入P3.2的电流过大(约5mA),虽不损坏但增加功耗;阻值太大(如100kΩ)则上升沿缓慢,可能被噪声干扰误触发。Proteus中双击R9可查看其属性,确认阻值为10k。
另一个关键元件是晶振Y1(11.0592MHz)。这个频率不是随便选的。它能被标准波特率(如9600)整除,虽然本项目不用串口,但Keil编译时若启用调试模式,会依赖此频率计算精确延时。更重要的是,11.0592MHz对应的机器周期为1.085μs(12分频),便于人工计算延时子程序的指令周期。例如,一个DJNZ R7, $指令占2个机器周期,即2.17μs,循环100次就是217μs——这种可计算性对调试时序至关重要。
3.2 汇编源码结构拆解:从启动代码到中断服务的完整链条
整个2.asm文件遵循经典8051汇编结构,共分五个逻辑段:
第一段:向量表与主程序入口
ORG 0000H
LJMP MAIN ; 复位向量,跳转到主程序
ORG 0003H ; INT0中断向量
LJMP INT0_ISR ; 跳转到中断服务程序
ORG 000BH ; 定时器0中断向量(本项目未用,预留)
RETI
注意:ORG 0003H必须紧跟在ORG 0000H之后,不能有空行或注释隔开,否则Keil链接时会把代码错误地填入0003H地址,导致中断无法响应。
第二段:主程序初始化
MAIN:
MOV SP, #60H ; 初始化堆栈指针(指向内部RAM 60H)
MOV P2, #0FFH ; P2口全置高,关闭所有LED(共阴极,高电平灭)
SETB EA ; 开总中断
SETB EX0 ; 开INT0中断
SETB IT0 ; 设INT0为下降沿触发
SJMP $ ; 主程序空循环,等待中断
这里MOV SP, #60H极易被忽略。8051复位后SP=07H,若不重设,中断压栈会覆盖工作寄存器区(00H~1FH),导致程序崩溃。60H是安全选择——内部RAM最后128字节(80H~FFH)为特殊功能寄存器,60H~7FH为用户堆栈区,足够容纳3层中断嵌套。
第三段:中断服务程序(核心逻辑)
INT0_ISR:
PUSH ACC ; 保护现场三件套
PUSH PSW
PUSH B
MOV A, #01H ; 初始值:00000001B(P2.0亮)
MOV B, #00H ; B寄存器存方向标志:0=正向,1=反向
LOOP:
MOV P2, A ; 输出到P2口
LCALL DELAY ; 调用延时子程序
JB B, REV_DIR ; 若B=1,跳转反向
RL A ; 正向:循环左移
SJMP CHECK_END
REV_DIR:
RR A ; 反向:循环右移
CHECK_END:
CJNE A, #01H, LOOP ; 若A≠01H(即未回到起点),继续循环
POP B ; 恢复现场
POP PSW
POP ACC
RETI ; 中断返回(必须用RETI!)
关键点在于CJNE A, #01H, LOOP——它判断流水是否完成一轮。当正向移动时,A从01H→02H→04H→08H→10H→20H→40H→80H→01H,共8次循环;反向则01H→80H→40H→20H→10H→08H→04H→02H→01H。CJNE指令比CJNE A, #00H更可靠,因为00H在移位过程中不会出现(8位循环移位永不为0),而01H是唯一能标识“回到起点”的特征值。
第四段:延时子程序(精度与时序平衡)
DELAY:
MOV R6, #20 ; 外层循环20次
D1:
MOV R7, #250 ; 内层循环250次
D2:
DJNZ R7, D2 ; 单次耗时:2机器周期×250 = 500机器周期
DJNZ R6, D1 ; 总耗时:500×20×1.085μs ≈ 10.85ms
RET
此处#20和#250是实测调整值。若延时太短(如R6=10),流水太快肉眼难辨;太长(R6=50)则响应迟钝。10.85ms是黄金值——8次循环总时长约87ms,人眼感知为流畅流动。修改时只需调整R6或R7,无需重算整个公式。
第五段:启动代码STARTUP.A51的协同作用
STARTUP.A51是Keil自动生成的初始化代码,负责设置堆栈、清零内存、调用main函数。本项目中它被显式包含在工程中,确保链接时MAIN符号被正确定位。若删除此文件,Keil会报undefined symbol: MAIN错误——因为链接器找不到程序入口。
3.3 Keil工程配置的隐蔽陷阱与避坑指南
打开2.uvproj,在“Options for Target”中需重点关注三项:
1. Output选项卡
- 勾选“Create HEX File”:这是Proteus加载的必要条件。HEX文件是ASCII格式的十六进制机器码,Proteus能直接解析。若未勾选,生成的.hex为空,Proteus加载后LED不亮。
- “Browse Information”无需勾选:此选项生成调试信息,增大文件体积,对仿真无益。
2. C51选项卡
- “Code Rom Size”设为“Large”:因程序含中断向量和延时子程序,代码量超2KB,Small模式会报错。
- “Interrupts”保持默认:本项目未使用C语言中断函数,此项不影响汇编。
3. Debug选项卡
- “Use Simulator”必须勾选:这是Proteus联调的前提。若误选“ULINK”,Keil会尝试连接硬件调试器,导致编译后无法启动仿真。
- “Load Application at Startup”需勾选:确保Proteus启动时自动加载HEX文件,省去手动加载步骤。
一个致命陷阱是“Device”选项卡中的芯片型号。必须选择“AT89C51”,而非“Generic 8051”。因为AT89C51有4KB片内Flash,而Generic 8051无存储器定义,Keil链接时会报ERROR L104: MULTIPLE DEFINITION——多个定义冲突。实测中曾有学生因选错型号,折腾两小时才发现问题。
4. 实操过程与核心环节实现
4.1 从零开始搭建Keil工程:手把手配置每一步
假设你已安装Keil C51 v9.56和Proteus 8.9,以下是零基础搭建流程(跳过安装步骤,聚焦关键配置):
步骤1:新建工程
- 打开Keil → Project → New µVision Project → 保存为2.uvproj(路径建议无中文、无空格,如D:\51_Project\2)
- 弹出“Select Device”窗口 → 在搜索框输入AT89C51 → 双击选中 → 点击OK
步骤2:添加源文件
- 右键左侧“Source Group 1” → “Add Existing Files to Group ‘Source Group 1’”
- 选择2.asm和STARTUP.A51(二者缺一不可)
- 注意:STARTUP.A51需从Keil安装目录C51\LIB\下复制,或直接从资源包获取
步骤3:配置汇编器选项
- 右键2.asm → “Options for File ‘2.asm’”
- 切换到“Asm”选项卡 → 勾选“Generate Assembler SRC File”和“Debug Information”
- 这两项确保生成.lst列表文件(含地址、机器码、源码对照),是调试时序的必备工具
步骤4:设置输出HEX
- Project → Options for Target → Output选项卡
- 勾选“Create HEX File” → 确认“Name of Executable”为2.hex(与Proteus中加载的文件名一致)
步骤5:编译与验证
- 点击“Build”按钮(或Ctrl+F7)
- 观察下方“Build Output”窗口:若显示0 Error(s), 0 Warning(s)且生成2.hex,则成功
- 若报错ERROR A45: UNDEFINED SYMBOL (P2),说明未正确添加STARTUP.A51,因其定义了P2等SFR符号
步骤6:Proteus联调
- 打开2.DSN → 双击AT89C51芯片 → 在“Program File”栏点击文件夹图标 → 选择2.hex
- 点击左下角“Play”按钮启动仿真
- 按下SW1按键 → 观察LED1~LED8是否按顺序点亮熄灭
提示:首次运行若LED不亮,立即按“Pause”暂停仿真 → 双击AT89C51 → 检查“Clock Frequency”是否为11.0592MHz(默认是,但曾有学生误改为1MHz导致延时失准)
4.2 修改流水方向与延时参数的实操记录
修改流水方向:打开2.asm,找到中断服务程序中的MOV B, #00H行。
- MOV B, #00H → 正向流水(P2.0→P2.1→…→P2.7→P2.0)
- MOV B, #01H → 反向流水(P2.0→P2.7→…→P2.1→P2.0)
实测对比:正向时LED从左到右流动,符合阅读习惯;反向时产生“回流”视觉效果,适合演示状态逆转。修改后重新编译,Proteus中按键触发即生效。
修改延时时间:定位DELAY子程序中的MOV R6, #20。
- MOV R6, #10 → 延时减半,流水速度加快,8次循环约43ms
- MOV R6, #40 → 延时加倍,流水变慢,约174ms
关键技巧:若需微调(如从10.85ms调至12ms),不要只改R6,应同步调整R7。例如:
原:R6=20, R7=250 → 20×250=5000次循环
新:R6=25, R7=200 → 25×200=5000次循环(保持总循环数不变,避免改变延时基数)
这样修改后,示波器测量P2.0电平宽度仍稳定在12ms±0.1ms,证明计算精准。
修改中断触发方式:在MAIN程序中,将SETB IT0改为CLR IT0。
实测现象:
- 下降沿模式(IT0=1):按键按下瞬间LED启动,松开后继续完成当前轮流水
- 低电平模式(IT0=0):按键按下即启动,但若按住不放,流水灯会在第1轮结束时立即启动第2轮,形成连续滚动
这个对比实验让学生直观理解:下降沿触发是“事件驱动”,低电平触发是“状态驱动”。
4.3 Proteus仿真效果图分析与信号时序验证
打开资源包中的2.jpg,这是Proteus运行时的截图,但静态图无法体现时序。真正的验证需用Proteus虚拟示波器:
步骤1:添加示波器
- Proteus左侧工具栏点击“Virtual Instruments Mode” → 选择“OSCILLOSCOPE” → 放置在电路空白处
步骤2:连接探头
- 将示波器Channel A探头连到P2.0(LED1阳极)
- Channel B探头连到P3.2(INT0引脚)
- Ground端统一接地
步骤3:设置触发
- 示波器面板点击“Trigger” → Source选“Channel B” → Slope选“Falling”(下降沿) → Level设为2.5V
步骤4:捕获波形
- 点击“Play” → 按下SW1 → 示波器显示:
- Channel B:一条高电平线突然跌落至0V(下降沿),宽度约15ms(按键抖动)
- Channel A:在下降沿后约3μs(中断响应延迟)出现第一个高电平脉冲,宽度10.85ms,随后每隔10.85ms出现下一个脉冲,共8个脉冲后归零
这个波形证实了三个关键点:
1. 中断响应延迟≈3μs(3个机器周期),符合8051手册描述
2. LED点亮时间=延时子程序执行时间,与代码计算值一致
3. 流水结束时P2.0回归低电平,证明CJNE判断准确
注意:若示波器显示脉冲宽度不稳定,检查Keil中晶振频率是否设为11.0592MHz。曾有学生因误设为12MHz,导致实测延时为12ms,与理论值偏差10%。
5. 常见问题与排查技巧实录
5.1 典型问题速查表与独家解决方案
| 问题现象 | 可能原因 | 排查步骤 | 解决方案 | 我的实操心得 |
|---|---|---|---|---|
| LED完全不亮 | 1. HEX文件未加载 2. P2口初始化错误 3. 限流电阻开路 | 1. 双击AT89C51确认“Program File”路径正确 2. 检查 2.asm中MOV P2, #0FFH是否被执行3. Proteus中右键R1~R8 → “Edit Properties” → 确认Resistance=220Ω | 重新编译工程,确保HEX生成;在MAIN开头加CLR P2.0测试单灯 | 初学者常忽略HEX加载路径,Proteus中路径显示为相对路径,务必确认文件存在 |
| 按键按下后LED只亮第一个,不流水 | 1. CJNE A, #01H, LOOP逻辑错误2. RL A/RR A指令未执行 | 1. 在Keil中全速运行,暂停后查看A寄存器值是否变化 2. 检查 JB B, REV_DIR是否跳转正确 | 在RL A后加NOP,用单步调试观察A值;确认B寄存器初始值 | 移位指令易被误认为无效,其实是因为未观察到A值在循环中变化,需耐心单步 |
| 流水灯闪烁异常快或慢 | 1. 晶振频率设置错误 2. 延时参数计算失误 | 1. 双击AT89C51 → “Clock Frequency”确认为11.0592MHz 2. 用计算器验证 20×250×2×1.085μs | 修改Keil工程中“Device”选项卡的晶振值;重算R6/R7 | 曾有学生在Proteus中把晶振设为1MHz,结果延时变成108ms,误以为代码错误 |
| 按键多次触发,流水灯重启 | 1. IT0设置为0(低电平触发) 2. 按键抖动未消隐 | 1. 检查2.asm中SETB IT0是否被注释2. 观察Proteus示波器Channel B波形宽度 | 恢复SETB IT0;或在硬件上加RC消抖电路(10kΩ+100nF) | 下降沿触发是教学首选,低电平触发仅用于特定场景,切勿混淆 |
| Keil编译报错“UNDEFINED SYMBOL” | 1. STARTUP.A51未添加2. SFR定义缺失 | 1. 查看“Project”窗口是否显示STARTUP.A512. 检查 2.asm开头是否有$NOLIST或$INCLUDE (REG51.INC) | 将STARTUP.A51拖入工程;在2.asm首行加$INCLUDE (REG51.INC) | REG51.INC是Keil自带的SFR定义文件,包含P0/P1/P2等符号,缺失则无法识别 |
5.2 那些教科书不会写的实战技巧
技巧1:用“断点+寄存器监视”秒杀逻辑错误
Keil调试时,在INT0_ISR开头设断点,按下按键后程序暂停。此时打开“Peripherals” → “I/O Ports” → “Port 2”,实时观察P2口各位状态。若A寄存器值正确但P2口无变化,说明MOV P2, A未执行——大概率是中断未真正进入(检查EA/EX0/IT0)。这个技巧比看代码快10倍。
技巧2:Proteus中“暂停-单步-运行”三连击定位时序
仿真中点击“Pause”,然后按F11单步执行,每步观察P2口变化。你会发现:RL A执行后A值变化,但P2口要等到下一条MOV P2, A才更新。这直观展示了“寄存器操作”与“I/O输出”的分离性,是理解CPU执行模型的关键一课。
技巧3:HEX文件反汇编验证编译结果
用记事本打开2.hex,可见类似:020000040000FA的ASCII行。用在线HEX转ASM工具(如hex2bin.org)上传,可反汇编出机器码对应的汇编指令。对比2.lst文件,确认SETB IT0确实编译为D2 88(机器码),证明配置生效。这是检验“所写即所得”的终极手段。
技巧4:快速切换正/反向流水的硬件捷径
在Proteus中,双击SW1 → “Edit Properties” → 将“Key”从空格改为‘S’。此后在仿真运行时,直接按键盘‘S’键即可触发中断,无需鼠标点击。配合方向修改,可实现“S键正向,D键反向”的交互演示,课堂效果极佳。
6. 项目延伸与教学应用建议
这个看似简单的流水灯,其实是嵌入式开发的微型训练场。我常把它作为“中断进阶三部曲”的第一步:第一步用本项目掌握中断基本流程;第二步在INT0_ISR中加入定时器0计数,实现“按键触发后流水持续5秒自动停止”;第三步扩展为双按键系统——SW1启动正向流水,SW2启动反向流水,用INT1实现并行中断处理。每一步都基于本项目代码微调,无需重学框架。
对于高校教师,建议在实验指导书中加入“故障注入”环节:故意将SETB EA删掉,让学生用示波器测量INT0引脚电平变化,却看不到P2口响应,从而深刻理解“总中断使能”是中断系统的总闸门。这种主动制造故障的教学法,比单纯演示有效得多。
最后分享一个个人体会:去年带毕业设计时,有学生用此项目为基础,给宿舍门锁加装了“按键唤醒流水指示”功能——夜间摸黑找钥匙孔时,轻按门把手上的触点,LED从上到下流水点亮门锁轮廓。他只改了两处:把P2口换成P1口(因P2被锁控芯片占用),延时调到500ms增强可视性。这个案例让我确信,扎实掌握中断底层逻辑的人,才能把技术真正用活。所以别嫌汇编麻烦,当你亲手写出RETI那一刻,你写的不是代码,是和硬件对话的语言。
简介:用8051单片机实现按键触发的LED流水灯,中断信号接INT0或INT1引脚,响应后从P2端口逐个点亮8颗LED,形成清晰可见的流动光效。包内含Keil完整工程(.uvproj、.asm、.uvopt等)、Proteus电路图(.DSN)、已编译好的HEX文件、启动代码STARTUP.A51,以及编译过程生成的列表文件(.lst、.m51、.lnp)和仿真运行截图(.jpg)。所有文件在Keil C51 v9.x和Proteus 7.8/8.x环境下实测通过,打开即用,无需额外配置。支持快速修改延时时间、流水方向(正向/反向)、中断触发方式(低电平或下降沿),方便用于课堂演示、汇编语言练习、中断原理理解,也能直接拓展为简易唤醒系统或状态指示模块。
2705

被折叠的 条评论
为什么被折叠?



