8051单片机是早最典型的产品,该系列具它单片机都是在8051的基础上进行功能的增、减、改变而来的,所以人们习惯于用8051来称呼MCS51系列单片机。
8051单片机可分为无ROM型和ROM型两种 无ROM型的芯片,必须外接EPROM才能应 用(典型芯片为8031) ROM型芯片又分为EPROM型(典型芯片为 8751)、FLASH型(典型芯片为89C51)、 掩膜ROM型(典型芯片为8051 )、一次性 可编程ROM(One Time Programming,简 称OTP)的芯片(典型芯片为97C51)。
(1)一个位微处理器CPU。。
(2)片内数据存储器 )片内数据存储器RAM和特殊功能寄存器 和特殊功能寄存器 。
(3)片内程序存储器 )片内程序存储器ROM。
(4)两个定时 计数器 TO、T1,可用作定时器,也可用以 )两个定时/计数器 对外部脉冲进行计 数。 I/O端口
(5)四个8位可编程的并行I/O端口,每个端口既可作输 )四个8位可编程的并行I/O端口, 也可作输出。 入,也可作输出。 一个串行端口,用于数据的串行通信。
(6)一个串行端口,用于数据的串行通信。 中断控制系统。
(7)中断控制系统。 内部时钟电路。
(8)内部时钟电路。
由于单片机是一门实践性很强的课程,如果采用传统的开发模式,则要购买价格昂贵的仿真器、编程器等开发工具来作实验。其实由于芯片功能的日益完善,我们可以利用芯片的在系统编程(ISP)功能制作出实用而低价的开发工具。本文旨在帮助DIY爱好者开发制作出适合自己的开发工具。
1 当前常用开发模式
目前,基本上有两种开发模式可供选择:用仿真器、用编程器。
① 用仿真器。优点:方便,可以设置断点,可以观察存储器及寄存器的内容。缺点:价格昂贵,不同类型的单片机要购买不同的仿真器;仿真器终究不是单片机,有时代码在仿真器上能通过,但在单片机中不能正常工作,反而增加了调试的难度。
② 用编程器。优点:价格相对便宜,通常一款编程器可编程多种器件。缺点:操作相当不便,每次要将芯片在目标板与编程器之间转移,并且还要在编译操作界面与编程器操作界面之间切换,大部分时间在做简单的重复工作。
2 新的开发模式介绍及芯片选择
本文介绍的开发工具采用一种新的开发模式(类似于编程器开发模式)。由于利用了芯片的在系统编程功能,因此不需要移动芯片。在软件设计时设计成:一旦代码文件被重新编过,即自动下载到芯片,并自动复位运行,是真正的“所编即所得”。
目前很多单片机都支持在系统编程。8051系列单片机支持在系统编程的也很多,但大多数是支持通过PC机的串口对单片机进行编程。这样有四个不方便的地方:一是项目本身与PC机串行通信不方便;二是要增加1片MAX232电平转换芯片;三是有的芯片要按特定的步骤进入下载模式,编程过程需要手工干预;四是有的芯片需要固件(定制的程序)的支持,如果不小心损坏了固件,则芯片的在系统编程功能也没有了。
经过比较,Atmel公司生产的AT89S8252是一种比较理想的芯片,适合制作开发工具。此芯片有如下特点:
与8051兼容;
内含8KB可擦写1000次的程序存储器,2KB可擦写超过100 000次的数据存储器及256字节8位宽内部RAM;
可通过SPI接口在系统串行编程,与8051兼容
串行编程时有自动擦写周期,在调试大程序时可以分段下载,节约时间;
低电压下载,无需12V编程电压。
3 AT89S8252串行编程
(1)AT89S8252串行编程模式
当芯片的RST引脚置高电平时,所有程序和数据存储器可以通过SPI总线接口[SCK,MOSI(input),MISO(output)]编程。RST变高以后,在编程或擦除操作之前必须首先发送一条编程允许命令。在串行编程模式下,芯片会在字节编程之前自动插入一个擦除周期。因此,除非芯片的代码保护位被编程,编程之前不需要执行全片擦除命令。SPI接口之SCK时钟频率须低于晶振频率的1/40。
(2)AT89S8252串行编程步骤
① 在XTAL1与XTAL2之间连接一个3~24MHz的晶振;在VCC与GND之前加上电源电压,将RST置高,等待10ms。
② 发送串行编程允许命令。
③ 发送写/读/擦除等命令及数据,串行数据高位在前,低位在后,数据在时钟的上升沿锁定。
④ 如果上一步是写命令,至少等待2.5ms。
⑤ 需要时重复③、④两步。
⑥ 将RST置低,芯片开始运行。
(3)AT89S8252串行编程命令
AT89S8252串行编程命令如表1所列。
4)AT89S8252串行编程时序图
AT89S8252串行编程时序如图1所示。
4 硬件设计
① 通过计算机并口与单片机SPI口连接;
② 为了保护计算机并口,需要增加1片74HC244作为隔离。
实用的原理图如图2所示。(已经过实践检验,可放心使用。)
5 用VB编程进行并口控制
打印端口的基地址一般为0x278、0x378或0x3BC,可以从控制面板中查到。为了方便读者,表2列出了常用打印端口引脚及寄存器位元的说明。
在Windows环境下最简单易学的语言恐怕非VB莫属,所以我们的开发工具也选用VB作为编程语言。但由于Windows的保护,VB无法直接读写打印端口,因此我们需要另外的程序模块来实现打印端口的直接读写。在Internet网上可以找到许多此类模块,并且相当多的模块可以免费使用。经过试用,笔者推荐使用Winio v2.0。该模块支持Win9X/NT/2000/XP(https://www.internals.com Yariv Kaplan ),并且带有详细的帮助、例子程序及源码。使用时,将Winio.sys、Winio.dll、Winio.vxd及Winio.bas四个文件拷贝到工作目录下,在VB中直接添加Winio.bas模块即可。本例中用到的函数有四个,分别说明如下。 ① Initialize():允许端口控制函数。在使用端口输入输出函数之前调用一次,成功返回“1”,失败返回“0”。
② Shutdown():关闭端口控制函数。在退出程序时执行一次,成功返回“1”,失败返回“0”。
③ GetPortVal(ByVal PortAddr As Integer, ByRef Portval As Long, ByVal bSize As Byte) As Boolean:读取端口函数,PortAddr 为端口地址, Portval为端口值,bSize为要读取的字节数。读取成功时返回“1”,失败时返回“0”。
④ SetPortVal(ByVal PortAddr As Integer, ByVal Portval As Long, ByVal bSize As Byte) As Boolean:写端口函数。PortAddr 为端口地址, Portval为要写的值,bSize为要写入的字节数。写入成功返回“1”,失败返回“0”。
四个函数在Winio.bas模块中的声明如下:
Declare Function InitializeWinIo Lib 揥inIo.dll” () As Boolean
Declare Function ShutdownWinIo Lib 揥inIo.dll” () As Boolean
Declare Function GetPortVal Lib 揥inIo.dll” (ByVal PortAddr As Integer, ByRef Portval As Long, ByVal bSize As Byte) As Boolean
Declare Function SetPortVal Lib 揥inIo.dll” (ByVal PortAddr As Integer, ByVal Portval As Long, ByVal bSize As Byte) As Boolean
6 Intel HEX 格式文件
由于一般编译软件产生的用于写入芯片的文件都是Intel HEX格式的文件。Intel HEX文件属于文本文件,可以用记事本查看。一个Intel HEX文件的一行称为一个记录,每个记录都是由十六进制字符组成的,两个字符表示一个字节的值。Intel HEX文件通常由若干条记录组成,每个记录都具有如下的形式:
:LLAAAATTDD...DDCC
“:”——记录的起始标志;
LL——记录长度,表示该记录中的数据字节数;
AAAA——数据装入的首地址(16位);
TT——记录类型,00表示数据记录,01表示文件结束;(注意:有的编译软件会产生大于01的记录类型,本应用中对大于01记录类型的记录忽略掉即可。)
DD——数据值(字节);
CC——校验和。(将其本身与记录中除起始标志外的所有字节相加应为0,不为0则有错。)
VB编程详细说明见本刊网络补充版(https://www.dpj.com.cn)。(由于各子程序的流程都较简单,所以直接给出源码,而未画出流程图。程序采用由底至顶的设计方法。)
结 语
虽然上述程序能实现各种基本的功能,但并不完善,并未考虑各种异常情况,读者可根据实际情况进行完善。编程功力较差的朋友可直接到笔者的网站(http: //www.mcudiy.com)下载相对较完善的应用程序 。如果充分理解了上述程序,那么DIY一个AVR或PIC单片机的开发工具也非难事。在笔者的网站也有制作完成的“MCS51/AVR/PIC三合一下载器资料”供爱好者下载。
由于AT89S8252的价格还是较贵,所以现在市场上较难买,不过Atmel公司推出的替代AT89C51/52的AT89S51/52也有在系统编程功能,且价格便宜。其在系统编程的实现方法与AT89S8252类似,对本例部分程序稍作修改即可支持该器件。笔者制作的“MCS51/AVR/PIC三合一下载器”增加了对AT89S51/52的支持。
本文通过对8051单片机的特点分析,提出了一种低成本的方法,使其软件可以利用系统已有的通信链路在线升级。
1 基本原理
类似于其他引导装载升级程序的方法,在系统中必须始终存在一段用于程序装载的代码(bootloader),该代码在启动时被运行。其基本功能是根据外部条件来判断是运行现有版本的程序还是从主机下载新程序。8051具有选择执行片内或者片外程序的功能,而对片内E2PROM编程过程相对比较复杂,因此这里将程序引导装载代码烧结在内部程序空间中,并不准备改变;而将系统应用程序存放在片外一编程相对简单和独立的E2PROM内,是随时可以更新的部分。通过外围电路的支持,单片机上电复位时首先执行片内的装载程序,如图1所示。该装载代码将应用程序从E2PROM拷贝到外部存储器(RAM)中以备执行,同时还通过通信接口监系统程序装载执行过程听主机命令。当收到主机更新程序的请求后,立即接收新的应用程序内容,并在最终确认后写入扩展E2PROM内。当片内程序执行完毕后,系统软件复位并执行片外RAM中的程序,而RAM的内容正是由装载所决定的。如果CPU再次复位,那么将重复上述装载执行过程。
值得注意的是,在对外部程序存储器访问时,8051单片机只提供读指令(MOVC)而并不具备写指令。但是从单片机对外部程序和数据存储器的访问时序上看具有一致性,不同的是读代码使用PSEN信号而读数据使用RD信号。同时,单片机的PSEN﹑RD和WR信号不会同时有效,因此将PSEN和RD逻辑合并后,可以使程序和数据合二为一读写成为可能。这样同一个地址单元RD、WR(MOVX)和PSEN(MOVC)均可以进行访问。单片机可以使用MOVX写指令来更改相当于其外部程序空间中的内容。特别要注意的是,当程序和数据共存于一片RAM中时,必须使用编译器提供的相关连接命令使数据区偏离代码可能占用的区域,否则会导致系统混乱。 2 硬件电路
硬件参考电路如图2所示。系统加电后,由于C3两端电压不能瞬变,使D触发器置1端保持一短暂低电平,强制将单片机EA信号置高。在U4看门狗上电复位信号撤销后,单片机开始从内部程序空间0地址起执行。内部装载程序先通过P1.4、P1.5模拟I2C总线时序从E2PROMU3中将应用程序代码拷贝到片外RAM从0地址起的空间中。如果到代码拷贝结束串行口一直没有收到预定的程序下载命令,则通过软件置低P1.6口触发看门狗芯片对单片机复位,在复位脉冲的上升沿,D触发器锁存其输出的信号使EA电平翻转为低电平。待复位信号撤销后,单片机开始执行位于外部程序空间的系统应用程序代码。在执行外部程序时,如果看门狗再次复位,EA将会恢复高电平并重新执行内部装载程序。
当上位机欲更改终端设备程序时,可通过串口向其发送特定的握手字符串,无论片外程序还是片内程序都能识别该字符串并且复位单片机(如果是正在运行外部程序)执行内部装载程序。装载程序就绪后向上位机发送确认回应,并接收来自上位机的程序代码。单片机通过置低P1.3允许E2PROM写操作,将新的内容写入E2PROM中,完成程序的更新。
3 软件设计
装载程序主要有两个功能,其一是要将E2PROM的内容拷贝到片外RAM中;其二是要响应上位机的更新程序命令并接收代码内容更新E2PROM。
#define uchar unsigned char
#define uintunsigned int
sbit WDI=P1^7;
sbit RESET=P1^6;
/*声明外部I2C读写函数*/
extern void I2c[_]wr(uchar addh,uchar addl,uchar buf[],uchar num,bit wr);
void main(void) {
uchar data addh,addl;
uchar data buf[16];
uchar j;
uint I=0;
XBYTE[0x1fff]=0;/*清除程序拷贝好标志*/
WDI=~WDI; /*喂狗*/
system[_]init(); /*初始化*/
for(addh=0;addh<0x10;addh++) {
for(addl=0;addl<0xf0;addl+=16) {
/*读入E2PROM地址addh:addl16字节内容到buf*/
I2c[_]wr(addh,addl,buf,16,1);
for(j=0;j<16;j++)
/*将代码写入外部地址*/
XBYTE[I++]=buf[j];
}
I2c[_]wr(addh,0xf0,buf,16,1);
for(j=0;j<16;j++)
XBYTE[I++]=buf[j];
WDI=~WDI;
}
if(shake[_]hand==1) {
/*shake[_]hand由串口中断收到握手命令后置1*/
rcv[_]data(); /*该函数负责从上位机获取程序*/
}
XBYTE[0x1fff]=0xaa;/*置程序拷贝好标志*/
RESET=0;/*复位单片机并执行外部RAM内的程序*/
while(1);
}
为了确保程序在装载完全正确后才开始执行,装载程序使用了外部RAM 0x1fff地址内容作为装载成功的标志。那么相应的应用程序应判断此标志后再执行。
调试结束的装载程序烧结在单片机中,而实际的系统应用程序则存储于外部E2PROM内。应用中,将单片机直接焊装在电路板上,而编程者只需通过串口或者其他形式的通信链路甚至无线的方式来更改升级目标应用程序。
4 几点讨论
在实际应用中,使用严格的校验及复查方法来确保程序拷贝无误。 另外, 在从上位机下载程序时应该制定一个可靠的通信协议, 从而保证获取的程序完全正确。 单片机在接收到上位机的代码数据时,不要急于写入外部E2PROM,而应先全部放在外部RAM区内,待代码获取完毕并且通过校验检查后再把RAM的内容一次性写入E2PROM。这样防止在获取程序的时候通信异常中断而E2PROM内将没有一个可以执行的程序。
从原理上看,如果片外RAM是非易失的,就可以不再使用E2PROM。但是这样系统成本变高且可靠性降低,因为当单片机程序跑飞时很容易产生MOVX指令而改变RAM区的内容,造成程序性不可恢复。而在程序跑飞的情况下,很难产生符合外部E2PROM接口的I2C写时序,同时E2PROM还有写保护功能。
虽然上述方法能使8051单片机系统具有远程升级代码的能力,但是程序装载过程将使系统的启动时间延长数秒,在对启动时间要求较短的场合不能应用本文中介绍的方法。
以下提供的链接是生产8051家族单片机的厂商的网址及其单片机产品数据手册的地址。如果你还知道其他8051兼容的单片机的厂商及其产品型号,请告知它们的网址。
Analog Devices
Micro PORTs UARTs TMR I2C IRAM OCPRG OCRAM A/D D/A WD CLK
ADuC812 4 1 3 Yes 256 EP=8k SR=640 Yes Yes Yes -
Atmel
Micro PORTs UARTs TMR I2C IRAM OCPRG OCRAM A/D D/A WD CLK
AT89C1051 2 - 1 - 64 F=1k - - - - -
AT89C2051 2 1 2 - 128 F=2k - - - - -
AT89C51 4 1 2 - 128 F=4k - - - - -
AT89C52 4 1 3 - 256 F=8k - - - - -
AT89LV51 4 1 2 - 128 F=4k - - - - -
AT89LV52 4 1 3 - 256 F=8k - - - - -
AT89LV55L 4 1 3 - 256 F=20k - - - - -
Dallas Semiconductor
Micro PORTs UARTs TMR I2C IRAM OCPRG OCRAM A/D D/A WD CLK
80C310 4 1 3 - 256 - - - - - -
80C320 4 2 3 - 256 - - - - Yes -
80C323 4 2 3 - 256 - - - - Yes -
87C520 4 2 3 - 256 EP=16k - - - Yes -
87C530 4 2 3 - 256 EP=16k - - - Yes Yes
87C550 7 2 3 - 256 EP=8k SRAM=1k Yes - Yes -
Intel
83C51KB
87C51
87C54
8xC151
8xC152
8xC251
8xC52 Online Tutorial
ISSI
Micro PORTs UARTs TMR I2C IRAM OCPRG OCRAM A/D D/A WD CLK
80C31 4 1 2 - 128 - - - - - -
80C51 4 1 2 - 128 R=4k - - - - -
80C32 4 1 3 - 256 - - - - - -
80C52 4 1 3 - 256 R=8k - - - - -
Okidata
MSM80C48/49/50
MSM80C154S/83C154S
MSM85C154HVS
Triscend Corporation
Micro PORTs UARTs TMR I2C IRAM OCPRG OCRAM A/D D/A WD CLK
TE505 12 1 3 - 256 - SR=8Kx8 - - Yes -
TE512 15 1 3 - 256 - SR=16Kx8 - - Yes -
TE520 31 1 3 - 256 - SR=40Kx8 - - Yes -
TE532 39 1 3 - 256 - SR=64Kx8 - - Yes -
TDK Semiconductor
Micro PORTs UARTs TMR I2C IRAM OCPRG OCRAM A/D D/A WD CLK
73M2910 4 1 3 - 256 - - - - - -
Philips
8xC51/80C
8XC32/51/52/54/58/FX/RX+
80/83/87C451
80/83/87C550
83C562
80/83/87C575
83/87C576
83/87C750
83/87C751
83/87C752
87C524
87C528
87C552
87C652
87C654
83/87C508
P80/83C56
89C535/53
P83C434/8
TELX FAMILY
8XC592
8XCE598
83/87C748
83/87C749
83C524
80/83C528
80/83C552
OM5202
OM5232
OM5234/5284
OM5238
80/83/89CE558
P80/83CE559
80/83C851
83C654
80/83C851
83CE654
83C/055/145/845/87C055
TPM749
TPM754
80/83/87C453
83/87C754
Infineon (previously Siemens)
C501
C504
C505
C509
C511/C513
C515
C517A
C540/C541
SMC
Micro PORTs UARTs TMR I2C IRAM OCPRG OCRAM A/D D/A WD CLK
COM20051 4 1 3 - 256 - - - - - -
TEMIC (now part of Atmel)
Micro PORTs UARTs TMR I2C IRAM OCPRG OCRAM A/D D/A WD CLK
80C31 4 1 2 - 128 - - - - - -
80C51 4 1 2 - 128 R=4k - - - - -
80C32 4 1 3 - 256 - - - - - -
80C52 4 1 3 - 256 R=8k - - - - -
TSC80CL31 4 1 2 - 128 - - - - - -
TSC80CL51 4 1 2 - 128 R=4k - - - - -
TSC87C51 4 1 2 - 128 EP=4k - - - - -
TSC87C52 4 1 3 - 256 EP=8k - - - - -
80C154 4 1 3 - 256 - - - - Yes -
83C154 4 1 3 - 256 R=16k - - - Yes -
83C154D 4 1 3 - 256 R=32k - - - Yes -
单片机的出现是计算机技术发展史上的一个里程碑,它使计算机从海量数值计算进入到控制领域。在单片机中,以8051系列最为经典,至今仍是最普及、广泛使用的8位MCU架构。业界许多技术人员在其基础上不断进行性能扩展,使得8051系列芯片不断完善,从而形成一个庞大的体系。在传统的8051系列单片机中,设置了一组双字节寄存器(数据指针DPTR),用于访问外接的64 KB数据存储器和I/O接口电路;但在现今的8051单片机应用中,特别是在嵌入式系统中,往往涉及大规模的数据转移操作,而传统8051的一组数据指针使用起来则显得捉襟见肘,因此若在8051设计中将数据指针设计为两组或多组,则在执行大规模数据转移操作时会相当简便、迅速。在这种背景下,本文首先以数据转移执行效率为衡量标准,分析了DPTR扩展的意义,并在Oregano公司的MCS8051核[1]上实现了DPTR扩展。
1 DPTR扩展意义
为描述8051中的DPTR扩展的意义,我们针对实现大规模数据转移,分别对DPTR扩展前后作了对比。为使对比更加清晰明了,提出了数据转移执行效率的概念。
数据转移执行效率v定义为进行单字节数据转移所耗费的机器周期数,即v=nt。其中,n表示所转移数据字节数;t表示所耗费的机器周期,可设定其单位为字节/机器周期。
在未进行DPTR扩展的8051中,可通过设置地址缓冲区的方法来实现大规模的数据转移。具体的例程如下:
MOVPRE:
MOV50H, #s[_]adrh
MOV51H, #s[_]adrl
MOV52H,#t[_]adrh
MOV53H,#t[_]adrl
MOVR2, #64
REMOVE:MOV DPH, 50H
MOV DPL, 51H
MOVX A, @DPTR
INC DPTR
MOV 50H, DPH
MOV 51H, DPL
MOV DPH, 52H
MOV DPL, 53H
MOVX @DPTR,A
INC DPTR
MOV 52H, DPH
MOV 53H, DPL
DJNZ R2, REMOVE
在此例程中,50H、51H用于存放数据源地址s[_]adr(s[_]adrh为高字节, s[_]adrl为低字节),52H、53H用于存放数据目的地址t[_]adr(t[_]adrh为高字节, t[_]adrl为低字节),实现将源地址起始64字节数据转移至目的地址。在8051中,执行n字节数据移位操作耗费(14+28×n+2)个机器周期,数据转移执行效率为v=n/(14+28×n+2)。在本例程中,n为64,计算得出共需耗费1 808个机器周期,执行效率v约为0.035 4字节/机器周期,而且在此实现方法中需占用8051的4个片内存储器(RAM)单元。
如8051中拥有两组DPTR,并可通过特殊指令来实现DPTR选取。可设定SETDPTR0指令表示选取DPTR0,SETDPTR1指令表示选取DPTR1,#s[_]adr表示数据源地址,#t[_]adr表示数据目的地址,则程序可设计为:
MOVPRE:
SETDPTR0
MOVDPTR,#s[_]adr
SETDPTR1
MOV DPTR,#t[_]adr
MOV R2,#64
REMOVE2:
SETDPTR0
MOVX A,@DPTR
INC DPTR
SETDPTR1
MOVX @DPTR,A
INC DPTR
DJNZ R2,REMOVE2
程序中, 对于特殊指令SETDPTR0和SETDPTR1,可通过设置特殊功能寄存器(SFR)以表示DPTR状态,并对此SFR进行操作,以实现DPTR选取。因此DPTR选取指令可由3字节指令实现,则在两组DPTR情况下执行大规模数据转移需耗费(14+12×n+2)个机器周期,数据转移执行效率为v=n/(14+12×n+2)。在本例程中,执行64字节数据转移需耗费784个机器周期,执行效率约为0.085 64字节/机器周期。
通过以上对比发现,拥用两组DPTR的8051比传统8051在大规模数据传输时的数据转移执行效率比为(14+28×n+2)/(14+12×n+2)。由图1可知,随着所转移数据量的不断加大,即n值增大时,执行效率比也不断增大,且趋近于2.33。
图1 数据转移执行效率对比图
经过以上分析得出:在8051中设置两组DPTR将会使其在数据转移执行效率上有很大提高。从资源占用方面考虑,使用扩展DPTR的方式来实现数据转移,仅需在8051中添加一个SFR,因此在8051中实现DPTR扩展,可在资源占用很少的条件下,明显加快数据转移速率。这对于在嵌入式系统应用中,进行大规模数据转移意义重大。
2 具体设计实现
在8051中对DPTR实现扩展,首先需要对DPTR的相关指令进行分析,再确定对其进行扩展会影响到哪些指令操作;并根据其所涉及的指令,分析相应的模块,针对各模块分别进行设计修改。
2.1 相关指令分析
在8051标准指令集的111条指令中,与DPTR有关的指令共有5类,分别为:
① 程序存储器查表指令,“MOVC A,@A+DPTR”;
② 片外RAM传送指令,“MOVX A, @DPTR”和“MOVX @ DPTR , A”;
③ 寄存器数据传送指令,即可对DPTR进行读写操作,在8051中DPTR由DPH(DPTR高8位字节)和DPL(DPTR低8位字节)构成,且DPH和DPL与一般的SFR一样,都可作为寄存器进行读写、压栈等操作;
④ 程序转移指令,“JMP @A+DPTR”;
⑤ 运算指令,可分别对DPH和DPL进行运算操作。
通过对以上与DPTR相关的5类指令分析可知:第③类指令和第⑤类指令是将DPTR作为SFR进行操作的。第①类指令和第④类指令都是DPTR与PC指针进行的数据传送操作;第②类指令是对片外RAM地址寄存器进行的数据传送操作。因此,DPTR的操作具体涉及8051中以下3个模块:SFR读写模块、PC指针模块及片外RAM地址模块,故对DPTR的扩展也在这3个模块中进行。
2.2 具体模块设计
对于DPTR状态寄存器可设为dptr[_]sel,通过对DPTR状态标志位dps操作,实现DPTR选取。当dps=0时,选取DPTR0;当dps=1时,选取DPTR1。在8051中,DPTR分别由DPH和DPL组成,因此对DPTR的选取实际上是对特殊功能寄存器DPH0、DPL0和DPH1、DPL1的选取。
基于以上的设计思路,笔者分别在涉及DPTR操作的3个模块中进行了相应的修改。本设计所选用MCS8051核由VHDL语言设计,完全兼容标准8051指令集。
在SFR读写模块中,应针对读、写模块分别进行修改。通过分析MCS8051设计代码可知,对于DPTR的读操作,是通过将DPTR中数据传送给数据暂存寄存器S[_]REGDATA,再通过对S[_]REGDATA进行读操作来实现的,因此可在进行DPTR数据暂存前,利用选择位dps来对DPTR进行选取。具体示意如图2所示。
在对DPTR进行写操作时,实际上是对DPH和DPL进行操作(DPH地址为83H,DPL地址为82H),因此对DPTR进行写操作时需对DPH和DPL分别进行操作。在MCS8051中对SFR的写操作,实际上是先将要写入的数据暂存在S[_]DATA寄存器中,再通过将S[_]DATA数据分别写入DPH和DPL来实现的。因此可在S[_]DATA数据写入前对DPTR0和DPTR1进行选择判断,来实现对DPTR0和DPTR1的写操作,即dps=1时,将S[_]DATA数据写入DPH1和DPL1;dps=0时,将S[_]DATA数据写入DPH0和DPL0,具体结构如图3所示。
图2 DPTR读模块示意图 图3 DPTR写模块结构图
在PC指针模块和片外RAM地址模块中,由于也是涉及DPTR的读操作,因此该模块的修改与SFR读模块中的修改类似,也是利用dps来实现DPTR0、DPTR1的选取。
3 仿真测试
在MCS8051中,针对以上3个模块分别作了修改,将DPTR扩展为两组,通过对DPTR[_]SEL(设定为SFR的E1H)中DPTR状态标志位dps进行操作,来实现对DPTR0和DPTR1的选取,并利用仿真软件Modelsim6.0进行了仿真测试。由于在实现DPTR扩展时主要针对SFR读写模块、PC指针模块和片外RAM地址模块这3个模块进行了修改,因此对于DPTR扩展的仿真测试也分3个模块进行。
3.1 针对SFR读写模块的测试
该模块的测试主要为测试DPTR0和DPTR1的数据传输。首先对DPTR状态标志dps位进行操作,分别选取DPTR0和DPTR1;其次分别对其进行写操作;将DPTR0和DPTR1中数据值依次输出寄存器A中。具体波形如图4所示。
图4 SFR读写测试波形
由图4可知,在执行指令75E100前后(即将dps复位,选取DPTR0),DPH和DPL输出(执行指令E583,E582)到寄存器A中的值不同。指令75E100执行前DPH输出为55,DPL输出为66,执行后输出分别为11和22,因此表明通过dps进行DPTR选取,读写操作无误,即对SFR读写模块的修改无误。
3.2 针对PC指针的数据查表测试
针对此模块,进行了一个查表测试,即向DPTR0和DPTR1中分别写入data1和data2两个数据表的地址;而后利用dps选取DPTR0和DPTR1,再分别对其进行数据查表输出。具体波形如图5所示。
图5 PC指针的数据查表波形
选取DPTR1(已存入data2地址,执行指令75E180)后,将寄存器A清零(执行指令7400),并将查表数据输出(执行指令93),输出数据为11H;而后选取DPTR0,再次将寄存器A清零,并进行查表输出,输出数据为44H。对比可发现输出数据与表中数据一致。由此表明,通过dps选取DPTR0和DPTR1,进行数据查表操作无误,即对PC指针模块的修改无误。
3.3 片外RAM数据读写测试
对于片外RAM数据读写测试,即大规模数据转移,测试方案为:首先将DPTR0和DPTR1中分别写入地址adr0和adr1,再分别对这两个地址写入数据,将这两个地址的数据通过DPTR0和DPTR1读出,将读出的结果与写入结果对比,具体测试波形如图6所示。
图6 片外RAM数据读写波形
将dps置位(执行指令75E180)选取DPTR1后,将片外RAM中adr1数据读出,输出数据为77H;将dps复位(执行指令75E100)选取DPTR0后,将adr0数据读出,输出数据为44H。经对比可发现与所写入的数据一致。由此可表明,通过dps选择DPTR0和DPTR1对片外RAM进行数据读写无误,即表明对片外RAM地址模块的修改无误。
3.4 FPGA仿真测试
基于MCS8051这款8051微控制器,我们还进行了实际的FPGA仿真测试。首先利用RS232接口,在从计算机上将大规模数据接收并写入到MCS8051片外RAM的地址adr0中;再利用例程2所给方法,进行大规模数据转移,将数据转移写入到地址adr1中;通过RS232接口将adr1中数据发送到计算机。通过对比发送和接收的数据发现,笔者对于DPTR的扩展无误。
结语
通过扩展DPTR可使8051在大规模数据转移时的执行效率大大提高,这使得采用扩展8051作为微控制器的嵌入式系统,在大规模数据转移时,其处理速度将大大提高。利用文中所阐述的方法也可将DPTR扩展为多组,但其具体应用意义尚需进一步探讨。