51单片机使LED灯闪烁和汇编程序查找平方数

一、主要任务

  1. 本篇文章的主要任务以周期性点亮LED灯的延时函数为例,掌握 1)通过软件多重循环软件计数的定时方法 ;2)通过 循环+ nop 指令的方法;

  2. 掌握汇编语言用查表法完成求平方数的程序;

  3. 掌握普中单片机实验开发板的开发使用方法,在板子上完成LED周期性点灯的C程序实验。

二、51单片机汇编延时函数分析

1. 周期

(1)单片机执行一条指令所需要的时间是一个指令周期。

(2)完成一个基本操作所用的时间是一个机器周期,如读操作、写等操作。当晶振频率为12MHz时,1个机器周期为1us。

2. 单重循环短暂延时

DJNZ RN,REL 是一条件转移指令,先将工作寄存器 Rn 中的数减 “ 1 ” ,判断结果是否为 “ 0 ”,不为 “ 0 ” 程序就跳转到行标为 REL 的地方执行,否则,为 “ 0 ” 就不转移,继续执行下一条指令。DJNZ 运行的机器周期为2。

如果需要短暂的延时,我们可以通过单重循环来实现。

例如,下面为延时250μs的程序。

DELAY:	
		MOV R7,#125      
DELAY1:	
		DJNZ R7,DELAY1	
		RET

MOV的指令周期为一个机器周期,即执行一条MOV指令需要1μs

DJNZ的指令周期为两个机器周期,即执行一条DJNZ指令需要2μs,每执行一次寄存器R7的值减 1 ,不断重复,到R7值为 0 的时候,跳转到 RET 指令结束,即执行 DJNZ 指令125次。

即可以实现延时大约250μs的目的。

3. 多重循环长延时

3.1 以实现LED周期性闪烁的汇编程序为例

LOOP:SETB 90H ;led0置1
	  LCALL DELAY ;调用延时函数
	  CLR 90H    ;led0置0
	  LCALL DELAY 
	  AJMP LOOP  ;跳转到LOOP
	  	
DELAY: MOV R7,#250 ;延时函数
D1:	   MOV R6,#250
D2:    DJNZ R6,D2
	   DJNZ R7,D1
	   RET  ;返回主函数
	   
END ;指令结束

延时函数中第一句是定义一个延时函数标号,并将250传到R7。

第二句是放置一个标号,并把250放到R6。“MOV R6,#250”的指令周期数为1个时钟周期,需要1μs。

第三句是放置一个标号,并判断R6的值是否为0,不为0的话转到后面标号对应处执行。“DJNZ R6,D2”的指令周期数为2个时钟周期,需要2μs。

而D2的标号也是第三条语句,因此只要R6不为0,则一直执行本条语句,又知R6=250,因此,这条语句将执行250次后结束。

第四句是先将R7减1 ,然后判断R7是否为0 ,不为0的话转到后面的标号对应处执行。标号D1,即第二句,执行第二句之后,又将执行第三句,执行250次后,再次执行语句四,如此循环即在第四句执行了250次后执行第五句,即结束函数。

第五句是函数结束。

共执行了:

第一句:1次;第二句:251次;第三句:250*250次;第四句:250次;第五句:1次

因此,此函数所用时间大约在第三条语句,时间为125000μs。

即这个LED灯大约每隔0.125s才变化一次亮灭状态。

3.2 实现LED 每隔1s亮灭的周期性变化

(1)通过软件多重循环软件计数的定时方法

此子程序采用3重循环结构。

LOOP:SETB 90H ;led0置1
	  LCALL DELAY ;调用延时函数
	  CLR 90H    ;led0置0
	  LCALL DELAY 
	  AJMP LOOP  ;跳转到LOOP
	  
DELAY: MOV R5,#20 
D1:	  MOV R6,#250
D2:   MOV R7,#100
      DJNZ R7,$
      DJNZ R6,D2
	  DJNZ R5,D1
	  RET 

由上述分析可知,为了计算上的简便,可以忽略赋值语句的时间,即只计算“DJNZ R7,$"语句的执行时间,该指令执行一次需2μs。执行的次数为R5、R6和R7值的乘积,即:

总延时=2μs x 20 x 250 x 10=1000000μs=1s

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

NOP指令

NOP指令是汇编语言中的一条空指令,通常用于延时或者在程序中占位。NOP指令本身不执行任何操作,只是让处理器执行一个空操作,不改变寄存器状态,也不影响程序流程。在大多数处理器架构中,NOP指令的执行时间非常短,通常只占用一个时钟周期。

在实际应用中,NOP指令可以用于以下几个方面:

延时:通过多次执行NOP指令来实现简单的延时效果。
占位:在程序中插入NOP指令,以便将来填充其他指令或代码。
调试:在调试过程中,可以在需要观察的地方插入NOP指令,以便暂停程序执行。

总的来说,NOP指令在汇编语言中是一个非常简单且常用的指令,虽然本身不执行任何有用的操作,但在某些情况下却具有一定的作用。

汇编程序:

DELAY: MOV R7,#250 ;延时函数
D1:	   MOV R6,#250
D2:   
       NOP
       ;此处需要有14个NOP指令
       DJNZ R6,D2
	   DJNZ R7,D1
	   RET  ;返回主函数
	   
END ;指令结束

由上述分析可知若不采用NOP的延时函数,只能延时0.125s,若想延时1s,NOP指令就额外需要延时大约875000μs,根据NOP所在位置,我们可知一个NOP指令就可以延时250 x 250 x 1=62500μs,所以需要NOP的个数为875000/62500=14

三、查表法查找平方数的汇编程序

1、汇编程序

ORG 0000H
       
LB:DB 0,1,4,9,16,25,36
 MOV DPTR,#LB
 MOV R1,#5 
 MOV A,R1
 MOVC A,@A+DPTR
 MOV R2,A
 RET
 END
这段汇编程序是一个简单的查表法来查找平方数的程序。下面是这段程序的逐行解释:

ORG 0000H: 程序起始地址为 0000H。
LB: DB 0,1,4,9,16,25,36: 定义了一个存储平方数的表 LB,包含了 0 到 6 的平方数。
MOV DPTR, #LB: 将表 LB 的起始地址加载到数据指针 DPTR 中。
MOV R1, #5: 将要查找的数 5 存储在寄存器 R1 中。
MOV A, R1: 将要查找的数 5 存储在累加器 A 中。
MOVC A, @A+DPTR: 使用 MOVC 指令,通过查表法找到索引为 5 的平方数,并将结果存储在累加器 A 中。
MOV R2, A: 将找到的平方数从累加器 A 复制到寄存器 R2 中。
RET: 程序结束并返回。
END: 程序结束。
这段程序的逻辑比较简单,首先将要查找的数存储在 R1 寄存器中,然后通过查表法在表 LB 中查找对应的平方数,并将结果存储在 R2 寄存器中。最后程序返回。

MOVC 指令是一种特殊的指令,用于将数据从表中移动到累加器 A 中。在指令 MOVC A, @A+DPTR 中,它的作用是从表中读取数据,并将其存储在累加器 A 中。

具体来说,@A+DPTR 的含义是将累加器 A 中的值作为偏移量,加上数据指针 DPTR 指向的地址,然后从该地址读取数据。在这个特定的情况下,累加器 A 中存储着一个偏移量,用来在表中查找对应的数据。

DB 指令是汇编语言中用来定义数据的伪指令。在汇编语言中,程序员通常需要定义一些常量、变量或者数据,DB 指令就是用来完成这个任务的。

DB 指令的全称是 “Define Byte”,它的作用是定义一个或多个字节的数据。在汇编程序中,可以使用 DB 指令来为程序中的变量分配空间,并初始化这些变量的值。

2、验证结果

Edsim51仿真验证

在这里插入图片描述

四、在普中单片机开发板完成LED灯周期性闪烁及流水灯

1、LED灯周期性闪烁

汇编程序

LOOP:SETB P2.0 
	  LCALL DELAY ;
	  CLR P2.0    
	  LCALL DELAY 
	  AJMP LOOP  ;
	  
DELAY: MOV R5,#20 
D1:	  MOV R6,#250
D2:   MOV R7,#100
      DJNZ R7,$
      DJNZ R6,D2
	  DJNZ R5,D1
	  RET 

注:开发板上只有P2口的LED灯,需要将接口改为接入P2

c语言程序

#include<reg51.h> 
sbit LED0=P2^0;
void Delay(unsigned int t); 
void main (void)
{
                 
while (1)         
  {
  LED0=0;            
  Delay(10000);      
                     
  LED0=1;           
  Delay(10000);
                     
  }
}	
void Delay(unsigned int t)
{
 while(--t);
}

在PZ-ISP软件中导入hex文件

在这里插入图片描述

结果:

在这里插入图片描述

2、流水灯

汇编程序

ORG 000H  

  LJMP MAIN  
  ORG 0030H
  MAIN:
  MOV A,#0FEH            
  LOOP:                 
  MOV P2,A               
                   
  LCALL DELAY
  RL A  
  SJMP LOOP 

  DELAY:
  MOV R7,#255
  D1:
  MOV R6,#250
  DJNZ R6,$
  DJNZ R7,D1
  RET

END

c语言程序

#include <reg51.h>
	#include <intrins.h>

	void delay_ms(int a)
	{
		int i,j;
		for(i=0;i<a;i++)
		{
			for(j=0;j<1000;j++) _nop_();
	
		}
	}
	
	void main(void)
	{
		while(1)
		{
			P2=0xfe;
			delay_ms(50);
			P2=0xfd;
			delay_ms(50);
			P2=0xfb;
			delay_ms(50);
			P2=0xf7;
			delay_ms(50);
			P2=0xef;
			delay_ms(50);
			P2=0xdf;
			delay_ms(50);
			P2=0xbf;
			delay_ms(50);
			P2=0x7f;
			delay_ms(50);
		}
	}

在这里插入图片描述

五、总结

本次任务让我学习到了更多关于汇编语言的知识,也对单片机开发板的应用有了初步的了解,文章也有不足的地方,希望大家多多包涵。

参考资料:
https://blog.csdn.net/xinzhiya001/article/details/55001751?spm=1001.2014.3001.5506

  • 29
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值