一、采用汇编语言与C语言两种方式,在Edsim51虚拟开发板上点亮一个Led灯,并让Led灯周期性闪烁。
1.采用汇编语言与C语言点亮一个Led灯
(1)汇编语言
汇编语言比较简单,因为LED0 接在P1.0端口上,8051中P1.0的地址固定为 90H,因此,对这个地址 (指针)对应的寄存器写入立即数 0(低电平),就可以是 LED0电路导通,亮灯。 对应的汇编命令是
MOV 90H, #0xFE
或者
MOV 0x90,#0xFE
或者
MOV 0x90,#254
注意,在仿真运行之前,Edsim51的Update Frequency (刷新频率)要加大到10000或更高。
(2)C语言程序
Edsim51自身只能编译汇编语言,C语言程序需要借助其他C编译器(比如SDCC for 8051或 Keil for 8051)转换为汇编和二进制执行程序(.hex)才能仿真运行。
以SDCC for 8051 v3 为例,请下载,再将其尽量安装到除系统盘C之外的分区目录,比如 D:\SDCC3.0 (如果之前安装过其他版本的SDCC,先卸载)。 安装最后一步注意把 SDCC安装目录添加到 path 路径 变量中,这样才可以在任意位置运行 SDCC编译命令。安装好后,编译链工具程序均在 D:\SDCC3.0\bin 目录下。
首先到D:\SDCC\bin目录下先新建一个文本文档led1.text,copy 下列C代码文件在此目录下,然后将文件名改为led1.c。
源程序文件:
#include<mcs51/8051.h>
void main()
{
while(1){
P1=0b11111110;
}
}
然后按住windows+R,输入cmd,打开windows 命令行窗口。此时目录在C盘下,输入d:,切换当前工作目录到 D:\根目录下,接下来输入cd D:\SDCC\bin,切换到bin目录下。
注意:上面包含头文件 mcs51 目录下的 8051.h ,里面定义了各个寄存器的宏定义,比如 P1 、 TCON 等,不同公司的芯片其寄存器的地址可能不一样, edSim51 仿真的芯片采用的就是 mcs51 的8051芯 片。 另一个注意的地方是 main 函数是没有返回值的。 第三个注意的地方是程序里为了表示 P1 口的各个位( bit )的值,使用了 0b11111110 这样的二进制字面 量,这是非标准的 sdcc 扩展,为此,需要在编译的时候指定 --std-sdccxx 编译选项,这里 xx 需要按需 要替换为 89 、 99 、 11 、 2x 以适应不同标准,下面是一个参考命令:sdcc --std-sdcc89 led1.c
采用下列命令编译
sdcc --std-sdcc89 led1.c
如果编译成功的话,可以在当期目录下生成需要 led1.* 的文件,其中包括 ihx 文件: led1.ihx
然后 需要用 sdcc 配套的工具程序 packihx 把ihx文件转换为 hex 文件,操作命令如下:
packihx led1.ihx > led1.hex
成功的话可以得到 led1.hex 执行程序,然后我们就可以用 edSim51 仿真器中的 load 按钮加载 hex 进行仿真 run。
下面打开 edSim51 仿真器,点击 new 按钮, load 按钮:
选择生成的 led1.hex 文件
然后在 update freq 选择 50000 ,点击 run 按钮,如下得到结果
可以看到, run 运行后 变为 Pause ,在左下方可以看到 LED灯亮了(白色表示灭,最右边的红色表示 LED 0 灯亮),在右边可以看到 P1 口的状态( 0 或 1 )。
2.采用汇编语言与C语言使Led灯亮灭
(1)汇编语言
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 ;指令结束
仿真运行后,可以看到Led在闪烁。
(2)C语言程序
按照上文中点亮一个Led时,使C语言程序借助SDCC 转换为二进制执行程序(.hex)进行仿真运行。
源程序文件:
#include<mcs51/8051.h>
void Delay(unsigned int t);
void main (void)
{
while (1)
{
P1=0b11111110;
Delay(10000);
P1=0b11111111;
Delay(10000);
}
}
void Delay(unsigned int t)
{
while(--t);
}
运行结果可以看到Led闪烁。
二. 参考附件中8051指令集大全手册,在Edsim51,把汇编语言点亮Led1灯的代码,手工翻译转换为机器指令,与Edsim51 编译生成的机器码指令进行对比,查看是否一致。
汇编语言:
MOV 90H, #0xFE
机器语言:
(1)手工翻译
MOV对应机器码为74
90H对应机器码为90
#0xFE对应机器码为FE
(2)Edsim51 编译生成的机器码指令
MOV对应机器码为75
90H对应机器码为90
#0xFE对应机器码为FE
除了操作码MOV相差1之外,其他的都一致。
三. 在Proteus中画出一个与Edsim51虚拟电路原理基本相同的电路,用Proteus仿真完成Led灯的点亮和闪烁
1. Led灯的点亮
(1)采用Proteus+SDCC 的C程序编程
C语言程序:
#include<mcs51/8051.h>
void main()
{
while(1){
P1=0b11111110;
}
}
将生成的hex文件导入到AT89C51芯片中
(2)采用Proteus+Keil C51 的C程序编程
C语言程序:
#include<reg51.h>
void main()
{
while(1){
P1=0xFE;
}
}
将生成的hex文件导入到AT89C51芯片中
(3)采用Proteus 内置汇编语言编译的方式
首先右键点击AT89C51芯片,选择“编辑源代码”进行代码编译
然后在start:后面进行编辑代码,点击下面的三角形运行仿真
汇编语言:
ORG 0000H
MOV 90H,#0FEH
仿真运行3种方式,都能让Led灯点亮。
2. Led灯的闪烁
(1)采用Proteus+SDCC 的C程序编程
C语言程序:
#include<mcs51/8051.h>
void Delay(unsigned int t);
void main (void)
{
while (1)
{
P1=0b11111110;
Delay(10000);
P1=0b11111111;
Delay(10000);
}
}
void Delay(unsigned int t)
{
while(--t);
}
将生成的hex文件导入到AT89C51芯片中
(2)采用Proteus+Keil C51 的C程序编程
C语言程序:
#include<reg51.h>
sbit LED0=P1^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);
}
将生成的hex文件导入到AT89C51芯片中
(3)采用Proteus 内置汇编语言编译的方式
汇编语言:
ORG 0000H
SETB 90H ;led0置1
LCALL DELAY ;调用延时函数
CLR 90H ;led0置0
LCALL DELAY
AJMP Start ;跳转到Start
DELAY: MOV R7,#250 ;延时函数
D1: MOV R6,#250
D2: DJNZ R6,D2
DJNZ R7,D1
RET ;返回主函数
仿真运行3种方式,都能让Led灯实现闪烁。
四. 总结
通过此次实验,我了解到了新的仿真工具SDCC和Edsim51,Edsim51本身只能编译汇编语言,如果我们写的使C语言程序,就可以通过C语言编译器SDCC将其转变为汇编和二进制执行程序(hex),然后在Edsim51中进行编译。因此我学会了如何在终端通过SDCC将C语言程序文件生成hex文件。
该实验让我明白可以通过多种仿真平台和多种语言来控制LED灯的点亮和闪烁,之前的实验主要是在Proteus仿真平台通过C语言或Keil生成的汇编语言生成的hex文件来控制LED,现在也学会了采用Proteus内置汇编语言来编译的方式。
但是代码的编写还存在一定问题,主要是借鉴老师发的资料和网友所编写的内容,所以在今后的学习中,会花更多的时间进行学习。