【51单片机】运用汇编指令/C语言实现点灯

一、实验任务

  1. 安装Proteus8软件,使用AT89C51单片机的外部引脚,点亮1个LED灯。采用汇编指令完成。
  2. 采用多个LED,设计一个LED流水灯电路,分别用51汇编语言和C语言编程,实现流水灯正常工作。

二、实验实现

2.1 实验前置

http://t.csdnimg.cn/MrPeg 参考这篇博客

参考上面这篇博客,画出如下电路原理图。

原理图

2.2点亮一个LED灯

2.2.1 汇编指令

http://t.csdnimg.cn/2f8Pn 参考这个博客

其中最重要的几条指令:

ORG XXXXH     ;程序入口,其中xxxxH为程序起始地址
MOV XX,#NUM   ;MOV为数据传送指令,其中NUM为传输值,XX为寄存器
CLR X         ; 累加器X清零:
SJMP $        ;

SJMP短转移指令:
先使程序计数器PC加1两次(即:取出指令码),然后把加2后的地址和rel相加作为目标转移地址。
特例:SJMP $就是SJMP 0FEH,因为0FEH为-2补码,所以转移后地址为PC+2-2还是为0FEH,无限循环。

2.2.2 KEIL代码
ORG 0000H      ;设置程序的起始地址
MOV P0,#0FFH   ;将P0所有端口设为高电平,即关闭所有连接的LED灯
CLR P0.0       ;将P0端口第0位清除为低电平,即P0.0连接led灯点亮
SJMP $         ;短跳转指令,无限循环跳转到当前指令的地址,即LED长亮
END
2.2.3效果展示

LED1

2.3点亮流水灯

2.3.1 原理

在嵌入式开发过程中,流水灯的实现主要通过Delay函数实现。即P0~P7引脚对应的LED灯依次为低电平,然后加入延时函数,从而实现流水灯的效果。
因此,想要用汇编指令实现流水灯,则应该将寄存器中的值改变,把寄存器A中的值1000000(十进制的128)依次右移,即01000000、00100000…然后加入延时与循环,最终实现流水灯的效果。

2.3.2 汇编语言

LJMP长转移指令
如:在程序存储器中0000H单元存放一条指令:LJMP 3000H;程序就会转到3000H位置
LCALL长调用指令
RET 返回主程序
DJNZ*减 1 条件转移指令

2.3.3 KEIL代码
ORG 0000H
LJMP MAIN    ;跳转到标签MAIN所在的地址

ORG 0100H
MAIN:
MOV A,#80H   ;立即数80H(即十进制的128,二进制的1000 0000,除LED0.0其余都亮)移动到累加器A中
LOOP:        ;循环标签
MOV P0,A     ;将累加器A的内容移动到端口P0
LCALL DELAY  ;长调用指令,它调用DELAY子程序
RR A         ;将累加器A的内容右旋一位
LJMP LOOP

DELAY:
MOV R2,#255  ;分别将立即数255250移动到寄存器R2和R3中
D1:MOV R3,#250
D2:DJNZ R3,D2     
DJNZ R2,D1   ;这两个指令分别减少R3和R2的内容,并在不为0时跳回到对应的标签,形成延时
RET          ;返回主程序

END
2.3.4 实现效果

LED8

2.3.5 反向流水灯

如果我们想实现以一个个LED灯逐个点亮形成流水的效果,我们还可以这么写。
此时以LED1举例,首先我们需要让LED1亮,其余都不亮,即0111 1111,对用十进制数127,十六进制数7F。此时我们只需在2.3.3的代码基础上改动一行代码:

MOV A,#7FH  

在这里插入图片描述

2.3.5 C语言编程

同理,C语言实现反向流水灯,只需要将P0赋相对应的值:
如,当LED1亮,其余不亮时,即为1111 1110(十六进制FE)
当LED2亮,其余不亮时,即为1111 1101(十六进制FD)
当LED3亮,其余不亮时,即为1111 1011(十六进制FB)
当LED4亮,其余不亮时,即为1111 0111(十六进制FE)
当LED5亮,其余不亮时,即为1110 1111(十六进制EF)
当LED6亮,其余不亮时,即为1101 1111(十六进制FB)
当LED7亮,其余不亮时,即为1011 1111(十六进制FD)
当LED8亮,其余不亮时,即为0111 1111(十六进制FE)

如果看不懂怎么转换的,简单介绍一下
十六进制0、1、2、3、4…9、A、B、C、D、E、F
以1111 1110为例,前半部分1111转换为十进制为15,即十六进制的F
后半部分十进制是15,即十六进制的E,合起来就是FE
如果上面的也实在看不懂,可以打开微软自带的计算机
在这里插入图片描述

//51单片机编程常用的头文件
	#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)
		{
			P0=0xfe;
			delay_ms(50);
			P0=0xfd;
			delay_ms(50);
			P0=0xfb;
			delay_ms(50);
			P0=0xf7;
			delay_ms(50);
			P0=0xef;
			delay_ms(50);
			P0=0xdf;
			delay_ms(50);
			P0=0xbf;
			delay_ms(50);
			P0=0x7f;
			delay_ms(50);
		}
	}
//https://blog.csdn.net/qq_43279579/article/details/108908566

三、实验总结

此次实验过程中我们分别了解了汇编语言与C语言如何操作单片机流水灯,其实本质都是通过将所需要的值写入寄存器,从而实现引脚高低电平开关。
读完本篇文章,或许你也可以尝试用汇编或者C语言写一个1000 0000类型的流水灯程序。

以上是我的实验内容与个人学习记录,欢迎各位大佬指正其中的错误‘

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值