|
代码极其简单的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字...(地球人都知道数码管的管脚定义方法,在此就不贴出来了)
#ifndef FREQ
#define FREQ (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 uchar unsigned 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中存储的数值
}
} |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|