⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 本程序为89S52的IAP下载监控程序
💻 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 + -