位置:首页 > 其他编程语言 > 51单片机汇编程序实例 流水灯与中断代码

51单片机汇编程序实例 流水灯与中断代码

时间:2026-08-21  |  作者:清风无痕  |  阅读:0

本文通过延时、流水灯、定时器中断和数据累加等常见实例,说明51单片机汇编程序的基本结构、寄存器使用方法与调试要点。示例采用典型指令编写,便于理解程序执行流程,并可根据实际晶振频率和硬件连接进行调整。

汇编程序的基本结构

51单片机汇编程序通常由复位入口、初始化代码、主循环、功能子程序和中断服务程序组成。ORG用于指定代码存放地址,LJMP可在复位后跳转到主程序,END表示源程序结束。编写时应先确定端口连接、有效电平、定时器工作方式和存储单元用途,再安排循环与中断逻辑。调用子程序使用ACALL或LCALL,子程序结束必须执行RET;中断服务程序则应使用RETI返回。

  • ORG 0000H,设置复位入口地址
  • LJMP MAIN,跳转到主程序
  • MAIN: MOV SP,#60H,初始化堆栈指针
  • MAIN_LOOP: SJMP MAIN_LOOP,进入明确标注的主循环等待位置
  • END,结束汇编源程序

软件延时程序实例

下面给出一份可独立汇编的软件延时示例,适用于标准8051指令集和Keil A51语法,目标芯片可选AT89C51,晶振频率为12MHz。P1.0连接低电平点亮的LED,主程序每次翻转端口后调用双重循环延时。软件延时适合对时间精度要求不高的指示灯闪烁等场景,实际时间还会受到指令周期和调用开销影响;若需要稳定周期,应优先采用定时器。

  • ORG 0000H LJMP MAIN

    ORG 0030H
    MAIN:
        MOV SP,#60H
        SETB P1.0
    DELAY_LOOP:
        CPL P1.0
        ACALL DELAY
        SJMP DELAY_LOOP
    
    DELAY:
        MOV R6,#200
    D1:
        MOV R7,#250
    D2:
        DJNZ R7,D2
        DJNZ R6,D1
        RET

    END

流水灯程序实例

下面给出一份可独立汇编的流水灯程序,采用AT89C51、Keil A51语法和12MHz晶振。八个LED分别连接P1.0至P1.7,并按低电平点亮方式工作。程序将仅有一位为低电平的数据送到P1口,调用延时子程序后通过RL指令循环移动点亮位置;若硬件采用高电平点亮,应调整初始数据和驱动逻辑。

  • ORG 0000H LJMP MAIN

    ORG 0030H
    MAIN:
        MOV SP,#60H
        MOV A,#0FEH
    FLOW_LOOP:
        MOV P1,A
        ACALL DELAY
        RL A
        SJMP FLOW_LOOP
    
    DELAY:
        MOV R6,#200
    FLOW_D1:
        MOV R7,#250
    FLOW_D2:
        DJNZ R7,FLOW_D2
        DJNZ R6,FLOW_D1
        RET

    END

定时器中断程序实例

下面给出一份可独立汇编的定时器0中断程序,采用AT89C51、Keil A51语法、12MHz晶振和传统12时钟内核。定时器0工作于方式1,每个机器周期为1微秒,初值FC18H对应1000次计数,即约1毫秒中断一次。P1.0连接低电平点亮的LED,每次中断翻转一次,因此端口方波周期约为2毫秒。复位入口位于0000H,定时器0中断向量000BH处只跳转到服务程序;初始化代码位于MAIN,服务程序先重新装载TH0和TL0,再执行周期任务。该服务程序仅改写TH0、TL0和P1.0,不使用A、B、DPTR、PSW或工作寄存器,因此无需额外压栈;若扩展服务程序并使用累加器或改变PSW,应在入口执行PUSH ACC、PUSH PSW,并在返回前按相反顺序执行POP PSW、POP ACC。对于1T内核或其他晶振频率,必须按芯片手册重新计算初值。

  • ORG 0000H LJMP MAIN

    ORG 000BH LJMP TIMER0_ISR

    ORG 0030H
    MAIN:
        MOV SP,#60H
        SETB P1.0
        MOV TMOD,#01H
        MOV TH0,#0FCH
        MOV TL0,#018H
        SETB ET0
        SETB EA
        SETB TR0
    MAIN_LOOP:
        SJMP MAIN_LOOP
    
    TIMER0_ISR:
        MOV TH0,#0FCH
        MOV TL0,#018H
        CPL P1.0
        RETI

    END

数据累加程序实例

寄存器间接寻址适合处理连续存储的数据。假设内部RAM中30H至39H保存十个八位无符号数,可用R0作为地址指针、R2作为循环计数器,并将累加结果保存在A中。此示例只保留八位结果;如果总和可能超过255,还需要检测进位并保存高字节。

  • MOV R0,#30H,指向首个数据单元
  • MOV R2,#10,设置数据数量
  • CLR A,清除累加器
  • SUM: ADD A,@R0,累加当前数据
  • INC R0,指向下一个数据
  • DJNZ R2,SUM,循环处理十个数据
  • MOV 40H,A,将八位结果保存到40H

编译与调试要点

调试时应先检查目标芯片型号、汇编器语法、晶振频率、内核机器周期和端口连接,再通过单步运行观察A、PSW、SP以及相关寄存器的变化。使用中断时要确认向量地址没有被其他代码占用,并逐项列出服务程序会修改的寄存器;服务程序若修改了主程序依赖的ACC、PSW或工作寄存器,应先压栈保护并在返回前逆序恢复。端口现象与预期相反时,还应核对外围电路的有效电平。

  • 确认芯片型号、汇编器语法、晶振频率和机器周期与示例一致
  • 确认主程序和各中断入口地址没有冲突
  • 检查子程序中的RET与中断程序中的RETI是否正确
  • 列出中断服务程序修改的寄存器,并对主程序依赖的寄存器进行压栈保护
  • 通过汇编器编译、仿真波形或端口实测验证运行周期

掌握程序入口、循环、子程序和中断这几类结构后,便可将实例组合成按键控制、数码管显示等完整功能。实际应用中应结合芯片手册核对寄存器定义,并以硬件测试结果修正时序参数。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多