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

📄 bootldr.c

📁 根据HI-TECH PICC18原版BOOTLOADER改进的适合PIC18F4580的BOOTLOADER程序。对HEX文件有要求
💻 C
📖 第 1 页 / 共 2 页
字号:
void table_write(void)
 {
	if(DO_NOT_INCREMENT)		// 地址已经载入 TBLPTR, 不需要预先增加
	asm("tblwt*");				// 不修改TBLPTR,短周期写操作
	else
	asm("tblwt+*");				// TBLPTR在写前递增,短周期写操作
	DO_NOT_INCREMENT=0;			// 第二次开始,TBLPTR在写前递增
}

/*============================================================================
							写8字节缓冲区到 FLASH
============================================================================*/
void flash16(void)
{	
	unsigned char j;
	if(DO_NOT_INCREMENT)			// 地址已经载入TBLPTR
	TBLPTRL&=0xF0;					// TBLPTRL的低4位清0(16字节为1块)

for(j=0;j<4;j++)
{
	if(DO_NOT_INCREMENT)			// 地址已经载入TBLPTR
	TBLPTRL&=0xF0;					// TBLPTRL的低3位清0(16字节为1块)
	for(index=0;index<16;)			// 一共写16个字节
	{	
		TABLAT = buff[index++];		// 程序存储器表锁存
		table_write();				// 写1个字节
	}
	DO_NOT_INCREMENT=1;
	WREN=1;			// 允许闪存程序/数据EEPROM的写周期
	EECON2=0x55;	// 向EECON2写入0x55,必须执行的步骤
	EECON2=0xAA;	// 向EECON2写入0xAA,必须执行的步骤
	WR=1;			// 启动数据EEPROM擦写周期或程序存储器擦写周期
//	zap();			// 启动闪存程序写入(长周期写操作)
}
	while(WR);		// 等待写入结束
	WREN=0;			// 禁止闪存程序/数据EEPROM的写周期
	
	NOP();
	NOP();

}

/*============================================================================
							  填充清除字节
============================================================================*/
void clear_buffer(void)
{
	buff[0] 	= buff[1] 	= buff[2] 	= buff[3]	=FILL_BYTE;	
	buff[4] 	= buff[5] 	= buff[6] 	= buff[7]	=FILL_BYTE;	
	buff[8] 	= buff[9] 	= buff[10] 	= buff[11]	=FILL_BYTE;	
	buff[12] 	= buff[13] 	= buff[14] 	= buff[15]	=FILL_BYTE;	
}

/*============================================================================
								主程序
============================================================================*/
void main(void)
{
	init_comms();					// 初始化串口

	puts(START_MSG);
	
	INTCON3	=0;						// 禁止其他中断
	PIE2	=0;						// 禁止其他中断
	INTCON	=0;						// 禁止所有中断
	RD1=1;
//----------------------------------------------------------------------------
	T0CON 	=0x96;					// 采用1:128的分频
	TMR1H	=0x67;					// 使用这个值产生1秒延时
	TMR1L	=0x60;					
	for(delay_time=BOOT_TIMEOUT; delay_time ; --delay_time)
		{
			if (RCIF)				//这里可以加一些条件限制的
			break;
			puts(DOWNLOAD_MSG);		//  给用户一个倒数计秒
			putch('0'+delay_time);  //	显示ASCLL码
			while(!TRMT);
			TXREG='\r';
			while(!TMR0IF);			// 等待定时器0超时
			TMR0IF=0;
			TMR1H=0x67;				// 使用这个值产生1秒延时
			TMR1L=0x60;
		}
	
	T0CON=0x00;						// 再次停止定时器
	RD1=0;
/*******************************************************************************
* 如果串口没有响应,Bootloader 将等待一个设定的时间后,运行原来的固有的程序
*******************************************************************************/

	if (!RCIF)		// 如果没有下载到HEX文件, 恢复运行原来程序
		{
			(*((void(*)(void))PROG_START))();
		}
//==============================================================================
	puts(FILE_MSG);		// 立即请求你下载一个新的程序
		
	TBLPTRU=0;			// 表指针最高字节=0
	erase=PROG_START;	// PROG_START=0x400
	
	while(1)			//清除原来的程序,准备下载的程序使用
	{
		TBLPTRL=(unsigned char)erase;		// 闪存表指针低字节=0x400
		TBLPTRH=(unsigned char)(erase>>8);  // 闪存表指针高字节=0x04
		EECON1=0x90;						// 准备FLASH删除
		zap();								// 启动闪存程序写入(长周期写操作)
		erase+=64;
//----------------------------------------------------------------------------
#ifdef UPPER_ADDRESS_BYTE					// 高位地址
		if(CARRY)							// 闪存表指针低字节溢出(+64后)
			TBLPTRU++;						// 闪存表指针高字节+1
		if(TBLPTRU==UPPER_ADDRESS_BYTE)
#endif
		if(erase==MEM_TOP)
		break;
	}
//----------------------------------------------------------------------------
#ifdef 	UPPER_ADDRESS_BYTE					// 高位地址
		TBLPTRU=0;							// 表指针最高字节=0
#endif

/*****************************************************************************************
* 					通过串口接收HEX文件,然后写到程序空间
*****************************************************************************************/
	for(;;)									// l循环
		{
			while (RCREG!=':');				// 等待 HEX 文件开始
											// :冒号是每一条Intel HEX记录的开始
			putch(':');						// 输出到上位机字符':'
			cksum   = bcount  = g2x();		// 取数据长度
											// :冒号后面是一个字节的数据长度
			EEADRH  = TBLPTRH = g2x();		// 接着是高位地址
			EEADR   = TBLPTRL = g2x();		// 接着是地位地址
		
			DO_NOT_INCREMENT = 1;			// 地址已经载入TBLPTR,不需要预先增加
			rectype = g2x();				// 接着是数据类型

//****************************************************************************************		
			switch(rectype)					// 根据取数据类型
				{
					case DATA:				// 数据记录DATA=0 
//---------------------------------------------------------------------------------------
					if( (FLASH) && (TBLPTRU==0) && (TBLPTRH < (unsigned char)(PROG_START>>8)) )	
					break;	   // 保护bootloader避免被改写,高位地址<PROG_START>>8,退出
//---------------------------------------------------------------------------------------
					clear_buffer();			// 缓冲区16字节全部填充0xFF
					while(bcount--)
						{	
							TABLAT = EEDATA = buff[(EEADR&0xF)] = g2x();	// 取数据
							                //将数据依次读到buff[0]-buff[15]
							
							if((CONFIG)||(EEPROM))			// 如果是配置或EEPRON
								{
									if(CONFIG)				// 配置字节 
									table_write();			// 每次写1个字节
									zap();					// EEPROM不写
								}
							else							// 程序每次写8个字节
								if((EEADR&0xF)==15)			// 到第16个字节了
									{
										flash16();			// 每次写16个字节
										clear_buffer();		// 清除缓冲
									}
							EEADR++;
						}	

					if(((EEADR&0x0F)!=0)&&(FLASH))			// 写最后非满16个字节FLASH
                	flash16();								// 由于前面没有写
					checksum();								// 接收校验字节并检查校验和
					break;
//--------------------------------------------------------------------------------------
					case END:								// 文件结束END=1
					checksum();								// 接收校验字节并检查校验和
					puts(SUCSESS_MSG);						// 提示升级成功
    				(*((void(*)(void))PROG_START))();		// 运行新程序
					break;
//---------------------------------------------------------------------------------------
					case EXTEND_ADDRESS:		// 扩展地址记录 EXTEND_ADDRESS=4
					while(bcount--)			// EE\Config\ID?
						{
							EEADR=g2x();	// 2字节的扩展地址,先高后低,实际用低的
						}
					EEPGD=1;				// 先默认EEPGD=1,访问闪速程序存储器
				
					if(EEADR==0xF0)			// 只有 EEPGD=0,CFGS=0
					EEPGD=0;				// 访问数据EEPROM					
					CFGS=0;

					if((EEADR&0xF0)==0x30)	// 只要CFGS=1,就	
					CFGS=1;					// 访问配置寄存器				
					TBLPTRU=EEADR;

					checksum();				// 接收校验字节并检查校验和
					break;
//---------------------------------------------------------------------------------------
				}//switch(rectype)
		}//for(;;)
}//void main(void)

⌨️ 快捷键说明

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