刘楚浩
摘要:本文详细介绍了利用AT89S8252单片机的在系统编程功能,用(以下简称VB)在Windows环境下开发制作一款MCS51单片开发工具的方法。内容涉及VB编程、PC机并口控制及单片机在系统编程等内容。
关键词:VB编程AT89S8252在系统编程DIY
目前介绍单片机应用的文章很多,但介绍单片机开发工具制作的文章却较少。由于单片机是一门实践性很强的课程,所以单片机爱好者(尤其是初学者)往往更希望看到单片机开发工具制作方面的文章。本文正是因此而作,旨在帮那些DIY爱好者开发制作出适合自己的开发工具。
一、当前常用开发模式介绍
目前基本上有两种开发模式:
1,用仿真器优点:方便,可以设置断点,可以观察存贮器及寄存器的内容
缺点:价格昂贵,且仿真器终究不是单片机,有时代码在仿真器上能通过,但在单片机中不能正常工作,反而增加了调试的难度。
2,用编程器优点:价格相对便宜,通常一款编程器可编多种器件。
缺点:操作相当不便,每次要将芯片在目标板与编程器之间转移,并且还要在编译操作界面与编程器操作界面之间切换,大部份时间在做简单的重复的工作。
二、一种新的开发模式介绍及芯片选择
本文介绍的开发工具采用一种新的开发模式(类似于编程器开发模式)。由于利用了芯片的在系统编程功能,因此不需要移动芯片,在软件设计时设计成一旦代码文件被重新编过即自动下载到芯片并自动复位运行,真正的“所编即所得”。
目前很多单片机都支持在系统编程,MCS51系列单片机支持在系统编程的也很多,但大多数是支持通过PC机的串口对单片机进行编程。这样有三个不方便的地方:一是如果项目本身要与PC机串行通讯就不方便;二是要增加一片MAX232电平转换芯片;三是有的芯片要按特定的步骤进入下载模式,编程过程需要手工干预。
经过比较,Atmel公司生产的AT89S8252是一种比较理想的芯片,适合我们用来制作开发工具。此芯片有如下特点:
l与MCS51兼容
l内含8K可擦写1000次的程序存贮器,2K可擦写超过100000次的数据存贮器及256字节8位宽内部RAM
l可通过SPI接口在系统串行编程,与MCS51兼容
l串行编程时有自动擦写周期,在调试大程序时可以分段下载,节约时间
l低电压下载,无需12V编程电压
三、AT89S8252串行编程介绍
1、AT89S8252串行编程模式介绍
当芯片的RST引脚置高电平时,所有程序和数据存贮器可以通过SPI总线接口[SCK,MOSI(input),MISO(output)]编程。RST变高以后,在编程或擦除操作之前必须首先发送一条编程允许命令。在串行编程模式下,芯片会在字节编程之前自动插入一个擦除周期。因此,除非芯片的代码保护位被编程,编程之前不需要执行全片擦除命令。SPI接口之SCK时钟频率须低于晶振频率的1/40。
2、AT89S8252串行编程步骤
a)在XTAL1与XTAL2之间连接一个3-24MHz的晶振,在VCC与GND之前加上电源电压,将RST置高,等待10ms。
b)发送串行编程允许命令
c)发送写/读/擦除等命令及数据,串行数据高位在前,低位在后,数据在时钟的上升沿锁定
d)如果上一步是写命令等待至少2.5ms
e)需要时重复C,D两步
f)将RST置低,芯片开始运行
3、AT89S8252串行编程命令介绍

4、AT89S8252串行编程时序图

四、硬件设计:
a)通过计算机并口与单片机SPI口连接
b)为了保护计算机并口,增加一片74HC244作为隔离
实用的原理图如下已经过实践检验,放心使用:
(原理图文件为)
五、用VB编程进行并口控制介绍
打印端口的基地址一般为0x278,0x378或0x3BC,这可以从控制面板中查到。为了方便读者,下面以表格形式列出常用打印端口脚位及寄存器位元说明。
在Windows环境下最简单易学的语言恐怕非VB莫属,所以我们的开发工具也选用VB作为编程语言。但由于Windows的保护,VB无法直接读写打印端口,因此我们需要另外的程序模块来实现打印端口的的直接读写。在Internet网上可以找到许多的此类模块,并且相当多的模块可以免费使用。经过试用,笔者推荐使用,该模块支持Win9X/NT/2000/XP(),并且带有详细的帮助、例子程序及源码。使用时将、、及四个文件拷贝到工作目录下,在VB中直接添加模块即可。本例中用到的函数有四个,分别说明如下:
1、Initialize():允许端口控制函数,在使用端口输入输出函数之前调用一次,成功返回“1”,失败返回“0”,
2、Shutdown():关闭端口控制函数,在退出程序时执行一次,成功返回“1”,失败返回“0”,
3、GetPortVal(ByValPortAddrAsInteger,ByRefPortvalAsLong,ByValbSizeAsByte)AsBoolean:读取端口函数,PortAddr为端口地址,Portval为端口值,bSize为要读取的字节数,读取成功返回“1”,失败返回“0”,
4、SetPortVal(ByValPortAddrAsInteger,ByValPortvalAsLong,ByValbSizeAsByte)AsBoolean:写端口函数,PortAddr为端口地址,Portval为要写的值,bSize为要写入的字节数,写入成功返回“1”,失败返回“0”,
四个函数在模块中的声明如下:
DeclareFunctionInitializeWinIoLib""()AsBoolean
DeclareFunctionShutdownWinIoLib""()AsBoolean
DeclareFunctionGetPortValLib""(ByValPortAddrAsInteger,ByRefPortvalAsLong,ByValbSizeAsByte)AsBoolean
DeclareFunctionSetPortValLib""(ByValPortAddrAsInteger,ByValPortvalAsLong,ByValbSizeAsByte)AsBoolean
六、InterHEX格式文件介绍
由于一般的编译软件产生的用于写入芯片的文件都是InterHEX格式的文件,InterHEX文件属于文本文件,可以用记事本查看,一个InterHEX文件的一行称为一个记录,每个记录都是由16进制字符组成的,两个字符表示一个字节的值,InterHEX文件通常由若干条记录组成,每个记录都具有如下的形式:
:LLAAAATTDD…DDCC
“:”-是记录的起始标志
LL-记录长度,表示该记录中的数据字节数
AAAA-数据装入的首地址(16位)
TT-记录类型,00表示数据记录,01表示文件结束,(注意:有的编译软件会产生大于01的记录类型,本应用中对大于01记录类型的记录忽略掉即可)
DD-数据值(字节)
CC-校验和(将其本身与记录中除起始标志外的所有字节相加应为0,不为0则有错)
七、VB编程详细说明(由于各子程序的流程都较简单,所以直接给出源码而并未画出流程图,程序采用由底至顶的设计方法):
1,为了使用方便,我们分别写一个方便易记的输入函数及输出子程序,并且由于在很多情况下都要用到延时指令,所以我们也要写一个延时子程序(延时子程序调用WinAPI,有关方面的内容请读者参阅MSDN,此处不进行详细介绍)。
首先在“我的文档”内新建一个名为MCS51的文件夹,将、、及拷贝到MCS51文件夹。启动VB6,新建一标准EXE工程。
将工程保存在MCS51文件夹中,文件名为。在“工程”菜单中单击“添加模块”将添加到MCS51工程中。把模块中与本例无关的函数声明删除,增添延时子程序及输入输出处理代码。完成后的代码如下:
OptionExplicit
DimResultAsBoolean
DimPortvalAsLong
DeclareFunctionGetPortValLib""(ByValPortAddrAsInteger,ByRefPortvalAsLong,ByValbSizeAsByte)AsBoolean
DeclareFunctionSetPortValLib""(ByValPortAddrAsInteger,ByValPortvalAsLong,ByValbSizeAsByte)AsBoolean
DeclareFunctionInitializeWinIoLib""()AsBoolean
DeclareFunctionShutdownWinIoLib""()AsBoolean
PublicDeclareFunctionGetTickCountLib"kernel32"()AsLong
'延时TTms子程序
SubTimeDelay(TTAsLong)
DimtAsLong
t=GetTickCount()
Do
DoEvents
IfGetTickCount-t0Thent=GetTickCount
LoopUntilGetTickCount-t=TT
Sub
'将DataOut输出到地址为Address的端口子程序
PublicSubDIO_OutputByte(ByValAddressAsInteger,ByValDataOutAsInteger)
Portval=DataOut
Result=SetPortVal(Address,Portval,1)
Sub
'返回地址为Address的端口的值
PublicFunctionDIO_InputByte(ByValAddressAsInteger)AsInteger
Result=GetPortVal(Address,Portval,1)
DIO_InputByte=Portval
Function
2,在窗体上放置控件并设置控件的相关属性如下图及表所示:
3,首先编定程序起动及退出的相关代码,起动时将Timer1关闭,在Text1及Text2中显示相关提示信息,并加入允许端口操作命令,退出时发出关闭端口操作命令。双击窗体空白处,在出现的代码窗中输入如下代码:
PrivateSubForm_Load()
IfInitializeWinIo=FalseThen
MsgBox"错误,无法开启端口!"
If
=False
="*.HEX"
="请选择目标文件!"
Beep
Sub
双击“退出“按钮,在出现的代码窗中输入如下代码:
PrivateSubExit_Click()
CallShutdownWinIo
Sub
另外,为了使用方便,在代码窗的“通用”区定义打印端口基地址常数及定义一个存贮文件更新时间的变量;由于每个人的计算机配置不一样,对于快速的计算机可能需要延时同步,所以设置一个Delay延时常数。具体代码如下:
Constptraddress=H378‘此数值应根据机器的实际值填写
ConstDelay=2’当你的机器太快时加大此数值
Dimfile_date‘用于存贮文件更新时间
4,接下来我们要创建一个最基本的子程序,即字节输出子程序:
形式:outbyte(dataAsInteger)
功能:将一字节数据写入指定的单片机程序存贮器地址中,高位在前
入口:字节数据data
PrivateSuboutbyte(dataAsInteger)'输出字节
DimDelayAsInteger
DimiAsInteger
Forcon=7To0Step-1
DIO_OutputByteptraddress,2^7'输出时钟低电平,RST高
Fori=1ToDelay‘延时
Nexti
If(dataAnd2^con)=2^conThen'如果数据位为1则输出1
DIO_OutputByteptraddress,(2^7+2^5)
Fori=1ToDelay
Nexti
DIO_OutputByteptraddress,(2^7+2^5+2^4)'输出时钟高电平
Fori=1ToDelay
Nexti
DIO_OutputByteptraddress,(2^7+2^5)'输出时钟低电平
Else
DIO_OutputByteptraddress,2^7'如果数据位为0则输出0
Fori=1ToDelay
Nexti
DIO_OutputByteptraddress,(2^7+2^4)'输出时钟高电平
Fori=1ToDelay
Nexti
DIO_OutputByteptraddress,2^7'输出时钟低电平
If
Fori=1ToDelay
Nexti
Nextcon
Sub
5,根据字节输出子程序构建程序存贮器字节写入子程序
形式:w_c_b(codeaddressAsInteger,codedataAsInteger)
功能:将数据codedata写入单片机程序存贮器codeaddress地址
入口:codeaddress-程序存贮器地址
codedata-数据
此子程序兼容了AT89S53芯片的写入
PrivateSubw_c_b(codeaddressAsInteger,codedataAsInteger)'写代码字节
outbyte(((codeaddressAndHFF00)/(2^8)*8)AndHF8Or2Or((codeaddressAndH2000)/(2^11)))'合并命令与高地址字节
outbyte(codeaddressAndHFF)
outbytecodedata
Sub
6,构建读单片机程序存贮器数据函数
形式:r_c(codeaddressAsInteger)AsInteger
功能:返回单片机存器贮器地址codeaddress处的数据
入口:codeaddress-程序存贮器地址
出口:r_c返回值
PrivateFunctionr_c(codeaddressAsInteger)AsInteger'读代码字节
DimiAsInteger
Dimcon1AsInteger
DimXAsInteger
X=0
outbyte(((codeaddressAndHFF00)/(2^8)*8)AndHF8Or1Or((codeaddressAndH2000)/(2^11)))'合并命令与高地址字节
outbyte(codeaddressAndHFF)
Forcon1=7To0Step-1
DIO_OutputByteptraddress,2^7'输出时钟低电平,RST高
Fori=1ToDelay
Nexti
DIO_OutputByteptraddress,(2^7+2^4)'输出时钟高电平,RST高
Fori=1ToDelay
Nexti
If(DIO_InputByte(ptraddress+1))AndH40Then'采集数据
X=X+2^con1
If
Fori=1ToDelay
Nexti
DIO_OutputByteptraddress,2^7'输出时钟低电平
Nextcon1
r_c=X
Function
7,双击“打开文件”按钮,键入下述代码(获取目标文件的路径及文件名并保存到Text1文本框中)。
PrivateSubOpenFile_Click()'打开文件按钮
OnErrorGoToerrhandler
="*.HEX|*.hex"
=2
""Then
=
If
errhandler:
Sub
8,由于在进行任何操作之前都要发送允许编程命令,因此构建一个允许编程子程序。
功能:打开74HC244并发出允许编程命令,使芯片进入编程状态
PrivateSubStartProg()'发送串行编程命令
DIO_OutputByteptraddress,0'打开74hc244,点亮编程指示灯
TimeDelay(20)
DIO_OutputByteptraddress,2^7'设置RST为高
TimeDelay(20)
outbyteHAC
outbyteH53
outbyteH53
Sub
9,根据上面所构建的子程序及函数,可以编写出下载文件子程序的代码了。双击“下载代码”按钮,在代码窗中键入如下代码。
PrivateSubProg_Click()
ii=0
oo=0
="*.hex"=""Then
="未选择文件或文件不存在,请重新选择目标文件!"
GoToerr
If
FileNumber=FreeFile
StartProg
DoWhileNotEOF(FileNumber)
LineInputFileNumber,inbuf
IfLeft$(inbuf,1)":"Then
="非Inter格式Hex文件,请重新选择!"
GoToerr
If
'-------------------------------------------
IfVal("h"+Mid$(inbuf,8,2))1Then
GoToNEXT_LOOP
If
'--------------------------------------------
DimiAsInteger
DimoAsInteger
IfVal("h"+Mid$(inbuf,2,2))0Then
o=Val("h"+Mid$(inbuf,4,4))
Fori=10ToVal("h"+Mid$(inbuf,2,2))*2+8Step2
Ifr_c(o)Val("h"+Mid$(inbuf,i,2))Then
oo=oo+1
If
o=o+1
ii=ii+1
=Str$(ii)+"Bytes"
DoEvents
Nexti
If
NEXT_LOOP:
Loop
Ifoo=0Then
="文件检验通过"
Else
="文件检验共发现"+Str$(oo)+"字节错误!"
If
err:
DIO_OutputByteptraddress,2^3
CloseFileNumber
Beep
Sub
11,编写写保密位子程序,双击“写保密位”按钮,在代码窗中键入如下代码:
PrivateSubWriteS_Click()
DimtempAsInteger
StartProg
outbyteHAC
temp=HFF
=1Then
temp=tempAndH7F
If
=1Then
temp=tempAndHBF
If
=1Then
temp=tempAndHDF
If
outbytetemp
outbytetemp
="OK!"
TimeDelay(20)
DIO_OutputByteptraddress,2^3
Sub
12,文件更新后自动下载功能处理代码如下:
PrivateSubcheck1_click()'文件更新后自动重下载
=1Then
=True
"*.hex"""Then
file_data=FileDateTime(Text1)
If
Else
=False
If
Sub
PrivateSubTimer1_Timer()'文件是否更新检查
=False
OnerrGoToerr1
"*.hex"""Then
Iffile_dateFileDateTime(Text1)Then
Prog_Click
file_date=FileDateTime(Text1)
If
If
err1:
=True
Sub
至此,全部程序编写完成,程序能实现基本的下载、校验、写保密位及文件更新后自动重写功能。
八、结束语
虽然上述程序能实现各种基本的功能,但并不完善,并未考虑各种异常情况,读者可根据实际情况进行完善。编程功力较差的朋友可直接到笔者的网站()下载相对较完善的程序。如果充分理解了上述程序,那么DIY一个AVR及PIC单片机的开发工具也非难事。其实,在笔者的网站有“MCS51/AVR/PIC三合一下载器”供爱好者下载,之所以单独叙述MCS51开发工具,仅仅是为了叙述简单及容易理解。
参考资料:
《AT89S8252数据手册》
《利用VisualBasic实现串并行通信技术》范逸之、陈立元、孙德萱、程正孚编著
清华大学出版社2001年
《入门与提高》张树兵、戴红、陈哲、编著
清华大学出版社2001年