4.1 顺序程序设计
顺序程序是按照指令编写顺序逐条执行的程序结构,无分支、循环等控制逻辑。其核心是利用基本指令实现数据处理。
基本指令应用
- 数据传送(MOV、MOVX、MOVC)
- 算术运算(ADD、SUBB、INC)
- 逻辑运算(ANL、ORL、XRL)
伪指令支持
- ORG(指定程序起始地址)
- EQU(符号定义)
- DATA(数据地址赋值)
典型场景
- 简单数据处理
- 初始化设置
- I/O端口直接操作
示例代码:点亮LED并延时
ORG 0000H
MOV P2, #0FEH ; 点亮第一个LED
MOV R7, #20 ; 延时参数
DELAY:
DJNZ R7, DELAY ; 循环延时
SJMP $ ; 程序暂停
END
4.2 分支程序设计
通过条件判断实现程序流向控制,分为单分支、多分支结构。
条件转移指令
- CJNE(比较转移)
- JZ(判零转移)
- JB(判位转移)
多分支实现
- 使用散转程序(JMP @A+DPTR)
- 结合数据表格实现多路分支
设计要点
- 条件判断逻辑清晰
- 避免分支嵌套过深
示例代码:根据数值点亮不同LED
CJNE A, #10, NEXT ; 比较A与10
MOV P2, #0FFH ; 相等时全灭
SJMP END
NEXT:
JNC HIGH ; A>10则跳转
MOV P2, #0FEH ; A<10点亮第一个LED
SJMP END
HIGH:
MOV P2, #01H ; A>10点亮最后一个LED
END:
SJMP END
要点提示
分支程序设计的关键是合理使用条件转移指令,确保每个分支都有明确的出口,避免程序陷入死循环。
4.3 循环程序设计
通过循环结构重复执行某段程序,分为计数循环和条件循环。
循环三要素
- 初始化
- 循环体
- 循环控制(DJNZ、CJNE等)
典型应用
- 延时程序
- 数据块处理
- 查表遍历
注意事项
- 避免死循环
- 合理分配寄存器资源
示例代码:数据块求和
MOV R0, #30H ; 数据块起始地址
MOV R7, #10 ; 数据长度
CLR A ; 累加器清零
LOOP:
ADD A, @R0 ; 累加数据
INC R0 ; 指针后移
DJNZ R7, LOOP ; 未完成继续循环
MOV 40H, A ; 保存结果
技巧提示
循环程序设计时,应先初始化循环变量和指针,然后在循环体中更新这些变量,最后进行循环条件判断。
4.4 查表程序设计
通过查表指令(MOVC)快速获取预存数据,适用于非线性运算或固定参数访问。
查表方式
- 直接查表(表格起始地址固定)
- 变址查表(通过DPTR+A定位)
表格定义
- DB(定义字节)
- DW(定义字)
应用场景
- LED段码转换
- 温度补偿
- 代码转换
示例代码:数码管段码查表
MOV DPTR, #SEG_TAB ; 段码表首地址
MOV A, R2 ; 待转换数据
MOVC A, @A+DPTR ; 查表
MOV P0, A ; 输出显示
SEG_TAB:
DB 0C0H, 0F9H, 0A4H, 0B0H ; 0-3的段码
应用示例
查表程序广泛应用于LED数码管显示、LCD字符显示、传感器数据校准等场景,可以大大简化程序逻辑。
4.5 子程序设计和参数传递
将重复使用的代码模块化,通过调用指令(ACALL、LCALL)实现复用。
子程序结构
- 入口参数处理
- 功能实现
- 出口参数返回
- 现场保护
参数传递方法
- 寄存器传递:利用R0-R7传递数据
- 内存传递:通过固定地址单元交换数据
- 堆栈传递:使用PUSH/POP指令压栈出栈
注意事项
- 堆栈深度计算避免溢出
- 子程序嵌套不超过3层
示例代码:数据乘法子程序
MAIN:
MOV R0, #50H ; 入口参数地址
LCALL SUM ; 调用求和子程序
SJMP $
SUM:
PUSH ACC ; 保护现场
PUSH B
MOV A, @R0
MOV B, #10
MUL AB ; 计算50H单元数据×10
POP B ; 恢复现场
POP ACC
RET
要点提示
子程序设计时,应注意现场保护和恢复,确保子程序执行后不影响主程序的运行环境。参数传递方式应根据实际需求选择。
4.6 程序设计实例
综合应用多种程序设计方法实现具体功能。
实例1:LED流水灯(查表法)
ORG 0000H
MOV DPTR, #LED_TAB ; 流水灯模式表
MOV R2, #0 ; 初始偏移量
LOOP:
MOV A, R2
MOVC A, @A+DPTR ; 查表
MOV P2, A
LCALL DELAY ; 调用延时子程序
INC R2
CJNE R2, #8, LOOP ; 循环8次
SJMP LOOP
LED_TAB:
DB 0FEH, 0FDH, 0FBH, 0F7H ; 流水灯模式
DB 0EFH, 0DFH, 0BFH, 7FH
DELAY:
MOV R7, #20 ; 延时子程序
D1: MOV R6, #250
D2: DJNZ R6, D2
DJNZ R7, D1
RET
END
程序功能
控制8个LED循环点亮,形成流水灯效果。
技术要点
- 查表法实现多种显示模式
- 子程序实现延时控制
- 循环结构实现重复显示
实例2:按键控制数码管显示
ORG 0000H
MOV P1, #0FFH ; 初始化按键端口
MOV 30H, #0 ; 显示数值初始化为0
LOOP:
JB P1.0, DISP ; 检测按键是否按下
ACALL DELAY ; 消抖
JB P1.0, DISP
INC 30H ; 数值加1
CJNE 30H, #10, DISP
MOV 30H, #0
DISP:
MOV A, 30H
MOV DPTR, #SEG_TAB
MOVC A, @A+DPTR
MOV P0, A
SJMP LOOP
SEG_TAB:
DB 0C0H, 0F9H, 0A4H, 0B0H ; 0-3的段码
DB 099H, 092H, 082H, 0F8H ; 4-7的段码
DB 080H, 090H ; 8-9的段码
END
程序功能
通过按键调整数码管显示的数字(0-9循环)。
技术要点
- 按键检测与消抖处理
- 分支结构实现数值循环
- 查表法实现数码管段码转换