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

📄 otp_wu2441.c

📁 51单片机的控制程序.是一个烧写器的控制程序.语言采用的是c51
💻 C
📖 第 1 页 / 共 2 页
字号:
#pragma	 small
#pragma	 CODE	DEBUGSYMBOLS	OBJECTEXTEND
#include	<reg52.h>
#include	<stdio.h>
#include	<absacc.h>

//#include	"lcddisplay.h"

#define DEBUG   1
#define	NEW_OTP	1	//新旧版的不同应用

#define	uchar	unsigned	char
#define	uint	unsigned	int
#define	ulong	unsigned	long



#define	CTR_WORD	XBYTE[0x8000]
#define	DATA_WR		XBYTE[0x8100]
#define	DATA_RD		XBYTE[0x8400]
#define	RST_SYS		XBYTE[0x8700]

#define	KEY				XBYTE[0x8500]
#define	LED				XBYTE[0X7000]

#define	LCD_DATA		XBYTE[0x8600]
#define	LCD_COMM		XBYTE[0x8601]
#define	POWERMANG		XBYTE[0x8200]
#define	WORK_STATE	XBYTE[0x8300]
#define	TEST_LED		XBYTE[0x8800]


#define	FLASH_SDP0	XBYTE[0x2AAA]
#define	FLASH_SDP1	XBYTE[0x5555]


#define	ROMSIZE06		2048


#define Bodrate 0xFFDC	/*	FFDC相对于11.0592M晶振下9600波特率,
														FFB8将9600的波特率降低一半,为4800*/

#define	PROGRAM_MODE	0x05	/*0101,最高位控制12V,最低位控制6.5V*/
#define	TEST_MODE			0x07	/*0111,12V电源打开,其他几个关闭*/
#define	PRO_OVER			0x0f	/*关闭编程电压*/

#define	MERG_OVER			0X0F
#define	MERG_START		0X0E
#define	MERG_PRO			0X0D
#define	MERG_VERIFY		0X0B
#define	MERG_ADD			0X07

#define	CODE_PRO			0XAA
#define	OPTION_PRO		0X55

#define	Scomm			0xee
#define	Sdata			0xdd
#define	not_ready	0x82
#define	get_ready	0x81

#define	ERROR		0x03
#define	BUSY		0x05
#define	DONE		0x06

#define	first_page		1
#define	second_page		2

/****************全局变量定义区*******************/
bit		frame_flg;
bit		wr_hl;			/*这两个位变量用来标识当前数据是高字节还是低字节,为0表示低字节,1表示高字节
										每帧数据接收完毕后,则判断帧头是否为DD,是则进入编程数据处理中,根据wr_hl作出相应动作,并将其取反*/
bit		pro_done;		/*每次操作前,将其置位,操作完成后复位*/

bit		trans;
//bit		serialtst;

bit		old_first;

sbit    P10     =       P1^0;
sbit    P11     =       P1^1;
sbit    P12     =       P1^2;
sbit    P13     =       P1^3;
sbit    P14     =       P1^4;
sbit    P15     =       P1^5;
sbit    P16     =       P1^6;
sbit    P17     =       P1^7;

uchar		SERIAL_CNT;		//计算每帧数据已接收到的个数
uchar		WORKSTATE;		/*此变量用来表示系统当前所处工作状态
												空闲:0
												查空:1
												逐BYTE:2
												全烧:3
												每次更改WORKSTATE时需查询其值,如果WORKSTATE不为0,则不能改变其状态;
												当收到结束命令的时候可以将其置为0*/
uchar		SBUF_TEMP0,SBUF_TEMP1;	//每帧数据为2,与SERIAL_CNT配合使用,如果数据接收速度过快,需要标识当前缓存是否已空。可以考虑一个结构体
uchar		DATA_WR0,DATA_WR1;
uchar		DATA_RD0,DATA_RD1;

//uchar   cnt;
uchar		cnt_t0;


uint		CUR_ADDR;			//用于记录当前操作地址

uchar xdata *flash_p = 0;	//指向对FLASH的操作




void	Delay(uint	a)
{
	while( a--) ;
}


/**********************************************************/
/*					系统初始化,硬件及所有DATA区的全局变量						*/
/**********************************************************/
/****************全局变量定义区*******************/

void	Init_All_Var(void)
{
	frame_flg=0;
	wr_hl=0;
	pro_done=0;
  trans=0;
  old_first=0;
	SERIAL_CNT=1;
	WORKSTATE=0;
	SBUF_TEMP0=0xff;
	SBUF_TEMP1=0xff;
	DATA_WR0=0xff;
	DATA_WR1=0xff;
	DATA_RD0=0xff;
	DATA_RD1=0xff;
	#if		NEW_OTP
	CUR_ADDR=0x0000;				/*CUR_ADDR 总是指向待烧写的单元	*/
	#else
	CUR_ADDR=0x0000;				/*初始化过程会先将其+1,初始化以后其地址就变成真实地址0	*/
	#endif
	P10=0;
	P11=0;
	P12=0;		/*初始化为不能访问FLASH,在P10、P11、P12均为0的时候,地址译码74146方可进行译码,
							如果需要访问FLASH,另行设置P10,P11,P12,而且需要在访问完毕后关闭对FLASH访问的使能*/

}


void	Init_Hardware(void)
{
	EX0=1;//外部中断0打开
	IT0=1;//外部中断0为下降沿触发,IT0=0,则为低电平触发
	EX1=0;//外部中断1关闭
	IT1=1;//外部中断1为下降沿触发
	//ET0=1;//定时器中断0打开
	ET0=0;//定时器中断0关闭
	ET1=0;//定时器中断1关闭,不作为串口波特率发生器,用定时器2作为波特率发生器
	//TMOD=0x00;//设置工作方式
	//TH0=0xFC; //装高八位计数初值
	//TL0=0x03; //装低八位计数初值
	IP=0x03;    //外部中断0和定时器0定义为高优先级中断
	EA=1; //允许中断

}

void	Init_Timer0(void)
{
	TMOD&=0xf0;		/*改变定时器0的定时设置为16位全计数,每次中断差不多5ms*/
	TMOD|=0x01;		/*改变定时器1的定时设置为16位全计数,每次中断差不多5ms*/
	TH0=0x0;			/*波特率对应的时间重载常数 1200波特率为e5,4800为f9,9600为fc				*/
	TL0=0x0;			/*计算公式为:             BAND=(1+SMOD)*Fosc/12/32/(256-T)				*/
	//TR0=1;				/*打开定时器中断*/
	TR0=0;				/*关闭定时器中断*/
}

#if	0

void	Init_Timer1(void)
{
	TMOD&=0x0f;		/*改变定时器1的定时设置为自重载模式,以便于进行数据通讯,先清高四位与定时器相关的位*/
	TMOD|=0x20;		/*改变定时器1的定时设置为自重载模式,以便于进行数据通讯,之后加入高四位控制字*/
	TH1=0xfd;			/*波特率对应的时间重载常数 1200波特率为e5,4800为f9,9600为fc				*/
	TL1=0xfd;			/*计算公式为:             BAND=(1+SMOD)*Fosc/12/32/(256-T)				*/
								/*  Fosc=12MHz,SMOD=0:  T=256-(1+SMOD)*Fosc/12/32/BAND					*/
								/*                        T=256-1M/32/BAND                      */
								/*                        T=256-31250/BAND                      */
	PCON&=0x7f;		/*最高位SMOD=0时波特率不加倍,1时波特率加倍*/
	TR1=0;				/*打开定时器中断*/
}
#endif

void Uart_Init(void)
{
	T2CON   = 0x35;			/*0b0011 0101 16位串行波特率发生器,
												自动重装*/
	TH2	= (unsigned char )(Bodrate>>8) ;
	TL2	= (unsigned char )(Bodrate & 0xff);
	RCAP2H  = (unsigned char )(Bodrate>>8) ;
	RCAP2L  = (unsigned char )(Bodrate & 0xff);
	TR2	= 1;					// 启动时钟
	SCON	= 0x50;			// 0b0111 1010 第一种工作方式
										// 8位单机通信
	ES	= 1;					// 允许通信中断
}

void	Init_Serial(void)	/*串口工作于方式1,(10位异步收发,由定时器控制)允许接受中断,并且波特率不加倍											*/
{
	SCON=0x50;		/*将串行口设置成工作方式1,方式1为异步传送10位数据(1个起始位加8位数据加1个停止位,无奇偶校验位)*/
                /*该方式下用于数据发送,发送波特率为: BAND=(1+SMOD)*Fosc/12/32/(256-T)                 */
                /*打开接收允许,REN=1*/
	ES=0;					/*关、打开串口中断*/
	RI=0;					/*先将中断接受标志清掉,以避免无法正常接受*/
	TI=0;
	PS=0;					/*串口中断设置为0,低优先级*/

	ES=1;                                   //*开中断,add by liu
}
/**********************************************************/
/*					系统初始化,硬件及所有DATA区的全局变量						*/
/**********************************************************/

/**********编程电压控制**********/
void	Power_Ctr(uchar	powerS)
{
	switch(powerS){
		case	PROGRAM_MODE:POWERMANG=PROGRAM_MODE;break;
		case	TEST_MODE:POWERMANG=TEST_MODE;break;
		case	PRO_OVER:POWERMANG=PRO_OVER;break;

	}
}

/*******初始化系统工作状态********/
void	Init_Worstate(void)
{
	uchar		i;
	RST_SYS=0xff;		/*CPU初始化完毕后,紧接着对逻辑部分进行长复位*///对应0x8700
	Delay(24);			/*逻辑部分长复位时间*/
	RST_SYS=0x00;		/*复位结束*/
	WORK_STATE=BUSY;/*系统指示忙于初始化*/
	Power_Ctr(PRO_OVER);	/*关闭编程电压,待编程时再打开*/
	CTR_WORD=0xF0;	/*保证PROCLK为低电平*/
	DATA_WR=0x00;
	i=DATA_RD;
	WORK_STATE=DONE;
}


/*****LOAD&地址加模式触发*****/
void	Add_Tri(uchar  a,uchar  b)
{
	Delay(3);				/*稍微延时*/
	CTR_WORD=0XF4;	/*先将CTR1置为1*/
	Delay(6);
	CTR_WORD=0XF5;	/*再将PROCLK给高*/
	Delay(2);
	DATA_WR=a;			/*将数据a写入数据寄存器后,将会一直出现在OTP数据总线上*/
	Delay(2);
	CTR_WORD=0XF4;	/*再将PROCLK给低,利用此处PROCLK的下降沿将数据LOAD到OTP中*/
	Delay(2);
	CTR_WORD=0XF5;	/*再将PROCLK给高,此时该上升沿将触发OTP内部写地址单元的增加,而在WRITE的时候,将写到增加后的单元中去*/
	Delay(2);
	DATA_WR=b;			/*将数据a写入数据寄存器后,将会一直出现在OTP数据总线上*/
	Delay(2);
	CTR_WORD=0XF4;	/*再将PROCLK给低,利用此处PROCLK的下降沿将数据LOAD到OTP中*/
	Delay(2);
	CTR_WORD=0XF0;	/*再将控制信号全部置低,进入空闲状态*/
	Delay(6);
	CUR_ADDR++;
}





void	Add_Tri1()
{
	Delay(3);				/*稍微延时*/
	CTR_WORD=0XF4;	/*先将CTR1置为1*/
	Delay(6);
	CTR_WORD=0XF5;	/*再将PROCLK给高*/
	Delay(5);
	CTR_WORD=0XF4;	/*再将PROCLK给低,利用此处PROCLK的下降沿将数据LOAD到OTP中*/
	Delay(2);
	CTR_WORD=0XF5;	/*再将PROCLK给高,此时该上升沿将触发OTP内部写地址单元的增加,而在WRITE的时候,将写到增加后的单元中去*/
	Delay(5);
	CTR_WORD=0XF4;	/*再将PROCLK给低,利用此处PROCLK的下降沿将数据LOAD到OTP中*/
	Delay(2);
	CTR_WORD=0XF0;	/*再将控制信号全部置低,进入空闲状态*/
	Delay(8);
	CUR_ADDR++;
}





/********CODE写模式触发********/
void	Write_Tri(void)
{
	Delay(3);				/*稍微延时*/
	CTR_WORD=0XF1;	/*将PROCLK置高*/
	Delay(1);
	CTR_WORD=0XF0;	/*将PROCLK置低,至此顺利产生一个正脉冲*/
	Delay(3);				/*100us的精确延时,延迟数据需要进行调整*/
	CTR_WORD=0XFC;	/*将控制信号翻转,防止编程时间过长,产生负面影响与结果*/

}


void	Write_Tri1(uchar a)//byte by byte 重烧
{
	Delay(3);				/*稍微延时*/
	CTR_WORD=0XF0;
	Delay(2);
	DATA_WR=a;			/*重新录入高8位*/
	Delay(2);
	CTR_WORD=0XF1;	/*将PROCLK置高*/
	Delay(1);
	CTR_WORD=0XF0;	/*将PROCLK置低,至此顺利产生一个正脉冲*/
	Delay(3);				/*100us的精确延时,延迟数据需要进行调整*/
	CTR_WORD=0XFC;	/*将控制信号翻转,防止编程时间过长,产生负面影响与结果,切换成11状态*/

}


/*******OPTION写模式触发*******/
void	Write_Option(void)
{
	Delay(3);				/*稍微延时*/
	CTR_WORD=0XF2;	/*将CTR2置高,准备烧写OPTION*/
	Delay(1);
	CTR_WORD=0XF3;	/*将PROCLK置高*/
	Delay(1);
	CTR_WORD=0XF2;	/*将PROCLK置低,至此顺利产生一个正脉冲*/
	Delay(3);				/*100us的精确延时,延迟数据需要进行调整*/
	CTR_WORD=0XFC;	/*将控制信号翻转,防止编程时间过长,产生负面影响与结果*/
}

/*********写下一个字节*********/
void	Pro_Byte(uchar	a,uchar  b,uchar	S_code_option)		/*此功能一次完成数据的LOAD和PROGRAM
																														针对新的OTP一次LOAD一个WORD的方式,此函数入口的a和b可以分别为低字节和高字节
																														老版本的OTP一次LOAD一个BYTE的方式,由于老版本仅用于测试,可将其设计为兼容新版本一次LOAD一个WORD的方式
																														此时仅将函数入口的a和b都给当前要烧写的字节即可,相当于将同一个BYTE的数据LOAD了两次,实际上最终LOAD进去的为后面一个字节
																														此细节参考OTP烧录原理时序
																														*/
{
	Add_Tri(a,b);
	if(S_code_option	==	CODE_PRO)		//如果输入参数为CODE_PRO,则烧写CODE区
			Write_Tri();
	else	if(S_code_option	==	OPTION_PRO)	//如果输入参数为OPTION_PRO,则烧写OPTION区
			Write_Option();
	Delay(3);	/*触发以后延时一段时间,保证该步完整执行*/
}



void	Write_Option1(uchar a)
{
	Delay(3);				/*稍微延时*/
	CTR_WORD=0XF0;
	DATA_WR=a;
	Delay(2);
	CTR_WORD=0XF2;	/*将CTR2置高,准备烧写OPTION*/
	Delay(1);
	CTR_WORD=0XF3;	/*将PROCLK置高*/
	Delay(1);
	CTR_WORD=0XF2;	/*将PROCLK置低,至此顺利产生一个正脉冲*/
	Delay(3);				/*100us的精确延时,延迟数据需要进行调整*/
	CTR_WORD=0XFC;	/*将控制信号翻转,防止编程时间过长,产生负面影响与结果*/
}




/*******完整字接收并写入子程序******/
void	Word_Pro(uchar	S_COWW)
{
	if(wr_hl==0){
		DATA_WR0=SBUF_TEMP1;	//如果wr_hl为0,则表明此帧数据为低字节数据
		wr_hl=1;									//将数据存入低字节数据缓冲后,将wr_hl置1,表示下一帧数据将是高字节
		pro_done=0;
	}
	else{
		DATA_WR1=SBUF_TEMP1;	//如果wr_hl为1,则表明此帧数据为高字节数据
		wr_hl=0;									//将数据存入高字节数据缓冲后,将wr_hl置0,表示下一帧数据将是低字节
		Pro_Byte(DATA_WR0,DATA_WR1,S_COWW);				//此时需要触发一次写,
		pro_done=1;								/*一个字烧写完(需要两个frame_flg)后,将烧写完标志置1*/
	}
}


/*****字节数据串行发送子程序*****/
void Outport(uchar i)
{
 SBUF=i;               /*准备发送的数据*/
 while (TI==0);        /*数据发送完毕自动把TI置1,此语句等待数据发送完毕*/
 TI=0;
}

/*********CODE完整字读取操作********/
void	Word_Read(void)
{
	Delay(3);
	CTR_WORD=0XF8;	/*先将CTR0置为1*/
	Delay(12);
	CTR_WORD=0XF9;	/*先将CTR0 和 PROCLK均置为1*///
	Delay(2);
	DATA_RD0=DATA_RD;	/*将低字节数据读入单片机变量DATA_RD0中*///CS[4],读otp数据送51
	Delay(2);
	CTR_WORD=0XF8;	/*读完低字节以后,将PROCLK置为0*/
	Delay(2);				/*稍微延时*/
	CTR_WORD=0XF9;	/*先将CTR0 和 PROCLK均置为1*/
	Delay(2);
	DATA_RD1=DATA_RD;/*将高字节数据读入单片机变量DATA_RD1中*/
	Delay(2);
	CTR_WORD=0XF8;	/*读完低字节以后,将PROCLK置为0*/
	Delay(2);				/*稍微延时*/
	CTR_WORD=0XF0;	/*将控制信号全恢复为空闲状态*/
	Delay(12);
}


/********OPTION完整字读取操作*******/
void	Option_Read(void)
{
	Delay(3);
	CTR_WORD=0XFA;	/*先将CTR0,CTR2置为1*/
	Delay(12);
	CTR_WORD=0XFB;	/*先将CTR0 和 PROCLK均置为1*/
	Delay(2);
	DATA_RD0=DATA_RD;/*将低字节数据读入单片机变量DATA_RD0中*/
	Delay(2);
	CTR_WORD=0XFA;	/*读完低字节以后,将PROCLK置为0*/
	Delay(2);				/*稍微延时*/
	CTR_WORD=0XFB;	/*将CTR0,CTR2 和 PROCLK均置为1*/
	Delay(2);
	DATA_RD1=DATA_RD;/*将高字节数据读入单片机变量DATA_RD1中*/
	Delay(2);
	CTR_WORD=0XFA;	/*读完低字节以后,将PROCLK置为0*/
	Delay(2);				/*稍微延时*/
	CTR_WORD=0XF0;	/*将控制信号全恢复为空闲状态*/
	Delay(12);
}


/*****开始模式触发*****/
void	Start_Tri(void)
{
	WORK_STATE=BUSY;// C51语言,翻译成汇编是将地址置为8300,8表示p2.7=1,//3等价CS[3]=0,然后将0X05送数据总线,busy那条线送低电平
	Power_Ctr(PROGRAM_MODE);		/*打开编程电压控制继电器,12V和6.5V	*/////往0x8200送0x05对应CS[2]=0,POWER_CTR[3:0]=0x05
	Delay(3600);
	Delay(3600);
	Delay(3600);
	Delay(3600);

⌨️ 快捷键说明

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