[通用8051核FLASH系列]

HC89S003F4的Flash可以作EEPROM吗?

[复制链接]
1532|5
手机看帖
扫描二维码
随时随地手机跟帖
haixianhaixian|  楼主 | 2018-4-5 15:37 | 显示全部楼层 |阅读模式
本帖最后由 芯圣电子官方QQ 于 2023-7-25 10:51 编辑

如题,具体怎么做?谢谢!
xyz549040622| | 2018-4-6 07:18 | 显示全部楼层
手册上是这么说的【在应用编程(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++));//读取数据
}

使用特权

评论回复
haixianhaixian|  楼主 | 2018-4-6 09:16 | 显示全部楼层
谢谢,

使用特权

评论回复
magicoctoy| | 2018-4-24 16:28 | 显示全部楼层
xyz549040622 发表于 2018-4-6 07:18
手册上是这么说的【在应用编程(IAP)支持用户自定义启动代码和类EEPROM 区 】,官方的例程也提供了类EEPRO ...

谢谢分享。

使用特权

评论回复
Bruing| | 2018-4-26 22:49 | 显示全部楼层
支持下,flash模拟eeprom,还不如像STC一样,直接开个eeprom区域呢,省的模拟麻烦

使用特权

评论回复
wakayi| | 2018-7-14 21:11 | 显示全部楼层
存在自然是有道理的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

12

帖子

0

粉丝