51汇编仿真proteus8.15学习篇一(附源码)

文章目录


一、 前言

汇编语言是二进制指令的文本形式,与指令是一一对应的关系。比如,加法指令00000011写成汇编语言就是 ADD。只要还原成二进制,汇编语言就可以被 CPU 直接执行,所以它是最底层的低级语言。

最近对汇编的仿真产生兴趣,虽然尚未系统学习,但搜集了一些资料尝试实践。学习汇编有助于更深入理解硬件工作原理,顺带记录一下学习过程,也欢迎交流指正。


二、 仿真

1.001-灯闪烁

/*

001-灯闪烁

LED 以约 0.2 秒亮、0.2 秒灭的频率闪烁,总周期约为 0.4 秒。

*/

1.1 电路仿真

2.1 仿真程序

c 复制代码
/*
001-灯闪烁
LED 以约 0.2 秒亮、0.2 秒灭的频率闪烁,总周期约为 0.4 秒。
*/

ORG 0           ; ORG 0: 告诉编译器,程序从程序存储器(ROM)的地址 0 开始存放。
                ; 单片机复位后,程序计数器(PC)从 0 地址开始执行。

START: CLR P1.0 ; START: 标号,表示程序循环的起点。
                ; CLR P1.0: 清除 P1.0 引脚,即将其设置为低电平 (0V)。如果 LED 阴极接 P1.0,阳极接 VCC,则此时 LED 会亮。

LCALL DELAY     ; LCALL: 长调用指令。调用位于 DELAY 标号处的延时子程序。
                ; 执行这条指令后,程序会跳转到 DELAY 子程序,执行完后再返回到这里。

SETB P1.0       ; SETB P1.0: 置位 P1.0 引脚,即将其设置为高电平 (5V)。此时 LED 会熄灭。

LCALL DELAY     ; 再次调用延时子程序,使 LED 熄灭状态保持一段时间。

LJMP START      ; LJMP: 长跳转指令。无条件跳转回 START 标号处。
                ; 这将形成一个无限循环:亮 -> 延时 -> 灭 -> 延时 -> 亮 ... 从而实现 LED 闪烁。

; ===== 延时子程序 DELAY =====
DELAY: MOV R5, #20  ; DELAY: 子程序入口标号。
                    ; MOV R5, #20: 将立即数 20 送入寄存器 R5。这是外层循环计数器。
D1: MOV R6, #20     ; D1: 中层循环标号。将立即数 20 送入寄存器 R6。这是中层循环计数器。
D2: MOV R7, #248    ; D2: 内层循环标号。将立即数 248 送入寄存器 R7。这是内层循环计数器。
    DJNZ R7, $      ; DJNZ R7, $: 寄存器 R7 减 1,如果不为 0,则跳转到当前地址('$' 表示当前地址)。
                    ; 这条指令会执行 248 次,产生一个短暂的延时。
    DJNZ R6, D2     ; 寄存器 R6 减 1,如果 R6 不为 0,则跳转回 D2 标号,重新初始化 R7 并循环。
                    ; 该指令执行 20 次,所以内层循环(R7循环)总共执行 20 * 248 次。
    DJNZ R5, D1     ; 寄存器 R5 减 1,如果 R5 不为 0,则跳转回 D1 标号,重新初始化 R6 并循环。
                    ; 该指令执行 20 次,所以中层循环(R6循环)总共执行 20 * 20 * 248 次。
RET                 ; RET: 子程序返回指令。返回到 LCALL DELAY 的下一条指令继续执行。
                    ; 整个延时子程序通过三层嵌套循环来消耗 CPU 时间,实现延时效果。

END                 ; END: 汇编结束指令,告诉编译器程序到此为止。

2.002-模拟开关灯

/*

002-模拟开关灯

查询式按键检测程序,按键按下→ LED 亮,按键释放→ LED 灭。

*/

2.1 电路仿真

2.2 仿真程序

c 复制代码
/*
002-模拟开关灯
查询式按键检测程序,按键按下→ LED 亮,按键释放→ LED 灭。
*/

ORG 0           ; 程序起始地址为 0(通常省略,因为默认从 0 开始)

START: JB P3.0, LIG  ; START: 程序主循环的起点
                     ; JB P3.0, LIG: 判断 P3.0 引脚的电平
                     ; - 如果 P3.0 为高电平 (1),则跳转到 LIG 标号处执行
                     ; - 如果 P3.0 为低电平 (0),则顺序执行下一条指令

CLR P1.0        ; 将 P1.0 引脚设置为低电平 (0V)
                ; 如果 P1.0 接LED(阴极接P1.0,阳极接VCC),则LED亮

SJMP START      ; 短跳转回 START 标号,形成循环,继续检测 P3.0 的状态

LIG: SETB P1.0  ; LIG: 标号(可能是 "LIGHT" 的缩写)
                ; SETB P1.0: 将 P1.0 引脚设置为高电平 (5V)
                ; 此时 LED 熄灭

SJMP START      ; 短跳转回 START 标号,形成循环,继续检测 P3.0 的状态

END             ; 程序结束标志

3.003-多路开关状态指示

/*

003-多路开关状态指示

这是一个4路独立的开关控制程序,

输入引脚(检测端) 输出引脚(控制端)

P1.4 (按键) → P1.0 (LED)

P1.5 (按键) → P1.1 (LED)

P1.6 (按键) → P1.2 (LED)

P1.7 (按键) → P1.3 (LED)

*/

3.1 电路仿真

3.2 仿真程序

c 复制代码
/*
003-多路开关状态指示
这是一个4路独立的开关控制程序,
输入引脚(检测端)   输出引脚(控制端)
P1.4 (按键) → P1.0 (LED)
P1.5 (按键) → P1.1 (LED)  
P1.6 (按键) → P1.2 (LED)
P1.7 (按键) → P1.3 (LED)
*/

ORG 00H         ; 程序从地址 00H 开始执行

; ===== 检测 P1.4,控制 P1.0 =====
START: JB P1.4, NEXT1  ; 判断 P1.4 引脚电平
                       ; 如果 P1.4 = 1(高电平),跳转到 NEXT1
                       ; 如果 P1.4 = 0(低电平),顺序执行
CLR P1.0               ; 将 P1.0 设置为低电平 (0V)
SJMP NEX1              ; 跳转到 NEX1,跳过下面的 SETB 指令
NEXT1: SETB P1.0       ; 将 P1.0 设置为高电平 (5V)
NEX1:                  ; 第一个检测控制段的结束标号

; ===== 检测 P1.5,控制 P1.1 =====
JB P1.5, NEXT2         ; 判断 P1.5 引脚电平
                       ; 如果 P1.5 = 1,跳转到 NEXT2
                       ; 如果 P1.5 = 0,顺序执行
CLR P1.1               ; 将 P1.1 设置为低电平
SJMP NEX2              ; 跳转到 NEX2
NEXT2: SETB P1.1       ; 将 P1.1 设置为高电平
NEX2:                  ; 第二个检测控制段的结束标号

; ===== 检测 P1.6,控制 P1.2 =====
JB P1.6, NEXT3         ; 判断 P1.6 引脚电平
                       ; 如果 P1.6 = 1,跳转到 NEXT3
                       ; 如果 P1.6 = 0,顺序执行
CLR P1.2               ; 将 P1.2 设置为低电平
SJMP NEX3              ; 跳转到 NEX3
NEXT3: SETB P1.2       ; 将 P1.2 设置为高电平
NEX3:                  ; 第三个检测控制段的结束标号

; ===== 检测 P1.7,控制 P1.3 =====
JB P1.7, NEXT4         ; 判断 P1.7 引脚电平
                       ; 如果 P1.7 = 1,跳转到 NEXT4
                       ; 如果 P1.7 = 0,顺序执行
CLR P1.3               ; 将 P1.3 设置为低电平
SJMP NEX4              ; 跳转到 NEX4
NEXT4: SETB P1.3       ; 将 P1.3 设置为高电平
NEX4:                  ; 第四个检测控制段的结束标号

SJMP START             ; 跳转回 START,形成无限循环,持续检测和控制

END                   ; 程序结束

4.004-广告灯的左移右移

/*

004-广告灯的左移右移

流水灯,

LED灯会以0.2秒的间隔依次点亮,形成从左到右、再从右到左的来回扫描效果,类似于跑马灯灯效。

*/

4.1 电路仿真

4.2 仿真程序

c 复制代码
/*
004-广告灯的左移右移
流水灯,
LED灯会以0.2秒的间隔依次点亮,形成从左到右、再从右到左的来回扫描效果,类似于跑马灯灯效。
*/

ORG 0           ; 程序从地址0开始执行

START: MOV R2, #8      ; 设置循环计数器R2=8,控制8个LED的移动次数
       MOV A, #0FEH    ; 将初始值0FEH(1111 1110B)送入累加器A
                       ; 最低位为0,对应P1.0引脚为低电平,第一个LED亮
       SETB C          ; 将进位标志C置1,为后面的循环移位做准备

; ===== 从左到右的流水灯效果 =====
LOOP: MOV P1, A        ; 将累加器A的值输出到P1端口,控制LED显示
      LCALL DELAY      ; 调用延时子程序,保持当前显示状态一段时间
      
      RLC A           ; 带进位循环左移(Rotate Left through Carry)
                      ; 例如:A=1111 1110, C=1 → 左移后:A=1111 1101, C=1
                      ; 这样0的位置会向左移动,实现LED从左到右移动的效果
      
      DJNZ R2, LOOP    ; R2减1,如果不为0则跳转回LOOP继续循环
                      ; 共循环8次,完成8个LED的依次点亮

; ===== 从右到左的流水灯效果 =====
      MOV R2, #7      ; 重新设置循环计数器R2=7
	  
LOOP1: 
    RRC A              ; 先右移,再显示
    MOV P1, A          ; 将累加器A的值输出到P1端口
    LCALL DELAY        ; 调用延时子程序
    DJNZ R2, LOOP1     ; 循环7次
    
    LJMP START         ; 跳转回START,重新开始流水灯效果,形成无限循环	  	  

; ===== 延时子程序 DELAY =====
DELAY: MOV R5, #20     ; 外层循环计数器R5=20
D1:    MOV R6, #20     ; 中层循环计数器R6=20
D2:    MOV R7, #248    ; 内层循环计数器R7=248
       DJNZ R7, $      ; R7减1,不为0则跳转到当前地址($),形成短暂延时
       DJNZ R6, D2     ; R6减1,不为0则跳转到D2
       DJNZ R5, D1     ; R5减1,不为0则跳转到D1
       RET             ; 返回主程序

END                   ; 程序结束

5.005-广告灯(利用取表方式)

/*

005-广告灯(利用取表方式)

一个典型的多模式LED灯效控制器程序,通过查表法实现了复杂的显示效果。

LED会依次显示:

从左到右流水灯 × 2次

从右到左流水灯 × 2次

全亮全灭闪烁 × 2次

重复以上序列

*/

5.1 电路仿真

5.2 仿真程序

c 复制代码
/*
005-广告灯(利用取表方式)
一个典型的多模式LED灯效控制器程序,通过查表法实现了复杂的显示效果。
LED会依次显示:
从左到右流水灯 × 2次
从右到左流水灯 × 2次
全亮全灭闪烁 × 2次
重复以上序列
*/

ORG 0           ; 程序从地址0开始执行

START: MOV DPTR, #TABLE  ; 将数据指针DPTR指向TABLE表的起始地址

; ===== 主循环:读取表数据并控制LED =====
LOOP: CLR A              ; 清空累加器A(A=0)
      MOVC A, @A+DPTR    ; 查表指令:从程序存储器读取数据
                         ; 地址 = DPTR + A,即读取TABLE中的当前数据到A
      
      CJNE A, #01H, LOOP1 ; 比较A是否等于01H
                         ; 如果不等于01H,跳转到LOOP1
                         ; 如果等于01H,顺序执行(表示遇到结束标志)
      
      JMP START          ; 跳回START,重新开始循环(从头播放灯效)

LOOP1: MOV P1, A         ; 将表数据输出到P1端口,控制LED显示
      MOV R3, #20        ; 设置延时循环计数器R3=20
      LCALL DELAY        ; 调用延时子程序
      
      INC DPTR           ; 数据指针加1,指向下一个表数据
      JMP LOOP           ; 跳回LOOP,继续读取下一个数据

; ===== 延时子程序 =====
DELAY: MOV R4, #20       ; 中层循环计数器R4=20
D1:    MOV R5, #248      ; 内层循环计数器R5=248
       DJNZ R5, $        ; R5减1,不为0则跳转到当前地址(短暂延时)
       DJNZ R4, D1       ; R4减1,不为0则跳转到D1
       DJNZ R3, DELAY    ; R3减1,不为0则跳转回DELAY(外层循环)
       RET               ; 返回主程序

; ===== LED灯效数据表 =====
TABLE: 
; 模式1:从左到右流水灯(2次)
DB 0FEH,0FDH,0FBH,0F7H  ; 1111 1110, 1111 1101, 1111 1011, 1111 0111
DB 0EFH,0DFH,0BFH,07FH  ; 1110 1111, 1101 1111, 1011 1111, 0111 1111
DB 0FEH,0FDH,0FBH,0F7H  ; 重复一次
DB 0EFH,0DFH,0BFH,07FH

; 模式2:从右到左流水灯(2次)  
DB 07FH,0BFH,0DFH,0EFH  ; 0111 1111, 1011 1111, 1101 1111, 1110 1111
DB 0F7H,0FBH,0FDH,0FEH  ; 1111 0111, 1111 1011, 1111 1101, 1111 1110
DB 07FH,0BFH,0DFH,0EFH  ; 重复一次
DB 0F7H,0FBH,0FDH,0FEH

; 模式3:全亮全灭闪烁(2次)
DB 00H, 0FFH,00H, 0FFH  ; 0000 0000(全亮), 1111 1111(全灭), 全亮, 全灭

; 结束标志
DB 01H                  ; 结束标志,遇到01H就重新开始

END                   ; 程序结束

三、总结

今天通过几个简单的51汇编仿真,我们亲眼看到了代码如何驱动硬件。算是为"更深层次了解单片机工作原理"这个目标迈出了一小步。感谢观看,后续继续分享!

再次感谢你的观看!

相关推荐
乐茵lin2 小时前
golang中 Context的四大用法
开发语言·后端·学习·golang·编程·大学生·context
山土成旧客2 小时前
【Python学习打卡-Day26】函数的艺术(上):从基础定义到参数魔法
开发语言·python·学习
Coder_Boy_2 小时前
【人工智能应用技术】-基础实战-小程序应用(基于springAI+百度语音技术)智能语音控制-Java部分核心逻辑
java·开发语言·人工智能·单片机
车载测试工程师2 小时前
CAPL学习-AVB交互层-媒体函数1-回调&基本函数
网络·学习·tcp/ip·媒体·capl·canoe
richxu202510012 小时前
嵌入式学习之路-->stm32篇-->(0)学习路线
stm32·嵌入式硬件·学习
xiaobuding_QAQ2 小时前
51汇编仿真proteus8.15学习篇二(附源码)
开发语言·汇编·单片机·学习·proteus
黑客思维者2 小时前
机器学习015:监督学习【分类算法】( 决策树)-- 像玩“20个问题”游戏一样做决策
学习·机器学习·分类
Larry_Yanan11 小时前
Qt多进程(一)进程间通信概括
开发语言·c++·qt·学习
做cv的小昊12 小时前
【TJU】信息检索与分析课程笔记和练习(1)认识文献
经验分享·笔记·学习·搜索引擎·全文检索