[技术问答] 新塘NE76E003 EEPROM问题请教

[复制链接]
3464|14
 楼主| lizhenming 发表于 2018-5-29 09:11 | 显示全部楼层 |阅读模式
#include "N76E003.h"
#include "Flash.h"

static bit EA_Save_bit;

void Enable_IAP_Mode(void)
{
  EA_Save_bit=EA;
        EA=0;
        TA=0xAA;
        TA=0x55;
        CHPCON|=0x01 ;
        TA=0xAA;
        TA=0x55;
        IAPUEN|=0x01;
        EA=EA_Save_bit;
}
//-----------------------------------------------------------------------------------------------------------
void Disable_IAP_Mode(void)
{
  EA_Save_bit=EA;
  EA=0;
  TA=0xAA;
  TA=0x55;
  IAPUEN&=~0x01;
  TA=0xAA;
  TA=0x55;
  CHPCON&=~0x01;
  EA=EA_Save_bit;
}
//-----------------------------------------------------------------------------------------------------------
void Trigger_IAP(void)
{
        EA_Save_bit=EA;
        EA=0;
        TA=0xAA;
        TA=0x55;
        IAPTRG|=0x01;
        EA=EA_Save_bit;
}

       
uint8_t WriteDataToOnePage(uint16_t u16_addr,const uint8_t *pDat,uint8_t num)
{
  uint8_t i,offset;
  uint8_t code *pCode;
  uint8_t xdata xd_tmp[128];

        Enable_IAP_Mode();
        offset=u16_addr&0x007F;
        i = PAGE_SIZE - offset;
        if(num>i)num=i;
  pCode = (uint8_t code *)u16_addr;
  for(i=0;i<num;i++)
  {
    if(pCode[i]!=0xFF)break;
  }
        if(i==num)
        {
          IAPCN =BYTE_PROGRAM_AP;
                IAPAL = u16_addr;
                IAPAH = u16_addr>>8;
                for(i=0;i<num;i++)
                {
                        IAPFD = pDat[i];
                        Trigger_IAP();
                        IAPAL++;
                }
                for(i=0;i<num;i++)
                {
                        if(pCode[i]!=pDat[i])break;
                }
                if(i!=num) goto WriteDataToPage20;
        }
        else
        {
                WriteDataToPage20:
                pCode = (uint8_t code *)(u16_addr&0xff80);
                for(i=0;i<128;i++)
                {
                        xd_tmp[i] = pCode[i];
                }
                for(i=0;i<num;i++)
                {
                        xd_tmp[offset+i] = pDat[i];
                }
                do
                {
                        IAPAL = (u16_addr&0xff80);
                        IAPAH = u16_addr>>8;
                        IAPCN = PAGE_ERASE_AP;
                        IAPFD = 0xFF;       
                        Trigger_IAP();
                        IAPCN =BYTE_PROGRAM_AP;
                        for(i=0;i<128;i++)
                        {
                                IAPFD = xd_tmp[i];
                                Trigger_IAP();
                                IAPAL++;
                        }
                        for(i=0;i<128;i++)
                        {
                                if(pCode[i]!=xd_tmp[i])break;
                        }
                }while(i!=128);
               
        }
        Disable_IAP_Mode();
       
        return num;
}       

//-------------------------------------------------------------------------
void WriteDataFlash(uint16_t u16_addr,uint8_t *pDat,uint16_t num)
{
        uint8_t CPageAddr,EPageAddr,cnt;
        CPageAddr=u16_addr>>7;
        EPageAddr=(u16_addr+num)>>7;
        while(CPageAddr!=EPageAddr)
        {
                cnt=WriteDataToOnePage(u16_addr,pDat,128);
                u16_addr+=cnt;
                pDat+=cnt;
                num-=cnt;
                CPageAddr=u16_addr>>7;
        }
        if(num)
        {
                WriteDataToOnePage(u16_addr,pDat,num);
        }
}
//-------------------------------------------------------------------------
void ReadDataFlash(uint16_t u16_addr,uint8_t *pDat,uint16_t num)
{
        uint16_t i;
        for(i=0;i<num;i++)
    pDat[i] = *(uint8_t code *)(u16_addr+i);
}
//-----------------------------------------------------------------------------------------------------------
问题描述:
unsigned char eepbuf[24];
利用 ReadDataFlash(0x4700,&eepbuf,24); 去读取对应的数据,发现与**作写入的数据不一样(读出来有数据,但是错误的)
我是利用ICP烧录工具读取单片机片上APROM数据查看到0x4700-0x4717 数据是和写入的数据是一致的。
会有什么原因导致呢?会不会读取地址数据前需要操作什么指令之类?或者void ReadDataFlash(uint16_t u16_addr,uint8_t *pDat,uint16_t num)这个函数写法有错?


21mengnan 发表于 2018-5-29 15:44 | 显示全部楼层
  1. /*---------------------------------------------------------------------------------------------------------*/
  2. /*                                                                                                         */
  3. /* Copyright(c) 2017 Nuvoton Technology Corp. All rights reserved.                                         */
  4. /*                                                                                                         */
  5. /*---------------------------------------------------------------------------------------------------------*/

  6. //***********************************************************************************************************

  7. //***********************************************************************************************************

  8. //***********************************************************************************************************
  9. //  File Function: N76E003 APROM program DATAFLASH as EEPROM way
  10. //***********************************************************************************************************
  11. #include "N76E003.h"
  12. #include "Common.h"
  13. #include "Delay.h"
  14. #include "SFR_Macro.h"
  15. #include "Function_define.h"


  16. /*****************************************************************************************************************
  17. write_DATAFLASH_BYTE :
  18. user can copy all this subroutine into project, then call this function in main.
  19. ******************************************************************************************************************/               
  20. void write_DATAFLASH_BYTE(UINT16 u16_addr,UINT8 u8_data)
  21. {
  22.         UINT8 looptmp=0,u8_addrl_r;
  23.         unsigned char code *cd_longaddr;
  24.         unsigned char xdata *xd_tmp;
  25.        
  26. //Check page start address
  27.         u8_addrl_r = u16_addr;
  28.         if (u8_addrl_r<0x80)
  29.         {
  30.                 u8_addrl_r = 0;
  31.         }
  32.         else
  33.         {
  34.                 u8_addrl_r = 0x80;
  35.         }
  36. //Save APROM data to XRAM
  37.         xd_tmp = 0x80;
  38.         cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;       
  39.         while (xd_tmp !=0x100)
  40.         {
  41.                 *xd_tmp = *cd_longaddr;
  42.                 looptmp++;
  43.                 xd_tmp++;
  44.                 cd_longaddr++;
  45.         }
  46. // Modify customer data in XRAM
  47.         u8_addrl_r = u16_addr;
  48.         if (u8_addrl_r<0x80)
  49.         {
  50.                 xd_tmp = u8_addrl_r+0x80;
  51.         }
  52.         else
  53.         {
  54.                 xd_tmp = u8_addrl_r+0;
  55.         }
  56.         *xd_tmp = u8_data;
  57. //Erase APROM DATAFLASH page
  58.                 IAPAL = u16_addr;
  59.                 IAPAH = u16_addr>>8;
  60.                 IAPFD = 0xFF;
  61.           set_IAPEN;
  62.                 set_APUEN;
  63.     IAPCN = 0x22;                
  64.                 set_IAPGO;
  65. //Save changed RAM data to APROM DATAFLASH
  66.         u8_addrl_r = u16_addr;
  67.         if (u8_addrl_r<0x80)
  68.         {
  69.                 u8_addrl_r =0;
  70.         }
  71.         else
  72.         {
  73.                 u8_addrl_r = 0x80;
  74.         }
  75.                 xd_tmp = 0x280;
  76.           IAPAL = u8_addrl_r;
  77.     IAPAH = u16_addr>>8;
  78.                 set_IAPEN;
  79.                 set_APUEN;
  80.           IAPCN = 0x21;
  81.                 while (xd_tmp !=0xFF)
  82.                 {
  83.                         IAPFD = *xd_tmp;
  84.                         set_IAPGO;
  85.                         IAPAL++;
  86.                         xd_tmp++;
  87.                 }
  88.                 clr_APUEN;
  89.                 clr_IAPEN;
  90. }       
  91.        
  92. //-------------------------------------------------------------------------
  93. UINT8 read_APROM_BYTE(UINT16 code *u16_addr)
  94. {
  95.         UINT8 rdata;
  96.         rdata = *u16_addr>>8;
  97.         return rdata;
  98. }

  99. /******************************************************************************************************************/       


  100. void main (void)
  101. {
  102.                 UINT8 datatemp;
  103. /* -------------------------------------------------------------------------*/
  104. /*  Dataflash use APROM area, please ALWAYS care the address of you code    */
  105. /*        APROM 0x3800~0x38FF demo as dataflash                                                                                                     */
  106. /*         Please use Memory window key in C:0x3800 to check earse result                                        */             
  107. /* -------------------------------------------------------------------------*/
  108.                 InitialUART0_Timer1(115200);
  109. //call write byte
  110.                 write_DATAFLASH_BYTE (0x3881,0x55);
  111.                 write_DATAFLASH_BYTE (0x3882,0x56);
  112.                 write_DATAFLASH_BYTE (0x3855,0xaa);
  113.                 write_DATAFLASH_BYTE (0x3856,0x66);
  114. //call read byte
  115.                 datatemp = read_APROM_BYTE(0x3882);

  116.     while(1)
  117.                 {
  118. //                                printf ("\n data temp = 0x%bx", datatemp);
  119.                 }
  120. }
  121. //-----------------------------------------------------------------------------------------------------------
21mengnan 发表于 2018-5-29 15:44 | 显示全部楼层
可以参考官方例子的函数。
你的没看懂。
小灵通2018 发表于 2018-5-29 17:06 | 显示全部楼层
参考例子和手册的寄存器说明。
 楼主| lizhenming 发表于 2018-5-30 22:49 | 显示全部楼层
例程压根不行,数据都没写进去
 楼主| lizhenming 发表于 2018-5-30 23:23 | 显示全部楼层
UINT8 read_APROM_BYTE(UINT16 code *u16_addr)
{
        UINT8 rdata;
        rdata = *u16_addr>>8;
       
        return rdata;
}
这个函数UINT16 code *u16_add传参的地址会被其他定义了的变量改变吗?我找到原因就是这里了,函数不是读地址里面的数据,而是直接就是地址。。。很奇怪,我程序还定义了很多变量的,idata xdata等,但是容量没超
dzahz2008 发表于 2018-5-31 13:33 来自手机 | 显示全部楼层
优化等级不能太高 我也在用这个芯片qq718595426
 楼主| lizhenming 发表于 2018-6-1 08:29 | 显示全部楼层
搞不懂例程为什么先将数据保存到XRAM?之后再写入flash?
 楼主| lizhenming 发表于 2018-6-1 08:33 | 显示全部楼层
现在读取是可以了,原因是
UINT8 read_APROM_BYTE(UINT16 code *u16_addr)
这个函数的传参的类型定义 code 这个在其他地方定义了其他东西。
现在变成写入不成功了,是不是需要刷除之后才能写入呢?
 楼主| lizhenming 发表于 2018-6-1 08:44 | 显示全部楼层
看例程,貌似是需要先保存FLASH的数据,然后刷除,接着写入。
我的做法是不管之前FLASH是否有数据,都直接写入,这样的做法是不是不行?一定要刷除之后才能够写入?希望大神们知道的解答下,谢谢!
hj007 发表于 2018-6-1 08:50 | 显示全部楼层
lizhenming 发表于 2018-6-1 08:29
搞不懂例程为什么先将数据保存到XRAM?之后再写入flash?

楼主可以先把官方的例程看懂。
这是我之前回复被人的,可以参考一下。
https://bbs.21ic.com/forum.php?mo ... amp;fromuid=1698880
hj007 发表于 2018-6-1 08:52 | 显示全部楼层
//-------------------------------------------------------------------------
void ReadDataFlash(uint16_t u16_addr,uint8_t *pDat,uint16_t num)
{
        uint16_t i;
        for(i=0;i<num;i++)
           pDat[i] = *(uint8_t code *)(u16_addr+i);//----------->此处应该是:pDat[i] = *(uint16_t code *)(u16_addr+i);
}
 楼主| lizhenming 发表于 2018-6-1 09:00 | 显示全部楼层
hj007 发表于 2018-6-1 08:50
楼主可以先把官方的例程看懂。
这是我之前回复被人的,可以参考一下。
https://bbs.21ic.com/forum.php?mo ...

我纠结的点不在那里,我试过用例程是读写都正常
但是前天我发现写正常,读错误,昨晚找出问题源头了,解决了读取,之后发现写不正常了,
为什么会造成这样的原因呢?我猜测试这样,我之前写入可能是配置那里用了全部刷除之后下载,所以写入可以,读取的话还是因为code这个量被定义作为其他用途,所以影响到读取了。所以读取一直错误。
现在我在配置上去掉了刷除,直接写入,发现不成功,而且仔细看了例程,例程都是先把FLASH内的数据保存到XRAM.然后刷除整页,接着再把之前保存到XRAM的和新添加的数据,写入FLASH,所以这样就成功。
这样一个过程,我可以认为是必须要刷除整页,再写入才是正确操作?
 楼主| lizhenming 发表于 2018-6-1 09:02 | 显示全部楼层
写FLASH肯定要先擦除,这是flash机制决定的。flash只写0不写1,擦除后全部变成0xff,这时才能写入正确的值
这段话是我查到的答案吗?
 楼主| lizhenming 发表于 2018-6-1 09:06 | 显示全部楼层
找到原因了,就是我所找的答案,有点想当然了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

22

主题

129

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部