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

📄 e51pro.c

📁 AT89系列单片机ISP在线编程的AT89C2051的源代码
💻 C
字号:
//////////////////////////////////////////////////////////////////////////////////////////////////
//E51Pro.c
//Easy 51Pro编程器主程序,负责通讯,管理编程操作
///////////////////////////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////////////////////////
//2008-01-05由wangafu修改以下功能:
//适应K5i原理图
//目标芯片仅支持AT89S51/52
//烧写母片采用AT89C2051@11.0592Mhz
//增加AT89C2051为编程模式和红外模式
//编程模式下(ISP_MOD)下AT89C2051只做编程器烧写AT89S51/52
//红外模式下(IRD_MOD)下AT89C2051只做红外遥控器按键
///////////////////////////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////////////////////////////
//目前版本日期为2008-03-13
/////////////////////////////////////////////////////////////////////////////////////////////////

#include <E51Pro.h>

BYTE ComBuf[18];//串口通讯数据缓存,发送和接收都使用
UINT nAddress;//ROM中地址计数
UINT nTimeOut;//超时计数
ProWork pw;//编程器一般操作


void Delay_us(BYTE nUs)//微秒级延时<255us
{
	TH0=0;
	TL0=0;
	TR0=1;
	while(TL0<nUs)//利用T0做定时计数器,循环采样,直到达到定时值
	{
	}
	TR0=0;
}

void Delay_ms(UINT nMs)//毫秒级的延时<65535ms
{
	UINT n=0;
	TR0=1;
	while(n<nMs)////利用T0做定时计数器,循环采样,直到达到定时值
	{
		TH0=0;
		TL0=20;
		while(TH0<4)
		{
		}
		n++;
	}
	TR0=0;
}
 
BOOL WaitComm()//等待上位机的命令,18字节
{
	BYTE n=0;
	RI=0;
	while(!RI){}//等待第一个字节
	ComBuf[n]=SBUF;
	RI=0;
	n++;
	for(n;n<=17;n++)
	{
		nTimeOut=0;
		while(!RI)
		{
			nTimeOut++;
			if(nTimeOut>10000)//后17个字节都有超时限制 
				return 0;
		}
		ComBuf[n]=SBUF;
		RI=0;
	}
	return 1;
}

BOOL WaitResp()//等待上位机回应,1字节,有超时限制 
{
	nTimeOut=0;
	RI=0;
	while(!RI)
	{
		nTimeOut++;
		if(nTimeOut>50000) 
		{
			return 0;
		}
	}
	RI=0;
	ComBuf[0]=SBUF;
	return 1;
}

BOOL WaitData()//写器件时等待上位机数据,18字节,有超时限制 
{
	BYTE n;
	RI=0;
	for(n=0;n<=17;n++)
	{
		nTimeOut=0;
		while(!RI)
		{
			nTimeOut++;
			if(nTimeOut>10000)
			{
				return 0;
			}
		}
		RI=0;
		ComBuf[n]=SBUF;
	}
	return 1;
}

void SendData()//发送数据或回应操作完成,18字节
{
	BYTE n=0;
	for(n;n<=17;n++)
	{
		TI=0;
		SBUF=ComBuf[n];
		while(!TI){}
		TI=0;
	}
}

void SendResp()//回应上位机1个字节,在写器件函数中使用
{
	TI=0;
	SBUF=ComBuf[0];
	while(!TI){}
	TI=0;
}



void RstPro()//编程器复位
{
	pw.fpProOver();//直接编程结束
	SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同
}

void ReadSign()//读特征字
{
	pw.fpReadSign();
	SendData();//通知上位机,送出读出器件特征字
}

void Erase()//擦除器件
{
	pw.fpErase();
	SendData();//通知上位机,擦除了器件
}

void Write()//写器件
{
	BYTE n;
	pw.fpInitPro();//编程前的准备工作
	SendData();//回应上位机表示进入写器件状态,可以发来数据
	while(1)
	{
		if(WaitData())//如果等待数据成功
		{
			if(ComBuf[0]==0x07)//判断是否继续写
			{
				for(n=2;n<=17;n++)//ComBuf[2~17]为待写入数据块
				{
					if(!pw.fpWrite(ComBuf[n]))//<<<<<<<<<<<<<<<<<<<调用写该器件一个单元的函数
					{
						pw.fpProOver();//出错了就结束编程
						ComBuf[0]=0xff;
						SendResp();//回应上位机一个字节,表示写数据出错了
						WaitData();//等待上位机的回应后就结束
						return;	
					}
					nAddress++;//下一个单元
				}
				ComBuf[0]=1;//回应上位机一个字节,表示数据块顺利完成,请求继续
				SendResp();
			}
			else if(ComBuf[0]==0x00)//写器件结束
				break;
			else//可能是通讯出错了
			{
				pw.fpProOver();
				return;
			}
		}
		else//等待数据失败
		{
			pw.fpProOver();
			return;
		}
	}
	pw.fpProOver();//编程结束后的工作
	Delay_ms(50);//延时等待上位机写线程结束
	ComBuf[0]=0;//通知上位机编程器进入就绪状态
	SendData();
}

void Read()//读器件
{
	BYTE n;
	pw.fpInitPro();//先设置成编程状态
	SendData();//回应上位机表示进入读状态
	while(1)
	{
		if(WaitResp())//等待上位机回应1个字节
		{
			if(ComBuf[0]==0)//ComBuf[0]==0表示读结束
			{
				break;
			}
			else if(ComBuf[0]==0xff)//0xff表示重发
			{
				nAddress=nAddress-0x0010;
			}
			for(n=2;n<=17;n++)//ComBuf[2~17]保存读出的数据块
			{
				ComBuf[n]=pw.fpRead();//<<<<<<<<<<<<<<<<<<<调用写该器件一个单元的函数
				nAddress++;//下一个单元
			}
			ComBuf[0]=6;//向上位机发送读出的数据块
			SendData();
		}
		else
			break;//等待回应失败	

	}
	pw.fpProOver();//操作结束设置为运行状态
	ComBuf[0]=0;//通知上位机编程器进入就绪状态
	SendData();
}

void Lock()//写锁定位
{
	pw.fpLock();
	SendData();
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//所支持的FID,请在这里继续添加
///////////////////////////////////////////////////////////////////////////////////////////////////
//extern void PreparePro00();//FID=00:AT89C51编程器
//extern void PreparePro01();//FID=01:AT89C2051编程器

extern void PreparePro02();//FID=02:AT89S51编程器

//Only For K5i define
#define	IRD_LED	P1_1
#define ISP_LED	P1_2         //for test

#define ISP_XY	P1_3      //模式控制输出引脚 ISP_MOD : ISP_XY=0 / IRD_MOD :ISP_XY=1

#define ISP_SL  P3_2	  //模式选择输入引脚 ISP_SL=0: ISP_MOD  / ISP_SL=1:IRD_MOD

#define IRD_K1    P3_3
#define IRD_K2	  P3_4
#define IRD_K3    P3_5
#define IRD_K4    P3_7

#define T_K1    32      //K1按键按下后,IRD_LED发送的脉冲数
#define T_K2    64      //K2按键按下后,IRD_LED发送的脉冲数
#define T_K3    96      //K3按键按下后,IRD_LED发送的脉冲数
#define T_K4    128      //K4按键按下后,IRD_LED发送的脉冲数

//成品板上 ISP_SL=0: ISP_MOD  / ISP_SL=1:IRD_MOD
#define ISP_MOD  0
#define IRD_MOD  1

bit temp_ISP_SL=1;

bit temp_K1=1;
bit temp_K2=1;
bit temp_K3=1;
bit temp_K4=1;

BYTE t;

void main()
{
	SP=0x60;
	P3=0xff;

    ISP_SL=1;
    temp_ISP_SL = ISP_SL;	 //上电仅检测一次
 if(temp_ISP_SL==0)		 //ISP_MOD	 LED常亮
 {
   ISP_LED = 0;
   ISP_XY = ISP_MOD;
   
    P1_4 = 0;           //RST=1
    Delay_ms(100);
	P1_4 = 1;

//	SetVpp5V();//先初始化Vpp为5v
	SCON=0x00;
	TCON=0x00;
	//PCON=0x00;//波特率*2
	IE=0x00;
	//TMOD: GATE|C/!T|M1|M0|GATE|C/!T|M1|M0
	//        0    0   1  0   0    0   0  1
	TMOD=0x21;//T0用于延时程序
	TH1=0xff;
	TL1=0xff;//波特率28800*2,注意PCON
	//SCON: SM0|SM1|SM2|REN|TB8|RB8|TI|RI
    //        0   1   0   1   0   0  0  0
	SCON=0x50;
	TR1=1;
	Delay_ms(1000);//延时1秒后编程器自举
	ComBuf[0]=0;
	SendData();
 	while(1)//串口通讯采用查询方式
	{
		if(!WaitComm())//如果超时,通讯出错
		{
			Delay_ms(500);
			ComBuf[0]=0;//让编程器复位,使编程器就绪
		}
		switch(ComBuf[1])//根据FID设置(ProWork)pw中的函数指针
		{
		//K5i及AT89S51不需要,故注销
		/*	
			case 0://at89c51编程器
				PreparePro00();
				break;
			case 1://at89c2051编程器
				PreparePro01();
				break;
		 */
			case 2://at89s51编程器
				PreparePro02();
				break;
			//case 3:支持新器件时,请继续向下添加
			//	break;
			//case 4:
			//	break;
			default:
				ComBuf[0]=0xff;
				ComBuf[1]=0xff;//表示无效的操作
				break;
		}
		switch(ComBuf[0])//根据操作ID跳到不同的操作函数
		{
			case 0x00:
				RstPro();//编程器复位
				break;
			case 0x01:
				ReadSign();//读特征字
				break;
			case 0x02:
				Erase();//擦除器件
				break;
			case 0x03:
				Write();//写器件
				break;
			case 0x04:
				Read();//读器件
				break;
			case 0x05:
				Lock();//写锁定位
				break;
			default:
				SendData();
				break;
		}
	}
  }

else            //IRD_MOD
 {
  ISP_LED = 1;
  ISP_XY = IRD_MOD;
  
  IRD_K1=1;
  IRD_K2=1;
  IRD_K3=1;
  IRD_K4=1;
  

  while(1)
   {
   	Delay_ms(500);
	ISP_LED =~ISP_LED;
	temp_K1=IRD_K1;
	temp_K2=IRD_K2;
	temp_K3=IRD_K3;
	temp_K4=IRD_K4;
//按键K1处理	
	if(temp_K1==0)
	{
	    ISP_LED = 0;
		IRD_LED = 1;
		Delay_ms(10);
		temp_K1=IRD_K1;
	 	if(temp_K1==0)  //10ms延时去抖
	 	  
		  {for(t=1;t<=T_K1;t++)
		   {
		    IRD_LED = ~IRD_LED;
			Delay_us(1);
			}
		   }
		  
		  temp_K1=IRD_K1;
		  while(temp_K1==0)//查询按键有没有松开
		    {temp_K1=IRD_K1;}
		 IRD_LED=1;
		 ISP_LED=1;
	 }
	 
//按键K2处理	
	if(temp_K2==0)
	{
	    ISP_LED = 0;
		IRD_LED = 1;
		Delay_ms(10);
		temp_K2=IRD_K2;
	 	if(temp_K2==0)  //10ms延时去抖
	 	  
		  {for(t=1;t<=T_K2;t++)
		   {
		    IRD_LED = ~IRD_LED;
			Delay_us(1);
			}
		   }
		  
		  temp_K2=IRD_K2;
		  while(temp_K2==0)//查询按键有没有松开
		    {temp_K2=IRD_K2;}
		 IRD_LED=1;
		 ISP_LED=1;
	 }

///按键K3处理	
	if(temp_K3==0)
	{
	    ISP_LED = 0;
		IRD_LED = 1;
		Delay_ms(10);
		temp_K3=IRD_K3;
	 	if(temp_K3==0)  //10ms延时去抖
	 	  
		  {for(t=1;t<=T_K3;t++)
		   {
		    IRD_LED = ~IRD_LED;
			Delay_us(1);
			}
		   }
		  
		  temp_K3=IRD_K3;
		  while(temp_K3==0)//查询按键有没有松开
		    {temp_K3=IRD_K3;}
		 IRD_LED=1;
		 ISP_LED=1;
	 }

//按键K1处理	
	if(temp_K4==0)
	{
	    ISP_LED = 0;
		IRD_LED = 1;
		Delay_ms(10);
		temp_K4=IRD_K4;
	 	if(temp_K4==0)  //10ms延时去抖
	 	  
		  {for(t=1;t<=T_K4;t++)
		   {
		    IRD_LED = ~IRD_LED;
			Delay_us(1);
			}
		   }
		  
		  temp_K4=IRD_K4;
		  while(temp_K4==0)//查询按键有没有松开
		    {temp_K4=IRD_K4;}
		 IRD_LED=1;
		 ISP_LED=1;
	 }
 //查询按键完毕
   }
 }
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -