简单的汇编程序与周期性任务设计

文章介绍了使用8051单片机通过汇编语言实现周期性点亮和熄灭LED灯的两种方法,包括多重循环和查表法,以及延时函数的具体实现。随后讨论了如何调整延时函数以实现LED每1秒的亮灭周期,并给出了修改后的代码示例。
摘要由CSDN通过智能技术生成

周期性点亮LED灯的延时函数

1.通过软件多重循环软件计数的定时方法周期性点亮LED灯

ORG 0000H  ; 程序起始地址

MAIN:       ; 主程序标签
  SETB P1.0 ; 将P1.0设置为高电平,点亮LED
  ACALL DELAY ; 调用延时函数
  CLR P1.0  ; 将P1.0设置为低电平,熄灭LED
  ACALL DELAY ; 再次调用延时函数
  SJMP MAIN ; 无限循环

DELAY:     ; 延时函数标签
  MOV R0, #1  ; 外层循环计数器
OUTER_LOOP:
  MOV R1, #1   ; 内层循环计数器
INNER_LOOP:
  DJNZ R1, INNER_LOOP  ; 内层循环
  DJNZ R0, OUTER_LOOP  ; 外层循环
  RET                  ; 返回主程序

END

2.通过 循环+ nop 指令的方法

ORG 0000H

MAIN:

SETB P1.0

ACALL DELAY

CLR P1.0

ACALL DELAY

SJMP MAIN

DELAY:

MOV R0, #1

DELAY_LOOP: NOP ; 插入多个NOP指令来增加延时 NOP

NOP ; ...更多NOP指令...

DJNZ R0, DELAY_LOOP

RET

END

在edsim51上面仿真成功

使用汇编语言用查表法完成 求平方数的程序

ORG 0000H

; 平方数表
SQUARE_TABLE:
  DB 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225

; 主程序
MAIN:
  MOV A, #5  ; 假设我们要计算5的平方
  MOV R0, A  ; 将A的值移动到R0,用作表索引
  MOV DPTR, #SQUARE_TABLE ; 设置数据指针到平方数表
  MOVC A, @A+DPTR ; 查表得到平方数
  ; 此时,A寄存器中存储的是5的平方,即25
  ; ...其他代码...
  END

SETB 90H

LCALL DELAY

CLR 90H
LCALL DELAY
AJMP LOOP

DELAY:
MOV R7,#250
D1:MOV R6,#250
D2:DJNZ R7,D1


RET 
 END

汇编指令 “MOV R6,#250”和“DJNZ R6,D2”的指令周期数,计算其对应的时钟周期 us值;

对于指令 MOV R6,#250,这是一个2字节的指令,对于8051,它通常需要1个机器周期来执行,即12个时钟周期。

对于指令 DJNZ R6,D2,这是一个3字节的指令,通常需要2个机器周期来执行,即24个时钟周期。但是,当R6不为0时,它会跳转,这个跳转会增加额外的2个时钟周期,所以总共是26个时钟周期

现在,假设微控制器的时钟频率为12MHz,那么一个时钟周期的时间是 1/(12 * 10^6) 秒,或者大约 0.0833 微秒。

对于 MOV R6,#250 指令: 1 指令周期 * 12 时钟周期/指令周期 * 0.0833 微秒/时钟周期 = 1 微秒

对于 DJNZ R6,D2 指令: 26 时钟周期 * 0.0833 微秒/时钟周期 = 2.166 微秒

然后计算 Delay函数的总的循环次数和对应的时钟周期总数us, 说明这个LED灯大约每隔多少毫秒(ms)或秒(s)才变化一次亮灭状态

对于 DELAY 函数的总循环次数,有两个嵌套的循环,外层循环R7从250减到0,内层循环R6也是从250减到0。所以,总的循环次数是 250 * 250 = 62500。每次循环包括一个 MOV R6,#250 指令和250次 DJNZ R6,D2 指令。

总的时钟周期数是: (1 + 250 * 26) * 62500 * 0.0833 微秒 = 32687500 微秒 = 32.6875 秒

上述计算是基于单次 DELAY 函数调用的,但在程序中 DELAY 函数被调用了两次,一次用于LED开启的延时,一次用于LED关闭的延时。因此,LED灯的一次亮灭变化周期是两次 DELAY 函数调用的总和,即大约65.375秒。

要实现LED每隔1秒亮灭的周期性变化,需要根据实际的时钟频率调整延时循环的次数。如果我们假设时钟频率为12MHz,需要计算出使 DELAY 函数的延时大约为500毫秒的循环次数。

要求你实现准确的LED 每隔1s亮灭的周期性变化,上面程序如何修改?

ORG 0000h ; 程序起始地址

MAIN:

SETB P1.0 ; 将P1.0设置为高电位,点亮LED

ACALL DELAY_1S ; 调用1秒延时函数

CLR P1.0 ; 将P1.0设置为低电位,熄灭LED

SJMP MAIN ; 无限循环 ; 假设单片机的时钟频率为12MHz ; 1机器周期 = 12个时钟周期 = 1μs ; 假设每个循环迭代大约需要1μs

DELAY_1S:

MOV R1, #20 ; 外层循环计数器,假设大约为20次

OUTER_LOOP: MOV R2, #250 ; 内层循环计数器1,假设大约为250次

INNER_LOOP1: MOV R3, #250 ; 内层循环计数器2,假设大约为250次

INNER_LOOP2: NOP ; 执行一个空操作 (NOP) 以消耗时间

DJNZ R3, INNER_LOOP2 ; 循环直到R3为0

DJNZ R2, INNER_LOOP1 ; 循环直到R2为0

DJNZ R1, OUTER_LOOP ; 循环直到R1为0 RET ; 返回到调用DELAY_1S的地方

END ; 程序结束

在普中单片机开发板上重新完成上述实验

使用stc软件;

最终实验完成。

作者水平有限,不足之处欢迎指正。

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

珏决

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值