#define IAP_READ_Command 0x01 /* 字节读应用程序区和数据存储区 */
#define IAP_PROGRAM_Command 0x02 /* 字节编程应用程序区和数据存储区 */
#define IAP_SECTOR_ERASE_Command 0x03 /* 扇区擦除应用程序区和数据存储区 */
/*************************************************************************************************************************/
/* 复位程序从AP区切换到ISP区运行 */
#if reset_from_AP_to_ISP_EN || BOOT_ADR == 0
void reset_from_AP_to_ISP(void)
{
IAP_CONTR = 0x60; /* 0110,0000 */
_nop_();
}
#endif
/* 复位程序从ISP区切换到AP区运行 */
#if reset_from_ISP_to_AP_EN
void reset_from_ISP_to_AP(void)
{
IAP_CONTR = 0x20; /* 0010,0000 */
_nop_();
}
#endif
/* 打开 ISP,IAP 功能 */
#if sector_erase_EN || byte_program_EN || byte_read_EN
void IAP_enable(void)
{
ea_tmp = EA; /* 临时保存中断状态 */
EA = 0; /* 关中断 */
IAP_CONTR = IAP_CONTR & 0x18; /* 0001,1000 */
IAP_CONTR = IAP_CONTR | WAIT_TIME;
IAP_CONTR = IAP_CONTR | 0x80; /* 1000,0000 */
}
#endif
/* 关闭 ISP,IAP 功能 */
#if sector_erase_EN || byte_program_EN || byte_read_EN
void IAP_dISAble(void)
{
IAP_CONTR = IAP_CONTR & 0x7f; /* 0111,1111 */
IAP_CMD = 0;
IAP_ADDRH = 0xff;
IAP_ADDRL = 0xff;
IAP_TRIG = 0x00;
EA = ea_tmp; /* 恢复中断状态 */
}
#endif
/* 擦除1扇区(512字节) */
#if sector_erase_EN
void sector_erase(unsigned int destAddr)
{
IAP_ADDRH = (destAddr>>8) & 0xfe; /* 1111,1110,0000,0000; 取扇区地址 */
IAP_ADDRL = 0x00;
IAP_CMD = IAP_CMD & 0xf8; /* 1111,1000 */
IAP_CMD = IAP_CMD | IAP_SECTOR_ERASE_Command; /* 0000,0011 */
IAP_enable();
IAP_TRIG = 0x5a; /* 触发IAP_IAP命令 */
IAP_TRIG = 0xa5; /* 触发IAP_IAP命令 */
_nop_();
IAP_disable();
}
#endif
/* 写1字节 */
#if byte_program_EN
void byte_program(unsigned int destAddr, unsigned char dataByte)
{
IAP_ADDRH = destAddr >> 8;
IAP_ADDRL = destAddr & 0xff;
IAP_CMD = IAP_CMD & 0xf8; /* 1111,1000 */
IAP_CMD = IAP_CMD | IAP_PROGRAM_Command; /* 0000,0010 */
IAP_DATA = dataByte;
IAP_enable();
IAP_TRIG = 0x5a; /* 触发IAP_IAP命令 */
IAP_TRIG = 0xa5; /* 触发IAP_IAP命令 */
_nop_();
IAP_disable();
}
#endif
/* 读1字节 */
#if byte_read_EN
unsigned char byte_read(unsigned int byte_addr)
{
#if 1 /* IAP芯片,数据与程序混合的,可以不用IAP直接读数据 */
unsigned char code * pcadr;
pcadr=byte_addr;
return(pcadr[0]);
#else
IAP_ADDRH = byte_addr >> 8;
IAP_ADDRL = byte_addr & 0xff;
IAP_CMD = IAP_CMD & 0xf8; /* 1111,1000 */
IAP_CMD = IAP_CMD | IAP_READ_Command; /* 0000,0001 */
IAP_enable();
IAP_TRIG = 0x5a; /* 触发IAP_IAP命令 */
IAP_TRIG = 0xa5; /* 触发IAP_IAP命令 */
_nop_();
IAP_disable();
return (IAP_DATA);
#endif
}
#endif
/***********************************************************************************/
/* 进入在线升级监控程序 */
#if f_boot_EN
void f_boot(void)
{ void (* pc_boot)(void);
EA=0;
if(WDT_CONTR&0x20) WDT_CONTR=0x3f; /* 如果看门狗是开启的,则最长时间喂狗 */
//#if BOOT_ADR == 0
// reset_from_AP_to_ISP(); /* 不是IAP芯片,进固化的ISP程序 */
//#else
pc_boot = BOOT_ADR; /* 在线升级监控程序地址 */
pc_boot(); /* 进入在线升级监控程序 */
//#endif
}
#endif
/***********************************************************************************/
/* TEST用户程序演示
魏东( tonywei@tom.com ) 2009-6-25
IAP11F62X,频率:22.1184MHz(1T超高速 单片机 )
*/
#include "STC11Fxx.H"
#include "IAP_11_10.h"
#include <intrins.h>
#include <stdio.h>
#define CON_OSC 22118400 /* 振荡频率(1T超高速外部22.1184MHz) */
#define CON_BPS 256 - ( CON_OSC / 1 / 32 / 115200 ) /* 115.2kBPS时间常数(T1x12=1) */
#define CON_MSH ( 65536 - CON_OSC / 12 / 100 ) / 256 /* 10mS时间常数高字节 */
#define CON_MSL ( 65536 - CON_OSC / 12 / 100 ) % 256 /* 10mS时间常数低字节 */
#define CON_CTO 250 / 10 /* 设置串口指令最大间隔时间(10mS单位) */
sbit P_KEY1 = P1^0; /* 输入按键1状态(0:按下) */
sbit P_KEY2 = P1^1; /* 输入按键2状态(0:按下) */
unsigned char com_cur; /* 串口接收到的字节(本次) */
unsigned char com_old; /* 串口接收到的字节(上次) */
unsigned char com_timer; /* 串口数据间隔超时计算 */
unsigned char ms_timer; /* 10mS计时器 */
bit sec_id; /* 每秒发生 */
bit com_out; /* 串口发送完毕标志 */
bit com_in; /* 串口接收到数据标志 */
bit boot_id=0; /* 进入监控程序升级 */
/***********************************************************************************/
/* INT0外部中断(未用) */
int_0() interrupt 0
{
EX0=0; /* 禁止INT0中断 */
}
/* T0中断(10mS定时器) */
timer_int () interrupt 1
{
TH0=CON_MSH; /* 10mS时间常数 */
TL0=CON_MSL; /* 10mS时间常数 */
if(com_timer) com_timer--; /* 串口超时计数器 */
ms_timer++; /* 10mS计时器 */
if(ms_timer>100)
{ sec_id=1; /* 每秒发生 */
ms_timer=0;
}
}
/* INT1外部中断(未用) */
int1_int () interrupt 2
{
EX1=0; /* 禁止INT1中断 */
}
/* T1定时器中断(未用) */
timer1_int () interrupt 3 /* T1作为串口波特率发生器不产生中断 */
{
ET1=0; /* 禁止T1中断 */
}
/* 串口中断 */
com_int() interrupt 4
{ if(TI) /* 发送产生的中断 */
{ TI=0;
com_out=1; /* 串口发送完毕标志 */
}
if(RI) /* 接收产生的中断 */
{ RI=0;
com_old=com_cur;
com_cur=SBUF;
if(com_timer) /* 没有超过间隔时间连续字节有效 */
{ if((com_old==0x5a)&&(com_cur==0x7a)) boot_id=1; /* 特殊指令5A,7A则进入监控程序升级 */
}
com_timer=CON_CTO; /* 重新计时 */
com_in=1; /* 串口接收到数据标志 */
}
}
/* LVD中断() */
lvd_int() interrupt 6
{
ELVD=0; /* 禁止低压LVD中断 */
}
/***********************************************************************************/