📄 main.c
字号:
//**********************************************************************************
//本函数模块89S52的IAP下载监控程序,作者聂小猛(丁丁),主页地址http://www.mcu51.com
//本程序为89S52的IAP下载监控程序,可使用89C2051,89C51,89C52等等51单片机做监控芯片。
//P10-P13接89s52的IAP接口,具体见程序中的定义。
//监控芯片的串口经232电平转换接电脑串口,计算机使用串口调试工具控制烧写过程,如sscom32。
//本工具操作简单,只需按照监控程序返回到计算机的提示操作即可。
//本工具有检测设备连接,烧写,擦除,读出,复位目标单片机运行,等功能。
//本工具可以从程序运行状态直接进行烧写等动作,烧完后发指令直接运行,可用在远程升级场合。
//本工具烧写速度极快,通讯波特率38400bps,烧写整片89s52的8K程序仅需5.7秒!
//"51单片机世界"版权所有,未经允许,不得抄袭作为商业用途!
//**********************************************************************************
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#include <reg52.h>
//定义控制IAP烧写的IO脚
sbit SRST=P1^0; //控制器发出复位信号
sbit SCLK=P1^1; //控制器发出时钟信号
sbit SDOUT=P1^3; //控制器发出命令
sbit SDIN=P1^2; //控制器接收数据
extern char getbyte(void);//从串口取一个字节
extern putbyte(char c);//发送一个字节
extern putstring(uchar *puts);//发送一个字符串到串口
extern puthex(uchar c);//发送一个字节的hex码,分成两个字节发。
#define CR putstring("\r\n")//发送一个回车换行
extern void serial_init (void);
uchar code help[]="\r\n\r\nISP of AT89S52 bye DingDing(丁丁),WWW.MCU51.COM"
"\r\n-----------------------------------------------"
"\r\n'r'-read eprom"
"\r\n'w'-write data to 89S52"
"\r\n'e'-chip erase"
"\r\n'g'-Run 89s52\r\n\r\n";
//**************************************
//使能ISP,同时检测设备是否准备好
uchar bdata DATAOUT;
sbit BITOUT=DATAOUT^7;
sbit BITIN=DATAOUT^0;
void enable(void)
{
uchar i;
uint n;
P1=0xff;
SCLK=0;
SRST=0;
for(n=0;n<1000;n++);
SRST=1; //拉高S52的RST脚
for(n=0;n<1000;n++);
DATAOUT=0xac;//10101100
for(i=0;i<8;i++)
{
SDOUT=BITOUT;
SCLK=1;SCLK=1;
SCLK=0;SCLK=0;
DATAOUT=DATAOUT<<1;
}
DATAOUT=0x53;//01010011
for(i=0;i<8;i++)
{
SDOUT=BITOUT;
SCLK=1;SCLK=1;
SCLK=0;SCLK=0;
DATAOUT=DATAOUT<<1;
}
for(i=0;i<8;i++)
{
SCLK=1;SCLK=1;
SCLK=0;SCLK=0;
}
for(i=0;i<8;i++)
{
DATAOUT=DATAOUT<<1; //移位8次取到采样的值
BITIN=SDIN;
SCLK=1;SCLK=1;
SCLK=0;SCLK=0;
}
if(DATAOUT==0x69)putstring("89S52 device ready! \r\n");
else putstring("Device ERROR!!!!!!!!!!!!! \r\n");
}
//********************************
//片擦
void chiperase(void)
{
uchar i;
ulong n;
DATAOUT=0xac;//10101100
for(i=0;i<8;i++)
{
SDOUT=BITOUT;
SCLK=1;SCLK=1;
SCLK=0;SCLK=0;
DATAOUT=DATAOUT<<1;
}
DATAOUT=0x80;//100XXXXX
for(i=0;i<8;i++)
{
SDOUT=BITOUT;
SCLK=1;SCLK=1;
SCLK=0;SCLK=0;
DATAOUT=DATAOUT<<1;
}
for(i=0;i<16;i++)
{
SCLK=1;SCLK=1;
SCLK=0;SCLK=0;
}
for(n=0;n<0x2000;n++);
putstring("Erased OK!\r\n");
}
//*********************************
//读89s52中的内容并输出到串口
readeprom()
{
uchar i;
uint n,n_all;
for(n_all=0;n_all<0x2000;)
{
DATAOUT=0x30;//00110000
for(i=0;i<8;i++)
{
SDOUT=BITOUT;
SCLK=1;SCLK=1;
SCLK=0;SCLK=0;
DATAOUT=DATAOUT<<1;
}
DATAOUT=n_all/256;//XXX00000
for(i=0;i<8;i++)
{
SDOUT=BITOUT;
SCLK=1;SCLK=1;
SCLK=0;SCLK=0;
DATAOUT=DATAOUT<<1;
}
for(n=0;n<256;n++)
{
for(i=0;i<8;i++)
{
DATAOUT=DATAOUT<<1; //移位8次取到采样的值
BITIN=SDIN;
SCLK=1;SCLK=1;
SCLK=0;SCLK=0;
}
if(n%16==0){CR;puthex(n_all/256);puthex(n_all%256);putbyte(':');}
puthex(DATAOUT);
n_all++;
}
if(RI){getbyte();putstring(help);return;}
}
putstring(help);
}
//***********************************
//将两个HEX字节转换成一个字节 (2 hexbytes = 1 byte)
uchar code hex_c[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,10,11,12,13,14,15};
uchar hextochar(uchar c0,c1)
{
return((hex_c[c0-0x30]<<4)+hex_c[c1-0x30]);
}
//****************************************************
//从串口接收HEX文件并写入单片机
loadfile()
{
uchar c1,c0,i,n_of_line;
union {uint addrhl;struct {uchar h,l;}addr;} idata address; //定义现在写入的地址
union {uint addrhl;struct {uchar h,l;}addr;} idata addressall; //定义已经写入的总数
unsigned char free[8]; //定义行首处理空间
chiperase();
putstring("\r\n请发送您要烧的HEX文件!");
while (!(getbyte()==':')); //等待下一行开始
addressall.addrhl=0; //已经写入的总数清0
for(i=0;i!=8;i++) //读取第一行的行首,8字节
{
free[i]=getbyte();
}
n_of_line=hextochar(free[0],free[1]); //分析行首,解出行字节总数及行首址
address.addr.h=hextochar(free[2],free[3]); //高位地址
address.addr.l=hextochar(free[4],free[5]); //底位地址
do //大循环,行总数为0时停止,此时文件结束
{
do //小循环,每行一个循环
{
c1=getbyte();c0=getbyte(); //取两个HEX数据
c0=hextochar(c1,c0);
addressall.addrhl++; //已经写入的地址加1
DATAOUT=0x40;//01000000
for(i=0;i<8;i++)
{
SDOUT=BITOUT;
SCLK=1;SCLK=1;
SCLK=0;SCLK=0;
DATAOUT=DATAOUT<<1;
}
DATAOUT=address.addr.h;
for(i=0;i<8;i++)
{
SDOUT=BITOUT;
SCLK=1;SCLK=1;
SCLK=0;SCLK=0;
DATAOUT=DATAOUT<<1;
}
DATAOUT=address.addr.l;
for(i=0;i<8;i++)
{
SDOUT=BITOUT;
SCLK=1;SCLK=1;
SCLK=0;SCLK=0;
DATAOUT=DATAOUT<<1;
}
DATAOUT=c0;
for(i=0;i<8;i++)
{
SDOUT=BITOUT;
SCLK=1;SCLK=1;
SCLK=0;SCLK=0;
DATAOUT=DATAOUT<<1;
}
//for(t=0;t<120;t++);
address.addrhl++;//现在写入的地址加1
n_of_line--; //该行剩下的字节减一
}while(n_of_line!=0); //写完一行退出该循
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -