【51单片机】基于SDCC和Edsim51的代码仿真

1.实验目标

1.1. 点灯

安装SDCC和Edsim51,采用汇编语言与C语言两种方式,在Edsim51虚拟开发板上点亮一个Led灯,并思考尝试让Led灯周期性闪烁。写作详细操作过程。

1.2. 指令比对

参考附件中8051指令集大全手册,在Edsim51,把汇编语言点亮Led1灯的代码,手工翻译转换为机器指令,与Edsim51 编译生成的机器码指令进行对比,查看是否一致。写作详细操作过程。

1.3.Proteus仿真

在Proteus中画出一个与Edsim51虚拟电路原理基本相同的电路,用Proteus仿真完成Led灯的点亮和闪烁,须分别采用以下方式:

1.3.1采用Proteus+SDCC 的C程序编程;
1.3.2采用Proteus+Keil C51 的C程序编程;
1.3.3采用Proteus 内置汇编语言编译的方式;

2.实验过程

2.1.1 Edsim点亮1个LED灯

点亮1个接到P1端口的LED灯如P1.0,则需要1111 1110(低电平点亮LED)。
由于P1的低电平地址为90H(0x90),而我们需要传入的二进制1111 1110对应的十六进制数为FE、十进制数254。
因此,汇编语言可以写

MOV 90H,#254
;or
MOV 90H,#0xFE
;or
MOV 0x90,#254
;or
MOV 0x90,#0xFE

当然,不记得的话也可以写

MOV P1,#254 ;或许还有其他写法,可以自己尝试一下

2.1.1

2.1.2 周期性闪烁

想要实现周期性闪烁,我们可以让P1端口的八个灯依次逐个点亮。然后在最后加入DJNZ指令跳转LOOP实现周期循环。

DJNZ 将寄存器的值减1。如果寄存器的初始值为 0,则减少该值将使其重置为 255(0xFF Hex)。如果寄存器的新值 不为 0,程序将跳转到相对 addr指示的地址。如果寄存器的新值为0,则程序流程继续执行 DJNZ 指令后面的指令。

MOV R1,#0FEH  ;给寄存器Rn赋值254,这个值不是固定的,根据需求设置,越大延迟时间越长
LOOP: 
MOV P1,#0FEH 	;点亮LED1  
MOV P1,#253  	;0FDH,点亮LED2
MOV P1,#251		;0FBH,点亮LED3
MOV P1,#247		;0F7H,点亮LED4
MOV P1,#239		;0EFH,点亮LED5
MOV P1,#223		;0DFH,点亮LED6
MOV P1,#191		;0BFH,点亮LED7
MOV P1,#127		;07FH,点亮LED8
DJNZ R1,LOOP ;R1!=0时,R--;R1==0时,跳出循环
;以上代码在Edsim中低速运行,所以有流水灯效果,现实中微不可见,需要加入延时函数

效果如下:
在这里插入图片描述

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

    P1=0b11111101;

    P1=0b11111011;

    P1=0b11110111;

    P1=0b11101111;

    P1=0b11011111;

    P1=0b10111111;

    P1=0b01111111;
  }
}

值得注意的是,使用sdcc将.c文件依照以下指令转为hex文件后加载到Edsim后,需要将Update Freq.的值设为10000,此时运行代码会呈现相对流畅的LED灯周期变化。
在这里插入图片描述
请添加图片描述

2.2. 代码比对

以下为Edsim根据导入的hex文件生成的汇编语言。

ORG 0000H
    ;程序起始和跳转
	LJMP 0008H
	LCALL 0064H
	SJMP 0FEH    
	;数据移动和条件跳转
	MOV 81H,#07H
	LCALL 007EH
	MOV A,82H
	JZ 03H
	LJMP 0003H  
	;寄存器操作和循环 
	MOV R1,#00H
	MOV A,R1
	ORL A,#00H
	JZ 1BH
	MOV R2,#00H
	MOV DPTR, #0082H
	MOV R0,#00H
	;内存清零和循环结束检查
	MOV 0A0H,#00H
	CLR A
	MOVC A,@A+DPTR
	MOVX @R0,A
	INC DPTR
	INC R0
	CJNE R0,#00H,02H
	INC 0A0H
	DJNZ R1,0F4H
	DJNZ R2,0F2H
	;更多的条件跳转和内存操作
	MOV 0A0H,#0FFH
	CLR A
	MOV R0,#0FFH
	MOV @R0,A
	DJNZ R0,0FDH
	MOV R0,#00H
	MOV A,R0
	ORL A,#00H
	JZ 0AH
	MOV R1,#00H
	MOV 0A0H,#00H
	CLR A
	MOVX @R1,A
	INC R1
	DJNZ R0,0FCH
	MOV R0,#00H
	MOV A,R0
	ORL A,#00H
	JZ 0CH
	MOV R1,#00H
	MOV DPTR, #0000H
	CLR A
	MOVX @DPTR,A
	INC DPTR
	DJNZ R0,0FCH
	DJNZ R1,0FAH
	LJMP 0003H
	MOV 90H,#0FEH
	MOV 90H,#0FDH
	MOV 90H,#0FBH
	MOV 90H,#0F7H
	MOV 90H,#0EFH
	MOV 90H,#0DFH
	MOV 90H,#0BFH
	MOV 90H,#7FH
	SJMP 0E6H
	MOV 82H,#00H
	RET
	END

通过对比可以发现,Edsim生成的代码相较于我们写的汇编代码更长更复杂。

2.3.1 采用Proteus+SDCC 的C程序编程

Edsim51电路原理图
在这里插入图片描述

#include <8051.h>  //经过测试,2.1.3的代码并不好用,经过更改后如下,但是以下代码无法在Edsim中仿真
  
void delay(unsigned int count) {  
    while(count--);  
}  
void main() {  
    while(1) {  
    P1=0b11111110;
    delay(1000);
    P1=0b11111101;
    delay(1000);
    P1=0b11111011;
    delay(1000);
    P1=0b11110111;
    delay(1000);
    P1=0b11101111;
    delay(1000);
    P1=0b11011111;
    delay(1000);
    P1=0b10111111;
    delay(1000);
    P1=0b01111111;
    delay(1000); 
    }  
}
2.3.2采用Proteus+Keil C51 的C程序编程
//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.youkuaiyun.com/qq_43279579/article/details/108908566
2.3.3 采用Proteus 内置汇编语言编译的方式
ORG 0000H
LOOP: 
MOV P1,#0FEH ; 点亮LED  
MOV P1,#253
MOV P1,#251
MOV P1,#247
MOV P1,#239
MOV P1,#223
MOV P1,#191
MOV P1,#127
DJNZ R1,LOOP ;随便写个寄存器Rn都是可以的
END

3.实验总结

SDCC可以将.C文件转为hex文件,再由Edsim生成汇编语言,但是此时的汇编指令是很复杂的,比起了解汇编指令原理并直接书写要长很多。
C语言作为高级语言,比起汇编语言可读性更高,更容易理解。C语言是汇编语言的升级,汇编语言是C语言的基础,二者是相互兼容,理解汇编语言有利于我们更加了解C

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值