STC的IAP功能使用

 

以一些资料源自mcuol.com的xiaoxiaopig博客里面,http://blog.mcuol.com/User/xiaoxiaopig/Article/38135_1.htm,在此声明,如有意见,请立该联系处理。有空要加为好友∧_∧


 STC89C51、52内部都自带有2K字节的EEPROM,54、55和58都自带有16K字节的EEPROM,STC单片机是利用IAP技术实现的EEPROM,内部Flash擦写次数可达100,000 次以上,先来介绍下ISP与IAP的区别和特点。

知识点:ISP与IAP介绍
    ISP:In System Programable 是指在系统编程,通俗的讲,就是片子已经焊板子上,不用取下,就可以简单而方便地对其进行编程。比如我们通过电脑给STC单片机下载程序,或给AT89S51单片机下载程序,这就是利用了ISP技术。
IAP:In Application Programable 是指在应用编程,就是片子提供一系列的机制(硬件/软件上的)当片子在运行程序的时候可以提供一种改变flash数据的方法。通俗点讲,也就是说程序自己可以往程序存储器里写数据或修改程序。这种方式的典型应用就是用一小段代码来实现程序的下载,实际上单片机的ISP功能就是通过IAP技术来实现的,即片子在出厂前就已经有一段小的boot程序在里面,片子上电后,开始运行这段程序,当检测到上位机有下载要求时,便和上位机通信,然后下载数据到存储区。大家要注意千万不要尝试去擦除这段ISP引导程序,否则恐怕以后再也下载不了程序了。
STC单片机内部有几个专门的特殊功能寄存器负责管理ISP/IAP功能的,见表1。
表1 ISP/IAP相关寄存器列表
名称
地址
功能描述
D7
D6
D5
D4
D3
D2
D1
D0
复位值
ISP_DATA
E2h
Flash数据寄存器
1111 1111
ISP_ADDRH
E3h
Flash高字节地址寄存器
0000 0000
ISP_ADDRL
E4h
Flash低字节地址寄存器
0000 0000
ISP_CMD
E5h
Flash命令模式寄存器
--
--
--
--
--
MS2
MS1
MS0
xxxx x000
ISP_TRIG
E6h
Flash命令触发寄存器
xxxx xxxx
ISP_CONTR
E7h
ISP/IAP 控制寄存器
ISPEN
SWBS
SWRST
--
--
WT2
WT1
WT0
000x x000
ISP_DATA:ISP/IAP操作时的数据寄存器。
ISP/IAP从Flash读出的数据放在此处,向Flash写入的数据也需放在此处。
ISP_ADDRH:ISP/IAP操作时的地址寄存器高八位。
ISP_ADDRL:ISP/IAP操作时的地址寄存器低八位。
ISP_CMD:ISP/IAP操作时的命令模式寄存器,须命令触发寄存器触发方可生效。命令模式如表2所示。
表2 ISP_CMD寄存器模式设置
D7
D6
D5
D4
D3
D2
D1
D0
模式选择
保留
命令选择
--
--
--
--
--
0
0
0
待机模式,无ISP操作
--
--
--
--
--
0
0
1
对用户的应用程序flash区及数据flash区字节读
--
--
--
--
--
0
1
0
对用户的应用程序flash区及数据flash区字节编程
--
--
--
--
--
0
1
1
对用户的应用程序flash区及数据flash区扇区擦除
程序在系统ISP程序区时可以对用户应用程序区/数据Flash区(EEPROM)进行字节读/字节编程/扇区擦除;程序在用户应用程序区时,仅可以对数据Flash区(EEPROM)进行字节读/字节编程/扇区擦除。STC89C51RC/RD+系列单片机出厂时已经固化有ISP引导码,并设置为上电复位进入ISP程序区,并且出厂时就已完全加密。
ISP_TRIG:ISP/IAP操作时的命令触发寄存器。
在ISPEN(ISP_CONTR.7) =1时,对ISP_TRIG 先写入46h,再写入B9h,ISP/IAP命令才会生效。
STC89C52RC,STC89LE52RC单片机内部可用Data Flash(EEPROM)的地址如表3所示,其它型号单片机请查阅相关资料。
表3 STC89C52RC、STC89LE52RC单片机内部EEPROM地址表
第一扇区
第二扇区
第三扇区
第四扇区
起始地址
结束地址
起始地址
结束地址
起始地址
结束地址
起始地址
结束地址
2000H
21FFH
2200H
23FFH
2400H
25FFH
2600H
27FFH
第五扇区
第六扇区
第七扇区
第八扇区
起始地址
结束地址
起始地址
结束地址
起始地址
结束地址
起始地址
结束地址
2800H
29FFH
2A00H
2BFFH
2C00H
2DFFH
2E00H
2FFFH
每个扇区为512字节,建议大家在写程序时,将同一次修改的数据放在同一个扇区,方便修改,因为在执行擦除命令时,一次最少要擦除一个扇区的数据(需要提供扇区的首地址),每次在更新数据前都必须要擦除原数据方可重新写入新数据,不能直接在原来数据基础上更新内容。
     注意:上面的是数据存储区的地址,程序存储区地址是从0~1FFF,共8K,程序区只能是ISP编程。

以下是自己写的这部分功能代码,因为风格问题,不太喜欢原著代码,感觉自己的还严谨一点。


/****************************************************************************/
/*                           IAP驱动                                        */
/****************************************************************************/


/************************************************************************************************************************/
/* ISP/IAP相关寄存器列表 */
/* 名称 地址 功能描述 D7 D6 D5 D4 D3 D2 D1 D0 复位值 */
/* ISP_DATA E2h Flash数据寄存器 1111 1111 */
/* ISP_ADDRH E3h Flash高字节地址寄存器 0000 0000 */
/* ISP_ADDRL E4h Flash低字节地址寄存器 0000 0000 */
/* ISP_CMD E5h Flash命令模式寄存器 -- -- -- -- -- MS2 MS1 MS0 xxxx x000 */
/* ISP_TRIG E6h Flash命令触发寄存器 xxxx xxxx */
/* ISP_CONTR E7h ISP/IAP 控制寄存器 ISPEN SWBS SWRST -- -- WT2 WT1 WT0 000x x000 */
/************************************************************************************************************************/


/************************************************************************************/
/* ISP_CMD寄存器模式设置 */
/* D7 D6 D5 D4 D3 D2 D1 D0 模式选择 */
/* 保留 命令选择 */
/* -- -- -- -- -- 0 0 0 待机模式,无ISP操作 */
/* -- -- -- -- -- 0 0 1 对用户的应用程序flash区及数据flash区字节读 */
/* -- -- -- -- -- 0 1 0 对用户的应用程序flash区及数据flash区字节编程 */
/* -- -- -- -- -- 0 1 1 对用户的应用程序flash区及数据flash区扇区擦除 */
/************************************************************************************/

/*在ISPEN(ISP_CONTR.7) =1时,对ISP_TRIG 先写入46h,再写入B9h,ISP/IAP命令才会生效。*/


/* 定义常量 */
#define ERROR   0
#define OK      1

/* 定义Flash 操作等待时间 */
//#define WAIT_TIME   0x00     //mcu clock 40mhz
//#define WAIT_TIME   0x01     //mcu clock 20mhz
//#define WAIT_TIME   0x02     //mcu clock 10mhz
#define WAIT_TIME   0x03     //mcu clock 5mhz

sfr ISP_DATA = 0xe2;   // Flash数据寄存器
sfr ISP_ADDRH = 0xe3; // Flash高字节地址寄存器
sfr ISP_ADDRL = 0xe4; // Flash低字节地址寄存器
sfr ISP_CMD = 0xe5; // Flash命令模式寄存器
sfr ISP_TRIG = 0xe6; // Flash命令触发寄存器
sfr ISP_CONTR = 0xe7; // ISP/IAP 控制寄存器

#define CMD_READ 0x01 // 定义IAP的读字节操作
#define CMD_PRGM 0x02 // 定义IAP的写字节操作
#define CMD_ERASE 0x03 // 定义IAP的擦除扇区操作

/*********************** 打开 ISP,IAP 功能 ***********************/
static void ISPIAPEnable(void)
{
  //EA = 0;       // 关中断
  ISP_CONTR = ISP_CONTR & 0x18;       // 0001,1000
  ISP_CONTR = ISP_CONTR | WAIT_TIME; // 写入硬件延时
  ISP_CONTR = ISP_CONTR | 0x80;       // ISPEN = 1
}


/*********************** 关闭 ISP,IAP 功能 ***********************/
static void ISPIAPDisable(void)
{
  ISP_CONTR = ISP_CONTR & 0x7f; // ISPEN = 0
  ISP_TRIG = 0x00;
  //EA   = 1;   // 开中断
}

/************************* 触发Flash操作 *************************/
static ActiveOperate(void)
{
  bit eacpy;
  eacpy = EA;
  EA = 0;
  ISPIAPEnable();
  ISP_TRIG = 0x46;   // 触发ISP_IAP命令字节1
  ISP_TRIG = 0xb9;   // 触发ISP_IAP命令字节2
  {UINT8 i=2; while(i--);}
  ISPIAPDisable();
  EA = eacpy;
}


/**************************** 读一字节 ****************************/
static UINT8 IAPReadByte(const UINT16 uiAddr)
{
  ISP_ADDRH = (UINT8)(uiAddr >> 8); // 写地址
  ISP_ADDRL = (UINT8)(uiAddr&0xFF);
  ISP_CMD   = ISP_CMD & 0xf8; // 清低三位
  ISP_CMD   = ISP_CMD | CMD_READ; // 写入读命令
  ActiveOperate(); // 触发执行
  return (ISP_DATA);     // 返回读到的数据
}

/**************************** 写一字节 ****************************/
static void IAPWriteByte(const UINT16 uiAddr, const UINT8 ucData)
{
  ISP_ADDRH = (UINT8)(uiAddr >> 8); // 写地址
  ISP_ADDRL = (UINT8)(uiAddr&0xFF);
  ISP_CMD   = ISP_CMD & 0xf8; // 清低三位
  ISP_CMD   = ISP_CMD | CMD_PRGM; // 写入写命令
  ISP_DATA = ucData;   // 写入数据准备
 
  ActiveOperate(); // 触发执行
}

/**************************** 擦除一扇区 ****************************/
static void IAPEarseSection(const UINT16 uiAddr)
{
  UINT16 uiSecAddr;

  uiSecAddr = (uiAddr & 0xfe00); // 取扇区地址
  ISP_ADDRH = (UINT8)(uiSecAddr >> 8); // 写地址
  ISP_ADDRL = 0x00;
  ISP_CMD = ISP_CMD & 0xf8;   // 清低三位
  ISP_CMD = ISP_CMD | CMD_ERASE; // 写入擦除命令

  ActiveOperate(); // 触发执行
}
因为有点过简单,应用和驱动写在同一文件,驱动都使用了静态函数固定了调用域。

 

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页