涵潇舒雅 发表于 2017-10-22 09:31:31

N76E003 APROM作为EEPROM使用的问题!

N76E003跟stm8s003相比没有内部的eeprom,有教程通过用APROM分区(0x3800~0x38FF)作为内部eeprom使用;

bit BIT_TMP;

/* -------------------------------------------------------------------------*/
/*Dataflash use APROM area                                                                                                                         */
/*      APROM 0x3800~0x38FF demo as dataflash                                                                                                   */
/* Please use Memory window key in C:0x3800 to check earse result                                          */            
/* -------------------------------------------------------------------------*/
UINT8 read_APROM_BYTE(UINT16 code *u16_addr)
{
      UINT8 rdata;
      rdata = *u16_addr>>8;
      return rdata;
}

//-------------------------------------------------------------------------

//-------------------------------------------------------------------------


/*****************************************************************************************************************
write_DATAFLASH_BYTE :
user can copy all this subroutine into project, then call this function in main.
******************************************************************************************************************/               
void write_DATAFLASH_BYTE(UINT16 u16_addr,UINT8 u8_data)
{
       
        UINT8 looptmp=0,u8_addrl_r;
        unsigned char code *cd_longaddr;
        unsigned char xdata *xd_tmp;
       
//Check page start address
        u8_addrl_r = u16_addr;
        if (u8_addrl_r<0x80)
        {
                u8_addrl_r = 0;
        }
        else
        {
                u8_addrl_r = 0x80;
        }
//Save APROM data to XRAM
        xd_tmp = 0x80;
        cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;       
        while (xd_tmp !=0x100)
        {
                *xd_tmp = *cd_longaddr;
                looptmp++;
                xd_tmp++;
                cd_longaddr++;
        }
// Modify customer data in XRAM
        u8_addrl_r = u16_addr;
        if (u8_addrl_r<0x80)
        {
                xd_tmp = u8_addrl_r+0x80;
        }
        else
        {
                xd_tmp = u8_addrl_r+0;
        }
        *xd_tmp = u8_data;
//Erase APROM DATAFLASH page
                IAPAL = u16_addr;
                IAPAH = u16_addr>>8;
                IAPFD = 0xFF;
          set_IAPEN;
                set_APUEN;
    IAPCN = 0x22;                
                set_IAPGO;
//Save changed RAM data to APROM DATAFLASH
        u8_addrl_r = u16_addr;
        if (u8_addrl_r<0x80)
        {
                u8_addrl_r =0;
        }
        else
        {
                u8_addrl_r = 0x80;
        }
                xd_tmp = 0x80;
          IAPAL = u8_addrl_r;
    IAPAH = u16_addr>>8;
                set_IAPEN;
                set_APUEN;
          IAPCN = 0x21;
                while (xd_tmp !=0xFF)
                {
                        IAPFD = *xd_tmp;
                        set_IAPGO;
                        IAPAL++;
                        xd_tmp++;
                }
                clr_APUEN;
                clr_IAPEN;
}   
单独的读写验证已经通过,但是当定义如下结构体之后,就无法进行写操作了,

typedef_split3 DisMenu=
{
{13,0x81,0x01},/* 'P' '1.' '1'*/
{13,0x81,0x02},/* 'P' '1.' '2'*/
{13,0x81,0x03},/* 'P' '1.' '3'*/

{13,16,0x02},/* 'P' '-' '2'*/

{13,0x83,0x01},/* 'P' '3.' '1'*/
{13,0x83,0x02},/* 'P' '3.' '2'*/

{13,16,0x04},/* 'P' '-' '4'*/
};

90999 发表于 2017-10-22 11:19:35

那就不用结构体吧。

Ray______ 发表于 2017-10-22 15:12:45

我是最后放弃了这个DEMO的函数,自己根据手册里的程序按自己的需求写了几个API,现在没啥问题。

mandey 发表于 2017-10-22 19:17:20

这个Demo是整页操作的,先把整页的数据保存在Xdata中,然后把要写的数据组合起来,再一次性写入Flash

涵潇舒雅 发表于 2017-10-23 09:13:07

Ray______ 发表于 2017-10-22 15:12
我是最后放弃了这个DEMO的函数,自己根据手册里的程序按自己的需求写了几个API,现在没啥问题。 ...

前辈,弄否分享一下?感觉这个DEMO太吃内存了~

涵潇舒雅 发表于 2017-10-23 09:14:00

mandey 发表于 2017-10-22 19:17
这个Demo是整页操作的,先把整页的数据保存在Xdata中,然后把要写的数据组合起来,再一次性写入Flash ...

好像是你说的这种操作,Flash必须整页擦除?

涵潇舒雅 发表于 2017-10-23 09:18:45

90999 发表于 2017-10-22 11:19
那就不用结构体吧。

好像是DEMO Flash操作,太吃内存了,我这边一旦定义比较大的全局变量,就有问题,现在先用code修饰一下

mandey 发表于 2017-10-23 20:10:37

涵潇舒雅 发表于 2017-10-23 09:14
好像是你说的这种操作,Flash必须整页擦除?

擦除肯定是要整页的,所以擦除前要把Flash的数据先保存起来,这样再写进去之前的数据就不会受影响。如果你只是固定位置擦写,不管其他的数据,那就不用那个保存的操作,这样就可以省下128字节的内存。

Ray______ 发表于 2017-10-23 20:13:51

涵潇舒雅 发表于 2017-10-23 09:13
前辈,弄否分享一下?感觉这个DEMO太吃内存了~

#define PAGE_ERASE_AP       0x22
#define BYTE_PROGRAM_AP   0x21
#define BYTE_READ_AP      0X00


volatile uint8_t code Data_Flash _at_ 0x0200;
uint8_t saveTmp;

/************************************************************************************************************
*    判断是否新片,全FF为新片
*    1:新片    0:用过
************************************************************************************************************/
uint8_t CheckNewChip(void)
{
    uint8_t datTmp;
   
    datTmp = Data_Flash;
    if(datTmp == 0xff)
      return 1;
    else
      return 0;
   
   
   
    return 1;
}
/************************************************************************************************************
*    写一个字节进APROM
************************************************************************************************************/
void APROM_WriteOneByte(uint16_t addr, uint8_t dat)
{
    uint8_t offset;
    uint8_t i;
   
    offset = addr - START_EEPROM_ADD;
    for( i = 0; i < USE_EEPROM_SIZE; i++){saveTmp = Data_Flash; }//Copy data to temp area
    saveTmp = dat;                                             //Write data into temp area
   
    set_IAPEN;            //Enable IAP mode
    set_APUEN;            //Enable APROM update
   
    IAPCN = PAGE_ERASE_AP;//Erase page ,128byte of one page
    IAPAH = EEPROM_HIGH_ADD;
    IAPAL = 0x00;
    IAPFD = 0xFF;         //Erase
    set_IAPGO;            //Trigger IAP process
   
    IAPCN = BYTE_PROGRAM_AP;//APROM Byte program
    for( i = 0; i < USE_EEPROM_SIZE; i++)//Write data into APROM
    {
      IAPAH = EEPROM_HIGH_ADD;
      IAPAL = i;
      IAPFD = saveTmp;
      set_IAPGO;            //Trigger IAP process
    }
                           
    clr_APUEN;            //Disable APROM update
    clr_IAPEN;            //Disable IAP mode
}

/************************************************************************************************************
*    写一串数据进APROM
************************************************************************************************************/
void APROM_WriteBuf(uint16_t addr, uint8_t *in, uint8_t len)
{
    uint8_t offset;
    uint8_t i;
   
    offset = addr - START_EEPROM_ADD;
    cpybuf( saveTmp, Data_Flash, USE_EEPROM_SIZE);//Copy data to temp area
    cpybuf( saveTmp + offset, in, len);         //Copy buff into temp area
   
    set_IAPEN;            //Enable IAP mode
    set_APUEN;            //Enable APROM update
   
    IAPCN = PAGE_ERASE_AP;//Erase page ,128byte of one page
    IAPAH = EEPROM_HIGH_ADD;
    IAPAL = 0x00;
    IAPFD = 0xFF;      
    set_IAPGO;            //Trigger IAP process
   
    IAPCN = BYTE_PROGRAM_AP;//APROM Byte program
    for( i = 0; i < USE_EEPROM_SIZE; i++)//Write data into APROM
    {
      IAPAH = EEPROM_HIGH_ADD;
      IAPAL = i;
      IAPFD = saveTmp;
      set_IAPGO;            //Trigger IAP process
    }
                           
    clr_APUEN;            //Disable APROM update
    clr_IAPEN;            //Disable IAP mode   
}


/************************************************************************************************************
*    读APROM一个字节
************************************************************************************************************/
uint8_t Read_APROM_Byte(uint16_t addr)
{
    uint8_t dataTmp;
   
    dataTmp = Data_Flash;
   
    return dataTmp;
}

/************************************************************************************************************
*    读APROM连续字节
************************************************************************************************************/
void Read_APROM_Buf(uint16_t addr, uint8_t *out, uint8_t len)
{
    uint8_t offset;
   
    offset = addr - START_EEPROM_ADD;
        cpybuf( out, &Data_Flash, len);
}

Ray______ 发表于 2017-10-23 20:15:18

Ray______ 发表于 2017-10-23 20:13


有个问题就是按照手册的从0x200开始了,会对应按数据大小生成对应的区域当作EEP用,可以自己选其他的区域,不过读写函数内部有些地址得改下,因为没有用宏做。

蛋定 发表于 2018-12-24 23:23:18

记号,谢谢,学习了。

pipi516 发表于 2020-6-24 17:16:29

可能会用到,MARK!

笔记本的自嘲 发表于 2020-12-26 20:26:48

mark一下,谢谢分享
页: [1]
查看完整版本: N76E003 APROM作为EEPROM使用的问题!