使用汇编语言实现周期性点亮LED灯并在开发板上实现


一、时钟周期与机器周期

         时钟周期:也称为振荡周期,定义为时钟脉冲的倒数(时钟周期就是单片机外接晶振的倒数,例如12M的晶振,它的时钟周期就是1/12us),是计算机中的最基本的、最小的时间单位。在一个时钟周期内,CPU仅完成一个最基本的动作。时钟脉冲是计算机的基本工作脉冲,控制着计算机的工作节奏。时钟频率越高,工作速度就越快。  

         机器周期:计算机中,常把一条指令的执行过程划分为若干个阶段,每一个阶段完成一项工作(例如,取指令、存储器读、存储器写等)。每一项工作称为一个基本操作,完成一个基本操作所需要的时间称为机器周期。它一般由12个时钟周期(振荡周期)组成,即由6个状态周期组成,而振荡周期=1/晶振频率,因此单片机的机器周期=12/晶振频率

        8051系列单片机中:1个机器周期=6个状态周期=12个振荡周期(即时钟周期)

二、通过软件多重循环软件计数的定时方法

1.双重循环法

        在使用12MHz的晶振时,51单片机的时钟周期是1/12微秒,一个机器周期就是1微秒,我们使用循环时要用DJNZ语句,而实现一个DJNZ语句需要2微秒。通常我们实现延时函数是采用双循环,如果我们用C语言写就是两个空的for循环,这里我们主要用汇编语言实现。

MOV R7,#250;//R7赋值为250
 D1:MOV R6,#250;
 D2:DJNZ R6,D2;//若R6-1不等于0,则继续执行D2
 DJNZ R7,D1;

总循环次数:250*250=62500,总循环时间:(2*250)*0.001*250= 125毫秒

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

         因为我们的单片机是8字节,一个寄存器最多能运行256个字节,,因此我们的R5,R6,R7的数值不能大于256。为了实现LED 每隔1s亮灭的周期性变化,我们必须要使用三个循环。

具体代码如下:

LOOP:
SETB  90H;//LED置1
LCALL DELAY;//调用延时函数
CLR 90H;//LED置0
LCALL DELAY;//调用延时函数
AJMP LOOP;//主体循环

DELAY:
MOV R5,#10;//R5赋值为10
 D1:MOV R7,#200;
 D2:MOV R6,#250;
 D3:DJNZ R6,D3;//若R6-1不等于0,则继续执行D3
 DJNZ R7,D2;
 DJNZ R5,D1;
RET;//返回函数
END

 D3:DJNZ R6,D3:指R6中的数减一后不等于0,则需循环执行D3步骤。

 DJNZ R7,D2:当R6中的数为0后再执行此步,R7中的数减一若不为0,则需要跳转回D2执行

DJNZ R5,D1:当R7中的数为0后再执行此步,R5中的数减一若不为0,则需要跳转回D1执行

        根据上面分析我们可以得出当R7减一时,R6需要减250次,R5减一时,R7需要减200次,因此整个循环的次数为250*200*10=500000次,而它的运行时间为250*2*200*2*10=1ms。当然对于整个程序的运行来说,我们求的次数是不精确的,我们除了要计算DJNZ语句执行的次数,还要计算每次循环执行的MOV语句执行的次数,因此,总的次数是要多于上面计算的次数的。与此相对应的运行时间也会有相应的偏差。

3.NOP指令

NOP指令在汇编中的作用是空指令,意味着什么都不做,一般用来控制CPU时间,达到时钟延时的效果。

NOP指令为单周期指令,可由晶振频率计算出延时时间,对于12M晶振,延时1μs。

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

查表就是根据自变量x,在表格中寻找y,使y=f(x).

查找1-9的平方代码如下:

ORG 0000H
LJMP A1
ORG 0080H
A1: NOP
    NOP
    MOV SP,#60H
	MOV DPTR,#2000H
	MOV A,#03H
	MOVC A,@A+DPTR
A2: SJMP A2
	ORG 2000H
	DB 00h,01h,04h,09h,10h,19h,24h,31h,40h,51h
END

 MOVC A,@A+DPTR:完成A中的内容作为一个无符号数与DPTR中的内容相加,所得结果为某一程序存储单元的地址,然后把该地址单元中的内容送到累加器A中。使用该指令时不必计算偏移量,表格可以设在64K程序储存空间内的任何地方。

四、在普中单片机开发板上完成LED灯的点亮和闪烁

1.单片机GPIO介绍

        GPIO(general purpose intput output)是通用输入输出端口的简称,可以通过软件来控制其输入和输出。51 单片机芯片的 GPIO 引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。不过 GPIO 最简单的应用还属点亮 LED 灯了,只需通过软件控制 GPIO 输出高低电平即可。当然 GPIO还可以作为输入控制,比如在引脚上接入一个按键,通过电平的高低判断按键是否按下。

        我所用的芯片是STC89C52,此芯片有40个引脚,具体每个引脚的作用可以查询芯片手册。

2.点亮一个LED灯

(1)在edsim51和proteus里面仿真

        edsim51的原理图中LED灯是在P1端口采用共阳极接法,因此编程时需要将P1端口赋值为低电平,代码如下:

#include<mcs51/8051.h>
void main()
{
while(1){
P1=0b11111110;
}
}

效果图如下: 

        proteus参照的是开发板,因此是将P2口赋值为低电平,代码只需要将P1改为P2即可,效果图如下: 

 

(2)开发板上点亮LED灯

开发板原理图如下:

         根据原理图我们可知开发板的LED灯接在P2端口,而LED灯采用的是共阳极接法,因此只需要将P2端口赋值为低电平就可以点亮相应的LED灯。代码如下:

#include "reg52.h"

sbit LED1=P2^0;	
void main()
{
	LED1=0;	
	while(1)
	{
		
	}		
}

         将程序烧录进开发板需要下载PZ-ISP软件,以及CH340驱动(下载时需要用USB将电脑和开发板连接起来。

在Keil C51中生成.hex文件,然后通过PZ-ISP软件烧录进开发板,效果如下:

3.LED灯闪烁

(1)edsim51和proteus仿真

汇编语言代码参考上文中的LED灯周期性变化代码,C语言则使在点亮灯的基础上添加延时函数,然后控制灯亮灯灭。效果图如下:
edsim51中LED闪烁-CSDN直播

proteus闪烁-CSDN直播

(2)在开发板上使LED灯闪烁

#include "reg52.h"

typedef unsigned int u16;	//对系统默认数据类型进行重定义
typedef unsigned char u8;

sbit LED1=P2^0;	//将P2.0定义为LED1


//定义延时函数
void delay_10us(u16 ten_us)
{
	while(ten_us--);	
}


void main()
{	
	while(1)
	{
		LED1=0;	//灯亮
		delay_10us(50000); //调用延时函数
		LED1=1;	//灯灭
		delay_10us(50000); 	
	}		
}

LED闪烁-CSDN直播 

参考链接:
【嵌入式百科】003——时钟周期、指令周期、机器周期、总线周期_总线周期和机器周期-CSDN博客


总结

        此次实验让我更加了解汇编语言和常用程序结构,特别是对通过软件多重循环软件计数的定时方法有了更深的认识。

文章多有不足,欢迎批评指正。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值