!!!痛苦,AVR内部EEPROM读写失败,已经严格按照官方手册规定的步骤来写,极其精简仍然不成功,
代码极其简单的EEPROM读写程序,调试良久,仍不成功,已经无语了。求助各位高手,指点一二!硬件电路连接:(很简单的,就不贴电路图出来了)
1、使用4位共阳数码管显示数值。
2、使用外部晶振8MHz。
3、+5V外部电源供电。
4、使用标准的ISP下载口下载程序。(本人有并行打印口和USB下载器,两者都能正常下载程序)
软件和程序设置:
1、使用AVR Studio 4.12编程软件,下载到单片机的软件是:ProgISP V1.66版。
2、AVR Studio 4.12设置频率为8MHz,优化程度选:00(即没有优化)。
3、单纯为了测试EEPROM有没有成功,除了显示函数外,其它函数和功能一概没有。
4、严格按照官方手册规定的步骤来写。
http://cache.amobbs.com/bbs_upload782111/files_47/ourdev_697168YS8UFL.jpg
(原文件名:GCC中的频率设置.jpg)
下载软件ProgISP V1.66的设置:
1、勾选:外部晶振(3.0--MHz)起动时间16K CK+64ms[...省略N字...]
2、不勾选:使能JTAG接口。 JTAGEN
3、勾选:使能ISP编程。SPIEN
4、勾选:执行芯片擦除时保留EEPROM的内容。EESAVE
5、其它选项使用默认值。
6、时钟校正框选择:1.0MHz。(1.0MHz-8.0MHz都试过了不成功)
7、编程框选择:“芯片擦除”、“编程FLASH”、“校验FLASH”、“编程熔丝”、“数据自动重载”,其它不选。
熔丝低位:(1=未被编程,0=被编程)
1 BODLEVEL: BOD触发电平,默认值:1
1 BODEN: BOD使能,默认值:1
1 SUT1: 选择启动时间,默认值:1
1 SUT0: 选择启动时间,默认值:0
1 CKSEL3: 选择时钟源,默认值:0
1 CKSEL2: 选择时钟源,默认值:0
1 CKSEL1: 选择时钟源,默认值:0
1 CKSEL0: 选择时钟源,默认值:1
熔丝高位:
1 OCDEN: 使能OCD,默认值:1
1 JTAGEN: JTAG仿真调试接口,默认值:0
0 SPIEN: SPI下载允许,使能串行程序和数据下载,默认值:0
1 CKOPT: 振荡器选项,默认值:1
0 EESAVE: 执行芯片擦除时EEPROM的内容保留,默认值:1(1:不保留;0:保留)
0 BOOTSZ1:选择BOOT区大小,默认值:0
0 BOOTSZ0:选择BOOT区大小,默认值:0
1 BOOTRST:选择复位向量,默认值:1
http://cache.amobbs.com/bbs_upload782111/files_47/ourdev_697333HY9354.jpg
(原文件名:下载器抓图01.jpg)
http://cache.amobbs.com/bbs_upload782111/files_47/ourdev_697334RR5IGH.jpg
(原文件名:下载器抓图02.jpg)
下面是程序源码:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>
//*************************************************************************
// 定义LED数码管的位选端和小数点位置
//*************************************************************************
...省略N字...(地球人都知道数码管的管脚定义方法,在此就不贴出来了)
#ifndefFREQ
#defineFREQ (8)// 单片机主频为8MHz,用于延时子程序,括号(8)里面的“8”表示单片机的主频为8MHz。
#endif
//*************************************************************************
// 精确延时定义
//*************************************************************************
#define delay_1us(x)\
_delay_loop_2((uint)((x)*FREQ/4))//_delay_loop_2(xxx)的意思是等于=xxx*4(个cpu时钟周期)/8(M时钟)
//#define delay_1us(x)中的括号(x)里面的“x”表示延时x uS。例如:x为1表示延时1uS,x为550表示延时550uS。
#define ucharunsigned char
#define uint unsigned int
uchar scandata[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff,0xfe,0xf7,0xbf};//共阳极数码管段码,为0-9,10:空白和11:上标-,12:下标_,13:中间-
//*************************************************************************
// 显示函数
//*************************************************************************
void Display(uint i)
{
...省略N字...(很简单的显示程序,地球人都知道,在此就不贴出来了)
}
//*************************************************************************
// AVR内部EEPROM写函数
//*************************************************************************
void EEPROM_write(uint addr,uint adata) //写EEPROM函数
{
while(EECR & (1<<EEWE));//等待上一次写操作结束
EEAR=addr; //配置地址
EEDR=adata;//配置数据
EECR |= (1<<EEMWE);//置位EEMWE
EECR |= (1<<EEWE);//置位EEWE以启动写操作
}
//*************************************************************************
// AVR内部EEPROM读函数
//*************************************************************************
uchar EEPROM_read(uint addr) //读EEPROM函数
{
while(EECR & (1<<EEWE)); //等待上一次写操作结束
EEAR=addr; //配置地址
EECR |= (1<<EERE);//设置EERE以启动读操作
return EEDR; //直接从数据寄存器返回数据,不需要另外定义变量了。
}
//*************************************************************************
// 主程序
//*************************************************************************
int main(void)
{
DDRA=0b11111111; //设置PA端口为输出口,1为输出,0为输入。(段码)
DDRC|=0b00001111; //设置PC端口的第1~4个端口为输出口。(位选端)
uint i=99;
uint j=57;
EEPROM_write(2,j); //在地址2的位置上,写入数据j。(把57这个数存入EEPROM,然后再读出来,以此验证读写是否成功)
delay_1us(10); //延时10us,让写和读之间有个空隙。
i=EEPROM_read(2); //从第2个地址读取数据。
while(1)
{
Display(i); //显示EEPROM中存储的数值
}
} 先用库函数解决,再用自己的程序对比。
如果库函数也出错,换芯片。
换芯片仍错,换厂家或使用外置EEPROM。
还错,换工作! 回复【1楼】cock
先用库函数解决,再用自己的程序对比。
......
-----------------------------------------------------------------------
什么是“库函数”?? 我用m8的eeprom很好用,cvavr下很方便。 我用的M64内部EEPROM,就照抄手册上的那段汇编程序。现在稳如磐石。操作EEPROM,最好关中断。另外还要记得打开BOD哦。 回复【楼主位】Ilove51andAVR
-----------------------------------------------------------------------
#include <avr/eeprom.h>.....都已经引用了却不用,好好看看手册。 做这种无用功!为何不直接用库函数,而且具有通用性,多好啊 参考一下iar的自带的
写数据
#define __EEPUT(ADR,VAL){while (EECR & 0x02); \
EEAR = (ADR); EEDR = (VAL); EECR = 0x04; EECR = 0x02;}
读数据
#define __EEGET(VAR, ADR) {while (EECR & 0x02); \
EEAR = (ADR); EECR = 0x01; (VAR) = EEDR;} 回复【5楼】huayuliang 花生
回复【楼主位】ilove51andavr
-----------------------------------------------------------------------
#include <avr/eeprom.h>.....都已经引用了却不用,好好看看手册。
-----------------------------------------------------------------------
回复【6楼】jason1927
做这种无用功!为何不直接用库函数,而且具有通用性,多好啊
-----------------------------------------------------------------------
我汗啊,原来AVR Studio 4.12(GCC)编程软件已经自带了读写语句,只需要三句就搞定了:
i=eeprom_read_byte((uchar *)0x02); //从EEPROM读取0x02地址处的数据赋给i。
eeprom_busy_wait();//等待EEPROM读写空闲
eeprom_write_byte((uchar *)0x02,j); //把j的值写入EEPROM地址0x02处。
以上三句就搞定了一切,根本用不着按ATMega16的官方手册来编写EEPROM的程序。看来对GCC编程软件自带的库函数还不熟悉。
已经调试成功,谢谢大家! 回复【楼主位】ilove51andavr
按ATMega16的官方手册来编写EEPROM的程序,
-----------------------------------------------------------------------
因为手册写EEPROM的程序时序有误。
问题出现在最後两句, ECR |= (1<<EEMWE);//置位EEMWE
及 EECR |= (1<<EEWE);//置位EEWE以启动写操作。ASM 程序没问题, C 程序超过了容许时限(四个周期)。 超容许时限(四个周期)是因为优化级最低时,把SFR当RAM操作,才超时的。优化到0级之外的其它级,就可以了。 都是高手 库自带的函数,好方便的 mark。。。。 winavr中,有些芯片对时序有要求的寄存器设置需要将优化等级设置为-O0以上,比较推荐-Os 不是有内部的读写函数吗? 这个。。。其实真的用内部函数就好了嘛、、 学习了,刚要用 本来内部有的,我以前也出过问题,那个DATASHEET里的要改一下也可以用的 chengtina 发表于 2012-3-28 09:15 static/image/common/back.gif
本来内部有的,我以前也出过问题,那个DATASHEET里的要改一下也可以用的
datasheet里面的函数需要修改什么? zhengyiqun 发表于 2013-8-16 08:52 static/image/common/back.gif
datasheet里面的函数需要修改什么?
void EEPROM_write(uint uiAddress, uchar ucData)
{
while(EECR & (1<<EEWE)) /* 等待上一次写操作结束 */
;
EEAR = uiAddress; /* 设置地址和数据寄存器*/
EEDR = ucData;
EECR |= (1<<EEMWE); /* 置位EEMWE */
// EECR |= (1<<EEWE);
EECR = (1<<EEWE) | (1<<EEMWE); //修改这里 /* 置位EEWE 以启动写操作*/
} chengtina 发表于 2013-8-16 17:00
void EEPROM_write(uint uiAddress, uchar ucData)
{
while(EECR & (1
置位EEMWE前加上一句cli();写完成以后加上,sei(); chengtina 发表于 2013-8-16 17:00 static/image/common/back.gif
void EEPROM_write(uint uiAddress, uchar ucData)
{
while(EECR & (1
读取EEPROM的内容函数是否有这样的情况?我现在是ATMEGA328P在用datasheet中的的读取EEROM函数出现有问题!!读取一个变量的内容变成oxff;等下次上电可能就OK了~~EEPROM内存的数据没变,只是读上来有问题~~ chengtina 发表于 2013-8-16 17:00
void EEPROM_write(uint uiAddress, uchar ucData)
{
while(EECR & (1
找到您去年的回复,解决了我的问题,谢谢! 用CVAVR是最方便的,直接使用就行。eeprom unsigned char a;a= 搞了一个早上,看到这个帖子一下就搞好了,谢谢{:lol:} M64 M128 内置eeprom有掉数据,不知道程序哪里的问题{:mad:} 这种情况,我一般先看官方汇编程序。
页:
[1]