手册上是这么说的【在应用编程(IAP)支持用户自定义启动代码和类EEPROM 区 】,官方的例程也提供了类EEPROM读写的例程的,你可以参考看看。
/**
* ************************************************************************************
* 上海芯圣电子股份有限公司
* www.holychip.cn
* ************************************************************************************
* @Examle Version V1.0.1.0
* [url=home.php?mod=space&uid=1102]@demo[/url] Version V1.0.2.0
* @Date 2017.12.21
* ************************************************************************************
* 模块性能介绍
* 1、Flash擦写次数10万次以上
* 2、扇区擦除时间约4.2ms,且擦除时不响应任何中断,但会置相关标志位,擦除完成后响应
* 3、可设置应用程序读保护,应用程序写保护(以4K字节为保护单位)
* 4、可以设置仿真器扇区读保护,扇区写保护(以4K字节为保护单位)
* 5、设置保护后无法擦写程序,读取的数据全为零
* 6、每一颗MCU在出厂时会固化一个CHIP_ID,一共8个字节,一颗芯片一个ID,不会重复
* ************************************************************************************
* 应用注意事项
* 1、CPU时钟需要配置为1-16MHz之间的正整数,且Flash擦写之前需要配置FREQ_CLK寄存器,该寄
* 存器值即为当前CPU时钟频率。
* 2、扇区擦除写入过程中不能被打断
* 3、数据存放地址需要在程序存放地址之后
* 4、第二复位向量使能时,无法在仿真环境下查看code区数据
* 5、Flsah操作最低电压限制为2.0V,所以建议进行Flash操作前进行电压检测或者打开BOR,BOR电
* 压建议设置为2.4V及2.4V以上
* 6、建议在进行Flash擦写操作前关闭中断,擦写完成后再打开中断
* ************************************************************************************
* 客户服务
* 感谢您使用我们的单片机,若发现错误或对函数的使用存在疑问。请添加上海芯圣电子官方QQ群
* ****************************技术支持群:201030494***********************************
* ************************************************************************************
**/
#define ALLOCATE_EXTERN
#include "HC89S003F4.h"
void Flash_EraseBlock(unsigned int fui_Address);//扇区擦除
void Flash_WriteArr(unsigned int fui_Address,unsigned char fuc_Length,unsigned char *fucp_SaveArr);
void Flash_ReadArr(unsigned int fui_Address,unsigned char fuc_Length,unsigned char *fucp_SaveArr);
unsigned char guc_Write_a[5] = {0x11,0x12,0x13,0x14,0x15}; //写入数据
unsigned char guc_Read_a[5] = {0x00}; //用于存放读取的数据
unsigned char guc_Uartflag = 0; //发送标志位
unsigned char guc_Uartcnt = 0; //发送计数
unsigned char guc_Uartbuf_a[2] = {0x00}; //缓存数组
/***************************************************************************************
* @实现效果 在地址0x2B00到0x2B04连续写入5个数据,通过串口工具发送地址可以读取相对应
的数据。
* @操作步骤 接上RXD TXD短路帽,通过串口工具向单片机发送以0x2B为帧头的数据,返回对应
对应地址的数据。
***************************************************************************************/
int main()
{
/************************************系统初始化****************************************/
WDTCCR = 0x00; //关闭看门狗
while((CLKCON&0x20)!=0x20); //等待内部高频RC起振
CLKSWR = 0x51; //选择内部高频时钟为主时钟,内部高频RC2分频,Fosc=16MHz
while((CLKSWR&0xC0)!=0x40); //等待内部高频切换完成
CLKDIV = 0x01; //Fosc1分频得到Fcpu,Fcpu=16MHz
/**********************************相关配置初始化**************************************/
P2M0 = P2M0&0x0F|0x80; //P21设置为推挽输出
P0M1 = P0M1&0x0F|0x20; //P03设置为上拉输出
TXD_MAP = 0x21; //TXD映射P21
RXD_MAP = 0x03; //RXD映射P03
T4CON = 0x06; //T4工作模式:UART1波特率发生器
TH4 = 0xFF;
TL4 = 0x98; //波特率9600
SCON2 = 0x02; //8位UART,波特率可变
SCON = 0x10; //允许串行接收
IE |= 0x10; //使能串口中断
/**********************************Flash配置初始化*************************************/
FREQ_CLK = 0x10; //指明当前系统时钟
Flash_EraseBlock(0x2B00); //擦除地址0x2B00所在扇区
Flash_WriteArr(0x2B00,5,guc_Write_a);//在地址0x2B00写入数据
Flash_ReadArr(0x2B00,5,guc_Read_a); //读取地址0x2B00所在扇区
EA = 1; //使能总中断
while(1)
{
if(guc_Uartflag)
{
IE &=~ 0x10; //失能UART1中断
if(guc_Uartbuf_a[0] == 0x2B)
{
switch(guc_Uartbuf_a[1])
{
case 0x00: SBUF = guc_Read_a[0];//发送8位串口数据
break;
case 0x01: SBUF = guc_Read_a[1];//发送8位串口数据
break;
case 0x02: SBUF = guc_Read_a[2];//发送8位串口数据
break;
case 0x03: SBUF = guc_Read_a[3];//发送8位串口数据
break;
case 0x04: SBUF = guc_Read_a[4];//发送8位串口数据
break;
default:break;
while(!(SCON&0x02)); //等待发送完毕
SCON &=~ 0x02;; //清除发送中断标志位
}
IE |= 0x10; //UART1中断使能
guc_Uartflag = 0; //标志位清零
guc_Uartcnt = 0; //标志位清零
SCON |= 0x10; //UART1接收使能
}
}
}
return 0;
}
/***************************************************************************************
* @说明 UART1中断服务函数
* @参数 无
* @返回值 无
* @注 无
***************************************************************************************/
void UART1_Rpt(void) interrupt UART1_VECTOR
{
if(SCON&0x01) //判断接收中断标志位
{
guc_Uartbuf_a[guc_Uartcnt++] = SBUF;//转存8位串口接收数据
if(guc_Uartcnt >= 2)
{
SCON &=~ 0x10; //失能UART1接收
guc_Uartflag = 1;
}
SCON &=~ 0x01; //清除接收中断标志位
}
}
/**
* @说明 扇区擦除,约消耗4.2ms的时间
* @参数 fui_Address :被擦除的扇区内的任意一个地址
* 取值范围:0x0000-0x3FFF
* @返回值 无
* @注 只要操作扇区里面的任意一个地址,就可以擦除此扇区
*/
void Flash_EraseBlock(unsigned int fui_Address)
{
EA = 0;
IAP_CMD = 0xF00F; //Flash解锁
IAP_ADDR = fui_Address; //写入擦除地址
IAP_CMD = 0xD22D; //选择操作方式, 扇区擦除
IAP_CMD = 0xE11E; //触发后IAP_ADDRL&IAP_ADDRH指向0xFF,同时自动锁定
EA = 1;
}
/**
* @说明 写入任意长度的数据到FLASH里面
* @参数 fui_Address :FLASH起始地址
* 取值范围:0x0000-0x3FFF
* @参数 fuc_Length : 写入数据长度
* 取值范围:0x00-0xFF
* @参数 *fucp_SaveArr:写入的数据存放区域的首地址
* @返回值 无
* @注 写之前必须先对操作的扇区进行擦除
*/
void Flash_WriteArr(unsigned int fui_Address,unsigned char fuc_Length,unsigned char *fucp_SaveArr)
{
EA = 0;
while(fuc_Length--)
{
IAP_DATA=*fucp_SaveArr; //待编程数据,写入数据寄存器必须放在解锁之前
IAP_CMD=0xF00F; //Flash解锁
IAP_ADDR=fui_Address; //写入地址
IAP_CMD=0xB44B; //字节编程
IAP_CMD=0xE11E; //触发一次操作
fui_Address++; //地址加一
fucp_SaveArr++; //数据后移一位
}
EA = 1;
}
/**
* @说明 从FLASH里面读取任意长度的数据
* @参数 fui_Address :FLASH起始地址
* 取值范围:0x0000-0x3FFF
* @参数 fuc_Length : 读取数据长度
* 取值范围:0x00-0xFF
* @参数 *fucp_SaveArr:读取数据存放的区域首地址
* @返回值 无
* @注 无
*/
void Flash_ReadArr(unsigned int fui_Address,unsigned char fuc_Length,unsigned char *fucp_SaveArr)
{
while(fuc_Length--)
*(fucp_SaveArr++)=*((unsigned char code *)(fui_Address++));//读取数据
}
|