打印

16F887开机读写EEPROM的问题

[复制链接]
3092|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ZG11211|  楼主 | 2013-9-17 20:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 ZG11211 于 2013-9-17 20:43 编辑

芯片型号:PIC16F887
预计目标:将一个长整形变量(计数器)关机保存后,重新上电从EEPROM里取出。用8位数码管显示,继续计数,掉电或者关机就自动保存。
故障现象:开机后直接取出,MPU失控(不算死机,还能喘气),但是修改程序,改为程序运行以后通过按键执行取出,无任何问题。
应急解决方案:将变量名unsigned long y  改为 long y 就可以工作了
求解!。。。。。。。。。。。。。。
部分代码如下
volatile bank3 union jishu_value   //定义一个共用体
{
     long y;        
  unsigned  char eep_data[4];
}jishu_data;

最大的困惑就是,如果不是在开机后自动先读取的话,等到程序运行以后,用按键操作的方式来读取,怎么定义那个变量都没问题。
沙发
XIEYUANBIN| | 2013-9-17 20:32 | 只看该作者
你试试开机延时几秒钟再读出呢?或者DEBUG看看。

使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
ZG11211 + 3 谢谢探讨
板凳
ZG11211|  楼主 | 2013-9-17 20:35 | 只看该作者
本帖最后由 ZG11211 于 2013-9-17 20:38 编辑

谢谢斑竹,我试过延时XXX毫秒,无效,甚至改成主代码里开机判断标志位再去读EEP(就是等程序跑到大循环里以后再去读取),都是一样的效果。
如果不要开机就读取,而是改等到用KEY去执行读或者写,都没有任何问题。

使用特权

评论回复
地板
NE5532| | 2013-9-20 09:39 | 只看该作者
1.既然是“计数器”,那么无论读出来的值等于多少,你的程序都应该可以处理,如果读出来的值可以造成你程序混乱,只能说明你程序写的不好。
2.读E2的操作本来就不能一上电就弄,根据你的电源上升速度决定,如果没有急迫的需求,等100-500mS未尝不可。
3.还可以试着在E2中保存2份这个值,一个原码,一个补码,读的时候两者必须合得上,才运行,否则重读。

使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
ZG11211 + 3 谢谢探讨
5
ZG11211|  楼主 | 2013-9-20 10:48 | 只看该作者
本帖最后由 ZG11211 于 2013-9-20 11:08 编辑
NE5532 发表于 2013-9-20 09:39
1.既然是“计数器”,那么无论读出来的值等于多少,你的程序都应该可以处理,如果读出来的值可以造成你程序 ...


谢谢版主百忙之中来探讨!
我补充一下
1:我用按键来执行读出或者写入,都没有问题,而且程序也非常简单。
2:同样的程序,我将这个变量声明为无符号长整形就不行,声明为有符号长整形就没有问题(如果用1的方法来读,有符号和无符号都没有问题,均正常读取),开机延时再读取我也试过,没有什么分别。
3:我在公司里用的是数码管,为了验证这个问题,回家后我用12864液晶重新写了个验证程序,发现还是一样的效果,只要是无符号长整形的变量就不行,和读取的地址长短没有关系,太奇怪了。

还有就是用16F676的话,就不会出现这个问题,
以下是用16F887的部分代码

#include"pic.h"
__CONFIG(0x2044);         //芯片配置字
volatile bank3 union jishu   //定义一个共用体
//volatile  union jishu   //测试过,与上面效果一样
{
//unsigned long y; //这样写就不行
     long y; //无符号长整形在开机读取EEP时会出现死机,改用有符号型
  unsigned  char eep_data[4];
}Frequency;

void Delay_ms(unsigned char j)
{
unsigned  char i;
for(;j>0;j--)
for(i=100;i>0;i--)
{;}
}

unsigned char EEPROMread(unsigned char EEAddr)
{
unsigned char ReEEPROMread;
EEADR = EEAddr;
  EEPGD = 0;//访问数据存储器
RD = 1;    //读有效
//asm("nop"); //空操作延时,要不要没有什么区别
ReEEPROMread = EEDATA;  //EEPROM的读数据
return ReEEPROMread;
}
void EEPROMwrite(unsigned char EEAddr,unsigned char Cmd)
{
EEADR = EEAddr;   //EEPROM的地址
EEDATA = Cmd;   //EEPROM的写数据  
EEPGD = 0;
WREN = 1;//写使能
EECON2 = 0x55;            //
EECON2 = 0xAA;
WR = 1;      //写有效
while(WR==1);   //等待写操作完成
}
/************************************
读取EEP数据
************************************/
void EEP_LOAD(void)
{
GIE = 0;
Frequency.eep_data[0] =EEPROMread(0x03);
Frequency.eep_data[1] =EEPROMread(0x04);
Frequency.eep_data[2] =EEPROMread(0x05);
Frequency.eep_data[3] =EEPROMread(0x06);
GIE = 1;        //重开总中断
}
/***************************************
数据处理后保存到EEP
***************************************/
void EEP_SAVE(void)
{
GIE = 0;
EEPROMwrite(0x03, Frequency.eep_data[0]);
EEPROMwrite(0x04, Frequency.eep_data[1]);
EEPROMwrite(0x05, Frequency.eep_data[2]);
EEPROMwrite(0x06, Frequency.eep_data[3]);
Delay_ms(200);
GIE = 1;
}

void main( void)
{
//Delay_ms(10);//延时不延时没有任何效果
EEP_LOAD();//开机先读出数据
while(1)
   {
  //显示部分
   }
}

使用特权

评论回复
6
NE5532| | 2013-9-20 16:49 | 只看该作者
掉电以后,只要用编程器验证,这个数据正确写入了E2,就应该从怎样正确读取的方向来找。声明成singed或者unsigned只能造成数据的表达范围不同,无关乎写入读取的事。不要给自己设定这样的,神一样的命题去找问题,多怀疑流程上是否存在漏洞。

使用特权

评论回复
7
NE5532| | 2013-9-20 16:50 | 只看该作者
另外你延时有没有试过加长到1秒有用没?没用就不是上电电源稳定的问题,不用找这个方向三。

使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
ZG11211 + 3 很给力!
8
ZG11211|  楼主 | 2013-9-20 23:37 | 只看该作者
本帖最后由 ZG11211 于 2013-9-20 23:48 编辑

再次感谢楼主哦探讨,这个和写入数据无关,我讨论的是读取问题。就算它读出的全是FF或者随机数我都无所谓,只要能正确读出,程序就能正常运转,现在讨论的问题是,开机读取的数据如果转换成无符号长整形变量就会当机,如果是有符号长整形或者使用判断语句进入按键执行程序再去读取都没有问题。不是我死缠烂打,只是我也是喜欢刨根问底的,所以还是想验证一下,呵呵,我手上就有板子,版主提出的方案我都验证过,没发现有什么突破口,欢迎探讨!
开机延时也不是问题,延时多少都不影响有符号长整形的读取,延时再长也无法将读取的数组转换成无符号长整形变量。
供电也不是问题,无论是用7805还是MCP201,结果都是一样。
再次补充一下,这个和掉电保存数据无关,我的本意是公司某个产品需要进行老化测试,测试次数是10W级以上的,所以我设计的用8为数码管显示,为了方便大家操作,就设计了掉电自动保存当前计数值,次日上班上电继续上一次的计数次数,之前的用16F676做的没有任何问题,这次做的由于需要增加状态检测,所以选择了16F887,其实8位数也用不着无符号长整形这么大的数,有符号长整形完全满足8位数千万次的记录次数。一样的程序,将那个变量声明改一下就出现不同的效果!

使用特权

评论回复
9
NE5532| | 2013-9-21 08:33 | 只看该作者
既然上电延迟多少都会出现问题,那就不是上电的问题,既然有LED,你上电直接把E2里读出来的数据按Char型送显,能读对不?

使用特权

评论回复
10
ZG11211|  楼主 | 2013-9-21 09:48 | 只看该作者
好的,等明天上班了就去试试,不过我觉得char肯定没问题。

使用特权

评论回复
11
NE5532| | 2013-9-21 10:02 | 只看该作者
ZG11211 发表于 2013-9-21 09:48
好的,等明天上班了就去试试,不过我觉得char肯定没问题。

如果你觉得Char没问题,那就跟上电下电没有任何问题了,只有找你自己的算法漏洞了。

使用特权

评论回复
12
逍遥派掌门| | 2013-9-24 18:13 | 只看该作者
本帖最后由 逍遥派掌门 于 2013-9-24 18:22 编辑

debug 一下,看看变量的值

另外,检查数据类型和你的定义有没有冲突。

使用特权

评论回复
13
A旭日电子A| | 2018-10-10 20:56 | 只看该作者
值得学习和探讨!

使用特权

评论回复
14
WUZHIXIONG23| | 2018-10-19 18:58 | 只看该作者
我觉得跟读取的地址有关

使用特权

评论回复
15
QQ826220679| | 2019-1-27 12:39 | 只看该作者
对于PIC18f26K22相似芯片,内部有1024字节EEPROM,只有XC8 1.34及以前例如1.33版本能用eeprom_read(addr),及eeprom_write(addr,dat),函数库,能读写EEPROM ,并且能读写至1023地址。

其他版本XC8,如1.36,1.37,1.38,经实验不能读写,特此留下记录。

使用特权

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

本版积分规则

个人签名:工作不养闲人,团队不养懒人。赚不到钱赚知识,赚不到知识赚经历,赚不到经历赚阅历,让人迷茫的原因只有一个,那就是本该拼搏的年纪,却想得太多,做的太少!

29

主题

1113

帖子

8

粉丝