源程序与电路图在附件中:
EEPROM (Electrically Erasable Programmable Read-Only Memory),即电可擦可编程只读存储器,它是一种掉电后数据不丢失的存储器。ATmega8515单片机内部包含512字节的EEPROM数据存储器。它是作为一个独立的数据空间而存在的,可以按字节读写。EEPROM的访问由地址寄存器(EEARH/EEARL)、数据寄存器(EEDR)和控制寄存器(EECR)决定。EEPROM地址寄存器-EEARH与EEARL指定了512字节的EEPROM空间。EEPROM地址是线性的,从0到511。EEAR的初值没有定义。在请问EEPROM之前必须为其赋予正确的数据,懒猫建议从地址0X0001开始。对于EEPROM数据寄存器-EEDR主要作用是把要写入的数据赋值给EEDR,把要从地址单元中读出的值,要从EEAR中读取出来,就相当于一个人事中介。EEPROM控制寄存器-EECR,顾名思义当然是控制EEPROM的读写操作的了。注意在CPU写FLASH存储器的时候不能对EEPROM进行编程。
今天就学习使用8515内部的EEPROM写的小程序试一下。测试的电路主要有两部分组成按键与数码显示。按键部分包括三个按键,K1主要负责向EEPROM中写入1-20这20个数,K2是负责向EEPROM中写入随机的20个数,K3主要负责是把写入的数据读出来,并在数码管上显示。另外还加了一个小小的蜂鸣器,在操作成功后都会叫一下。其整体电路如下所示:参看附件(图1-1 硬件电路图)
好了硬件介绍完了,说说软件吧,软件也不是太难,主要就是数码显示,按键处理,至于今天主要做的EEPROM读写操作,我用的是GCC自己的库函数,它是在avr/eeprom.h这个头文件中有定义,其实很多就是宏定义,如果你想了解最好自己看看这个头文件。如果你想好好运用GCC,懒猫建议最好把avr-lib-manual数据手册读一下,虽然是英文的,但慢慢啃它还是能啃动的。关于avr/eeprom.h这个文件也在手册中有介绍,大概在242-244页,如果你看avr/eeprom.h,不太理解的可以到这个手册中看一下。
好了,下面贴上懒猫的程序:
/**************************************************************************
//文件名称:EEPROM_TEST.c
//功 能:学习使用单片机内部EEPROM
//作 者:懒猫爱飞
//建立日期:2010.11.02
//备 注:MCU-ATmega8515 开发环境-winavr100110 Crystal-8MHz
**************************************************************************/
#include <avr/io.h>
#include <inttypes.h> //关于数据类型的一些定义
#include <stdint.h> //同样是一些数据类型的定义
//#include <avr/interrupt.h> //---这个程序用不上---
#include <util/delay.h>
#include <avr/eeprom.h>
#include <stdlib.h>
#define KEY_W (PIND & _BV(PB0)) //第一个按键向EEPROM中写入1-20个数据
#define KEY_WS (PIND & _BV(PB1)) //第二个按键向EEPROM中写入随机数组
#define KEY_D (PIND & _BV(PB2)) //第三个按键让数码管循环显示
#define Display_Data PORTA //A口发送数据
#define On_Dis(N) PORTC &= ~_BV(N) //显示第的位数
#define Show_Off() PORTC |= _BV(0) | _BV(1) //关闭所有的数码管
#define Beep_Ring() PORTC ^= _BV(PC7) //Buzzer 连接在C端口的第七脚
int8_t Current_Data = 0; //当前读出的数据
int8_t Loop_Show_Flag = 0; //循环显示标志
int16_t Current_Read_Addr = 0x0001; //当前读取的地址
//将字节变量eepromx分配在EEPROM存储器(地址不透明)
int8_t eepromx __attribute__((section("eeprom")));
uint8_t EEMEM eeprom_array[] =
{
0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
};
//共阴极数码管显示码0-9黑屏
const uint8_t Dis_Code[] =
{
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00
};
//显示缓存
uint8_t Dis_Buf[]={0,0};
/**************************************************************************
//函数名称:void port_init(void)
//功 能:端口初始化
//入口参数:NULL
//出口参数:NULL
//备 注:NULL
**************************************************************************/
void port_init(void)
{
DDRA = 0xff; //端口A用于向数码管中发送数据
PORTA = 0x00; //初始化时把数码管关掉
DDRC |= (_BV(PC0))|(_BV(PC1))|(_BV(PC7)); //PC0-数码管1、PC1-数码管2、PC7-Buzzer
PORTC = 0x00;
DDRD = 0x00; //D口接三个按键
PORTD = 0x07;
}
/**************************************************************************
//函数名称:void Beep_Play(void)
//功 能:蜂鸣器蜂鸣程序
//入口参数:NULL
//出口参数:NULL
//备 注:NULL
**************************************************************************/
void Beep_Play(void)
{
int8_t cunt = 0;
for(cunt=0; cunt<100; cunt++)
{
Beep_Ring(); //连续响20次
_delay_ms(1);
}
}
/**************************************************************************
//函数名称:void Show_Display(void)
//功 能:显示函数
//入口参数:NULL
//出口参数:NULL
//备 注:NULL
**************************************************************************/
void Show_Display(void)
{
Show_Off();//消隐一下
Display_Data = Dis_Code[Dis_Buf[1]]; //显示十位
On_Dis(0);
_delay_ms(5);
Show_Off();//消隐一下
Display_Data = Dis_Code[Dis_Buf[0]]; //显示个位
On_Dis(1);
_delay_ms(5);
}
/**************************************************************************
//函数名称:void Key_Ctrl(void)
//功 能:按键处理程序
//入口参数:NULL
//出口参数:NULL
//备 注:NULL
**************************************************************************/
void Key_Ctrl(void)
{
int8_t i; //做一些临时循环变量用
//start:
//------------KEY_D:显示按键------------------//
if(!KEY_D) //KEY_D:显示按键,所有按键都是采用上升沿有效
{
while(!KEY_D);
Current_Read_Addr = 0x0001; //从地址0x0001开始读取数据
eeprom_busy_wait(); //宏定义在stdlib.h这个头文件中
Current_Data = eeprom_read_byte((int8_t*)Current_Read_Addr); //读取当前地址数据
/*
因为写入的数据都是不超过100,如果读0x0001时出现0xff,说明未写入新数据,这时循
环标志Loop_Show_Flag为关闭,否则要打开显示标志。
*/
if(Current_Data != 0xff)
{
Loop_Show_Flag = 1;
}
Beep_Play(); //读取完毕响铃
}
//------------KEY_W:写入1-20数据------------------//
if(!KEY_W)
{
while(!KEY_W);
Loop_Show_Flag = 0; //当要写数据时,关闭显示
for(i=0; i<=20; i++) //前20个地址写入1-20这20个数
{
eeprom_busy_wait();
eeprom_write_byte((int8_t*)i,(int8_t)i);
}
//再向EEPROM中写一个数据21,地址不确定
eeprom_busy_wait();
eeprom_write_byte(&eepromx,0x15);
Beep_Play(); //操作完毕响铃
}
//------------KEY_WS:写入21个随机数据------------------//
if(!KEY_WS)
{
while(!KEY_WS);
Loop_Show_Flag = 0; //当要写数据时,关闭显示
for(i=0; i<=20; i++) //前20个地址写入20个随机数据
{
eeprom_busy_wait();
eeprom_write_byte((int8_t*)i,rand()%100);
}
//再向EEPROM中写一个随机数据,地址也不确定
eeprom_busy_wait();
eeprom_write_byte(&eepromx,rand()%100);
Beep_Play(); //操作完毕响铃
}
//------------调度显示------------------//
if(Loop_Show_Flag)
{
eeprom_busy_wait();
if(Current_Read_Addr != 21) //前20个数是从0x0001-0x0020中读出
{
Current_Data = eeprom_read_byte((int8_t*)Current_Read_Addr);
}
else //第二十一个数从eepromx这介地址中读取
{
Current_Data = eeprom_read_byte(&eepromx);
}
Dis_Buf[1] = Current_Data/10;
Dis_Buf[0] = Current_Data%10;
for(i=0; i<30; i++)
{
Show_Display();
if((!KEY_W) || (!KEY_WS)) //如果此时有新有数据写入,关闭数码码管
{
Loop_Show_Flag = 0;
Show_Off(); //关闭数码码管,等待数据更新后重新显示
break;
//goto start; //最好不要作用跳转语句
}
}
Current_Read_Addr = Current_Read_Addr%21 + 1; //地址循环递增
}
}
/**************************************************************************
//函数名称:int main(void)
//功 能:主程序
//入口参数:NULL
//出口参数:0
//备 注:NULL
**************************************************************************/
int main(void)
{
/*
Dis_Buf[0] = 2; //用于测试显示函数
Dis_Buf[1] = 5;
*/
port_init();
srand(200); //设置随机种子,此函数在stdlib.h中有定义
//Beep_Play(); //用于测试蜂鸣函数,调试时使用
while(1)
{
Key_Ctrl();
/*这之间的函数用于测试eeprom的操作函数
eeprom_busy_wait();
eeprom_write_byte((int8_t* )0x02,89);
eeprom_busy_wait();
Dis_Buf[1] = eeprom_read_byte((int8_t* )0x02)/10;
Dis_Buf[0] = eeprom_read_byte((int8_t* )0x02)%10;
*/
//Show_Display(); //用于测试显示函数,调试时使用
}
return 0;
}
程序可能稍微有点长,不过不是太复杂,可以一块一块的看,应该很容易理解的哦^_^
再喊一下口号,鼓励一下自己:
每天进步一点点,开心多一点^_^
用户1824753 2014-12-30 09:14
用户1588142 2011-4-27 18:51
用户1530930 2010-11-8 10:40
huotingtu_505472073 2010-11-3 23:35