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相关寄存器列表
称号地址功用描绘D7D6D5D4D3D2D1D0复位值ISP_DATAE2hFlash数据寄存器
1111 1111ISP_ADDRHE3hFlash高字节地址寄存器
0000 0000ISP_ADDRLE4hFlash低字节地址寄存器
0000 0000ISP_CMDE5hFlash指令形式寄存器———-MS2MS1MS0xxxx x000ISP_TRIGE6hFlash指令触发寄存器
xxxx xxxxISP_CONTRE7hISP/IAP 操控寄存器ISPENSWBSSWRST—-WT2WT1WT0000x 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寄存器形式设置
D7D6D5D4D3D2D1D0形式挑选保存指令挑选
———-000待机形式,无ISP操作———-001对用户的使用程序flash区及数据flash区字节读———-010对用户的使用程序flash区及数据flash区字节编程———-011对用户的使用程序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地址表
榜首扇区第二扇区第三扇区第四扇区开始地址完毕地址开始地址完毕地址开始地址完毕地址开始地址完毕地址2000H21FFH2200H23FFH2400H25FFH2600H27FFH第五扇区第六扇区第七扇区第八扇区开始地址完毕地址开始地址完毕地址开始地址完毕地址开始地址完毕地址2800H29FFH2A00H2BFFH2C00H2DFFH2E00H2FFFH
每个扇区为512字节,主张我们在写程序时,将同一次修正的数据放在同一个扇区,便利修正,由于在履行擦除指令时,一次最少要擦除一个扇区的数据(需求供给扇区的首地址),每次在更新数据前都必须要擦除原数据方可从头写入新数据,不能直接在本来数据基础上更新内容。
留意:上面的是数据存储区的地址,程序存储区地址是从0~1FFF,共8K,程序区只能是ISP编程。
以下是自己写的这部分功用代码,由于风格问题,不太喜爱原著代码,感觉自己的还谨慎一点。
/****************************************************************************/
/* IAP驱动 */
/****************************************************************************/
/************************************************************************************************************************/
/*ISP/IAP相关寄存器列表*/
/*称号地址功用描绘D7D6D5D4D3D2D1D0复位值*/
/*ISP_DATAE2hFlash数据寄存器1111 1111*/
/*ISP_ADDRHE3hFlash高字节地址寄存器0000 0000*/
/*ISP_ADDRLE4hFlash低字节地址寄存器0000 0000*/
/*ISP_CMDE5hFlash指令形式寄存器———-MS2MS1MS0xxxx x000*/
/*ISP_TRIGE6hFlash指令触发寄存器xxxx xxxx*/
/*ISP_CONTRE7hISP/IAP 操控寄存器ISPENSWBSSWRST—-WT2WT1WT0000x x000*/
/************************************************************************************************************************/
/************************************************************************************/
/*ISP_CMD寄存器形式设置*/
/* D7D6D5D4D3D2D1D0形式挑选*/
/*保存指令挑选*/
/* ———-000待机形式,无ISP操作*/
/* ———-001对用户的使用程序flash区及数据flash区字节读*/
/* ———-010对用户的使用程序flash区及数据flash区字节编程*/
/* ———-011对用户的使用程序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_READ0x01// 界说IAP的读字节操作
#define CMD_PRGM0x02// 界说IAP的写字节操作
#define CMD_ERASE0x03// 界说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)
{
UINT16uiSecAddr;
uiSecAddr= (uiAddr & 0xfe00);// 取扇区地址
ISP_ADDRH= (UINT8)(uiSecAddr 》》 8);// 写地址
ISP_ADDRL= 0x00;
ISP_CMD= ISP_CMD & 0xf8; // 清低三位
ISP_CMD= ISP_CMD | CMD_ERASE;// 写入擦除指令
ActiveOperate();// 触发履行
}
————————————————————————————————————————
#include//到宏晶网站下载头文件或自己在现有的头文件上加上相应的寄存器界说即可。
#include
#define uchar unsigned char
#define uint unsigned int
/****************uart init***********/
void UART_inti(void)
{
AUXR=0x40;//定时器1速度是一般8051的12倍,不分频
TMOD=0x20;//定时器1作业在方法2,用来发生波特率
SCON=0x50;//串口作业在方法1,答应接纳
TL1=0xF7;//波特率为38400;FB为115200
TH1=0xF7;
PCON=0x00;//SMOD=0
TR1=1; //发生波特率
}
void ISP_write