打印
[技术问答]

新塘NE76E003 EEPROM问题请教

[复制链接]
3226|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 | 只看该作者
/*---------------------------------------------------------------------------------------------------------*/
/*                                                                                                         */
/* Copyright(c) 2017 Nuvoton Technology Corp. All rights reserved.                                         */
/*                                                                                                         */
/*---------------------------------------------------------------------------------------------------------*/

//***********************************************************************************************************

//***********************************************************************************************************

//***********************************************************************************************************
//  File Function: N76E003 APROM program DATAFLASH as EEPROM way
//***********************************************************************************************************
#include "N76E003.h"
#include "Common.h"
#include "Delay.h"
#include "SFR_Macro.h"
#include "Function_define.h"


/*****************************************************************************************************************
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 = 0x280;
          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;
}       
       
//-------------------------------------------------------------------------
UINT8 read_APROM_BYTE(UINT16 code *u16_addr)
{
        UINT8 rdata;
        rdata = *u16_addr>>8;
        return rdata;
}

/******************************************************************************************************************/       


void main (void)
{
                UINT8 datatemp;
/* -------------------------------------------------------------------------*/
/*  Dataflash use APROM area, please ALWAYS care the address of you code    */
/*        APROM 0x3800~0x38FF demo as dataflash                                                                                                     */
/*         Please use Memory window key in C:0x3800 to check earse result                                        */             
/* -------------------------------------------------------------------------*/
                InitialUART0_Timer1(115200);
//call write byte
                write_DATAFLASH_BYTE (0x3881,0x55);
                write_DATAFLASH_BYTE (0x3882,0x56);
                write_DATAFLASH_BYTE (0x3855,0xaa);
                write_DATAFLASH_BYTE (0x3856,0x66);
//call read byte
                datatemp = read_APROM_BYTE(0x3882);

    while(1)
                {
//                                printf ("\n data temp = 0x%bx", datatemp);
                }
}
//-----------------------------------------------------------------------------------------------------------

使用特权

评论回复
板凳
21mengnan| | 2018-5-29 15:44 | 只看该作者
可以参考官方例子的函数。
你的没看懂。

使用特权

评论回复
地板
小灵通2018| | 2018-5-29 17:06 | 只看该作者
参考例子和手册的寄存器说明。

使用特权

评论回复
5
lizhenming|  楼主 | 2018-5-30 22:49 | 只看该作者
例程压根不行,数据都没写进去

使用特权

评论回复
6
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等,但是容量没超

使用特权

评论回复
7
dzahz2008| | 2018-5-31 13:33 | 只看该作者
优化等级不能太高 我也在用这个芯片qq718595426

使用特权

评论回复
8
lizhenming|  楼主 | 2018-6-1 08:29 | 只看该作者
搞不懂例程为什么先将数据保存到XRAM?之后再写入flash?

使用特权

评论回复
9
lizhenming|  楼主 | 2018-6-1 08:33 | 只看该作者
现在读取是可以了,原因是
UINT8 read_APROM_BYTE(UINT16 code *u16_addr)
这个函数的传参的类型定义 code 这个在其他地方定义了其他东西。
现在变成写入不成功了,是不是需要刷除之后才能写入呢?

使用特权

评论回复
10
lizhenming|  楼主 | 2018-6-1 08:44 | 只看该作者
看例程,貌似是需要先保存FLASH的数据,然后刷除,接着写入。
我的做法是不管之前FLASH是否有数据,都直接写入,这样的做法是不是不行?一定要刷除之后才能够写入?希望大神们知道的解答下,谢谢!

使用特权

评论回复
11
hj007| | 2018-6-1 08:50 | 只看该作者
lizhenming 发表于 2018-6-1 08:29
搞不懂例程为什么先将数据保存到XRAM?之后再写入flash?

楼主可以先把官方的例程看懂。
这是我之前回复被人的,可以参考一下。
https://bbs.21ic.com/forum.php?mo ... amp;fromuid=1698880

使用特权

评论回复
12
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);
}

使用特权

评论回复
13
lizhenming|  楼主 | 2018-6-1 09:00 | 只看该作者
hj007 发表于 2018-6-1 08:50
楼主可以先把官方的例程看懂。
这是我之前回复被人的,可以参考一下。
https://bbs.21ic.com/forum.php?mo ...

我纠结的点不在那里,我试过用例程是读写都正常
但是前天我发现写正常,读错误,昨晚找出问题源头了,解决了读取,之后发现写不正常了,
为什么会造成这样的原因呢?我猜测试这样,我之前写入可能是配置那里用了全部刷除之后下载,所以写入可以,读取的话还是因为code这个量被定义作为其他用途,所以影响到读取了。所以读取一直错误。
现在我在配置上去掉了刷除,直接写入,发现不成功,而且仔细看了例程,例程都是先把FLASH内的数据保存到XRAM.然后刷除整页,接着再把之前保存到XRAM的和新添加的数据,写入FLASH,所以这样就成功。
这样一个过程,我可以认为是必须要刷除整页,再写入才是正确操作?

使用特权

评论回复
14
lizhenming|  楼主 | 2018-6-1 09:02 | 只看该作者
写FLASH肯定要先擦除,这是flash机制决定的。flash只写0不写1,擦除后全部变成0xff,这时才能写入正确的值
这段话是我查到的答案吗?

使用特权

评论回复
15
lizhenming|  楼主 | 2018-6-1 09:06 | 只看该作者
找到原因了,就是我所找的答案,有点想当然了

使用特权

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

本版积分规则

22

主题

127

帖子

2

粉丝