打印

请教PIC 内部EEPROM读写错误的问题?谢谢!!

[复制链接]
10687|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zb02373|  楼主 | 2012-8-24 23:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这段程序用于读写PIC内部EEPROM,但我测试后,发现读出来的总是最后写入的数据,而不是根据地址读出的数据。
比如,写地址8,数据8;写地址9,数据9。但现在读地址8时,显示的仍然为9,请教一下到底是什么原因??
已经困扰我一个月时间了,一直找不到原因,谢谢各位指教,不盛感激。


#include <p18cxxx.h>/*18F系列单片机头文件*/
#include "toppic.h"/*TOPPIC开发板头文件*/
#include "delay.h"/*爱晶电子提供的延时头文件*/
/*0-F共阴字形码表*/
const rom uchar sz[17]={0x3f  , 0x06 , 0x5b , 0x4f , 0x66 ,
   0x6d ,0x7d , 0x07 , 0x7f  , 0x6f , 0x77 , 0x7c ,
   0x39 , 0x5e , 0x79 , 0x71 , 0x00};


//EEPROM写数据函数
int WriteEE(int addr,int data)
{
    do{}
    while(EECON1bits.WR == 1);//等待写完成
   
    EEADR=addr;//写入地址信息
    EEDATA=data;//写入数据信息
    EECON1bits.EEPGD = 0;//操作EEPROM
    EECON1bits.WREN = 1; //写EEPROM允许
    EECON2 = 0x55;//写入特定时序
    EECON2 = 0xaa;
    EECON1bits.WR=1; //执行写操作
    do{}
    while(EECON1bits.WR == 1);//等待写完成
    EECON1bits.WREN = 0;//禁止写入EEPROM
}
//EEPROM读数据函数
int ReadEE(int address)
{
    int num;
    do{}
    while(EECON1bits.RD == 1);//等待读完成
   
    EEADR=address;//写入要读的址址
   
    EECON1bits.EEPGD = 0;//操作EEPROM
    EECON1bits.RD = 1;//执行读操作
    do{}
    while(EECON1bits.RD==1);//等待读完成
    return (EEDATA); //返回读取的数据
}

void main(void) //主函数
{
    int k,shu;
    toppic_init(); /*TOPPIC开发板初始化*/
    COL1=1;/*选中4位数码管的最右边一位*/
     WriteEE(8,8); //循环调用EEPROM写函数,向地址为0~7的写入1~8
     WriteEE(8,8); //循环调用EEPROM写函数,向地址为0~7的写入1~8
     while(1)
    {
         shu=ReadEE(8);
        PORTD=sz[shu];/*送出欲显示数的字形码*/
    }
}
沙发
Ryanhsiung| | 2012-8-25 08:09 | 只看该作者
问题不清楚,不好回答!
  你可以开启仿真,打开EEPROM,写完EEPROM后 查看EEPROM是否被改成你想要的数据(要FRESH)!
     若是,但读出来不是,则是你读出程序的BUG

使用特权

评论回复
板凳
yewuyi| | 2012-8-25 08:46 | 只看该作者
库函数自带EEPROM_READ()和EEPROM_WRITE()两个读写函数,你可以直接调用。

你也可以到库函数里面找到这两个函数本征代码,然后在此基础上修改部分代码以满足你的特殊要求。

使用特权

评论回复
地板
NE5532| | 2012-8-25 09:26 | 只看该作者
如果E2数据比较重要,建议用自己写的函数,开软件仿真来调。

使用特权

评论回复
5
longjun3121| | 2012-8-25 09:31 | 只看该作者
我看你的这个函数WriteEE(8,8); //循环调用EEPROM写函数,向地址为0~7的写入1~8  应该是向地址0~7都写入数据8的,好像不是1~8的啊,还有那个写函数应该是void类型的!

使用特权

评论回复
6
zb02373|  楼主 | 2012-8-27 09:28 | 只看该作者
谢谢楼上各位!!
我用的C18,所以没有eeprom的读写函数,得自己写.
程序中应为:
    WriteEE(8,8);
    WriteEE(9,9);
我用软件仿真测试了一下,写没有问题,数据可以存进去。但没有读书来,表现在EEADR的可以变为8,但EEDATA的值仍为9。
不知是什么原因???

使用特权

评论回复
7
yewuyi| | 2012-8-27 09:35 | 只看该作者
谢谢楼上各位!!
我用的C18,所以没有eeprom的读写函数,得自己写.
程序中应为:
    WriteEE(8,8);
    WriteEE(9,9);
我用软件仿真测试了一下,写没有问题,数据可以存进去。但没有读书来,表现在EEADR的可以变为8 ...
zb02373 发表于 2012-8-27 09:28


我没有装C18,但根据我的了解,没有读写EEPROM库函数的可能很小,你可以再查查,也许函数名不是我给你的那个名字,你可以到安装目录下打开文件快速找找看。

使用特权

评论回复
8
zb02373|  楼主 | 2012-8-28 11:11 | 只看该作者
C18中有通过I2C读写外部eeprom的函数,但没有读写PIC内部eeprom的函数.
我无论怎么测,就是读不到真实的数据.写没有问题,已通过仿真看到,就是读的不对。EEADR可以按要求改变地址,但EEDATA总是显示9,到底是什么原因??

使用特权

评论回复
9
yewuyi| | 2012-8-28 14:21 | 只看该作者
注意别读成FLASH空间了

使用特权

评论回复
10
xzhihui| | 2012-8-28 14:59 | 只看该作者
我用的是PIC18F系列的,EEPROM也是自己写的,但是和你的有点小差别。
我不清楚你用的是那款芯片,不晓得是不是和我用的不一样。我建议你再看下Data  Sheet.
弄清楚读写的具体操作。
我的读写和你的区别是:
CFGS=0;//访问选择EEPROM或配置位,读写都要置零。
另外,我在读写的时候是没有那么多等待,只有在执行写操作的时候等待一次。
我的经验也少,不知道对你有没有用。我遇到问题的做法就是多做测试(想不通的时候的笨方法)。

使用特权

评论回复
11
yewuyi| | 2012-8-28 16:37 | 只看该作者
读无需延时,写需要延时

使用特权

评论回复
12
hjh002| | 2012-8-30 22:57 | 只看该作者
10楼已经给出答案了.
给一个我自己写的MCC18的 18F2550的EE读写程序.其实就是多了一条EECON1bits.CFGS=0;
程序是通过验证OK的.

unsigned char EEPROM_READ(unsigned char adrs)
{
        EEADR=adrs;
        EECON1bits.EEPGD=0;
        EECON1bits.CFGS=0;
        EECON1bits.RD=1;
        NOP();
        return EEDATA;
}

void        EEPROM_WRITE(unsigned char adrs,unsigned char dat)
{
        EEADR=adrs;
        EEDATA=dat;
        EECON1bits.EEPGD=0;
        EECON1bits.CFGS=0;
        EECON1bits.WREN=1;
       
        INTCONbits.GIE = 0;
        EECON2=0x55;
        EECON2=0xAA;
        EECON1bits.WR=1;
        CLRWDT();
        while(EECON1bits.WR); //等待写周期完成
        EECON1bits.WREN=0;
        INTCONbits.GIE = 1;
       
}

使用特权

评论回复
13
hjh002| | 2012-8-30 23:04 | 只看该作者
我没有装C18,但根据我的了解,没有读写EEPROM库函数的可能很小,你可以再查查,也许函数名不是我给你的那个名字,你可以到安装目录下打开文件快速找找看。 ...
yewuyi 发表于 2012-8-27 09:35

MCC18 真的没有读写EE库函数的哦,得自己写.

使用特权

评论回复
14
zenith1032| | 2013-4-7 11:46 | 只看该作者
注意用MPLAB IDE做debug的时候,要把debugger里面setting下,preserve eeprom on program给勾上。

使用特权

评论回复
15
yimankehao| | 2013-4-22 10:40 | 只看该作者
NE5532 发表于 2012-8-25 09:26
如果E2数据比较重要,建议用自己写的函数,开软件仿真来调。

请教一下,调用自带函数EEPROM函数有什么风险?

使用特权

评论回复
16
NE5532| | 2013-4-22 11:06 | 只看该作者
yimankehao 发表于 2013-4-22 10:40
请教一下,调用自带函数EEPROM函数有什么风险?

把自己的脑袋交给别人玩,始终不是一件好事。私人老板不听原因,直接炒你鱿鱼。

使用特权

评论回复
17
yimankehao| | 2013-4-23 10:06 | 只看该作者
我用过PIC内部E2PROM内部函数,主要是**按键变化后的改变值。项目量产很久了。PIC系统自带.h文件在调用write_eeprom 函数之前,会先行判断WR。确信上次写操作已经结束后,才会去调用新一次的写操作。

使用特权

评论回复
18
rosejeky2008| | 2014-3-10 22:11 | 只看该作者
#include<pic.h>
__CONFIG(HS &WDTDIS &PWRTDIS &BORDIS &LVPDIS &DUNPROT &UNPROTECT );
#define uchar unsigned char   //(00~255)
#define uint unsigned int   //(00~65535)
#define s1 RC0
uchar num,num1;
uint intnum;
bit  write=0;
const uchar table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
                        0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

uchar in_ee_addr,num;   //内部操作的EEPROM的地址(00H~FFH)
uchar EEPROMread(uchar EEAddr);
void EEPROMwrite(uchar EEAddr,uchar Cmd);

void delay(uint x)
{
        uint a,b;
        for(a=x;a>0;a--)
                for(b=110;b>0;b--);
}

void display(uchar z)
{
        PORTD=table[z];
        delay(10);
}
void scan0()
{               
                uchar i;

                if(s1==0)
                {
                        delay(10);
                        {
                                if(s1==0)
                                {
                                        num++;

                                        if(num==4)
                                                num=1;
                                        while(!s1);
                                }
                        }

                }

}


//主函数
void main(void)
{

TRISC=0xff;
TRISD=0x00;
PORTD=0x00;
while(1)
        {
                                //scan0();
                        EEPROMwrite(2,9);
                        num1=EEPROMread(2);
                display(num1);

        }

       
}
void EEPROMwrite(uchar EEAddr,uchar Cmd)
{
GIE=0;
while(WR==1);
EEADR = EEAddr;   //EEPROM的地址
EEDATA = Cmd;   //EEPROM的写数据
EEPGD = 0;
WREN = 1;
GIE=0;
EECON2 = 0x55;            //必须按这样的时序
EECON2 = 0xAA;
WR = 1;
while(WR==1);   //等待写操作完成
GIE=1;
WREN= 0;

  
}

uchar EEPROMread(uchar EEAddr)
{
        uchar d;
        EEADR = EEAddr;
        EEPGD = 0;
        GIE=0;
        RD = 1;
        while(RD==1);
        d = EEDATA;  //EEPROM的读数据
        RD=0;
        GIE=1;
        return d;
}

以上程序可以保存9。

使用特权

评论回复
19
rosejeky2008| | 2014-3-10 22:14 | 只看该作者
但下面程序不能保存到按键值,不知为什么,有点蒙了,有哪位高手点拔一下,谢了。

#include<pic.h>
__CONFIG(HS &WDTDIS &PWRTDIS &BORDIS &LVPDIS &DUNPROT &UNPROTECT );
#define uchar unsigned char   //(00~255)
#define uint unsigned int   //(00~65535)
#define s1 RC0
uchar num,num1;
uint intnum;
bit  write=0;
const uchar table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
                        0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

uchar in_ee_addr,num;   //内部操作的EEPROM的地址(00H~FFH)
uchar EEPROMread(uchar EEAddr);
void EEPROMwrite(uchar EEAddr,uchar Cmd);

void delay(uint x)
{
        uint a,b;
        for(a=x;a>0;a--)
                for(b=110;b>0;b--);
}

void display(uchar z)
{
        PORTD=table[z];
        delay(10);
}
void scan0()
{               
                uchar i;

                if(s1==0)
                {
                        delay(10);
                        {
                                if(s1==0)
                                {
                                        num++;

                                        if(num==4)
                                                num=1;
                                        while(!s1);
                                }
                        }

                }

}


//主函数
void main(void)
{

TRISC=0xff;
TRISD=0x00;
PORTD=0x00;
while(1)
        {
                                scan0();
                        EEPROMwrite(2,num);
                        num=EEPROMread(2);
                display(num);

        }

       
}
void EEPROMwrite(uchar EEAddr,uchar Cmd)
{
GIE=0;
while(WR==1);
EEADR = EEAddr;   //EEPROM的地址
EEDATA = Cmd;   //EEPROM的写数据
EEPGD = 0;
WREN = 1;
GIE=0;
EECON2 = 0x55;            //必须按这样的时序
EECON2 = 0xAA;
WR = 1;
while(WR==1);   //等待写操作完成
GIE=1;
WREN= 0;

  
}

uchar EEPROMread(uchar EEAddr)
{
        uchar d;
        EEADR = EEAddr;
        EEPGD = 0;
        GIE=0;
        RD = 1;
        while(RD==1);
        d = EEDATA;  //EEPROM的读数据
        RD=0;
        GIE=1;
        return d;
}

使用特权

评论回复
20
xupengpeng| | 2017-8-8 16:46 | 只看该作者
楼主解决了吗,我也是这样的,我用的PIC18F89K90

使用特权

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

本版积分规则

0

主题

5

帖子

0

粉丝