//-----------------------------------------------------------------
// 名称: EEPROM读写与数码管显示
//-----------------------------------------------------------------
// 说明: 本例运行时,按下K1将向EEPROM中写入1~21,按下K2时写入无规律
// 的21个数,按下K3时读取EEPROM中的21个数并循环显示.
// 所读写的21个数中,前20个在EEPROM中的地址是透明的(0x0001~0x0014),
// 最后的第21个数其地址是不透明的.
//
//-----------------------------------------------------------------
#define F_CPU 4000000UL //4M晶振
#include <avr/io.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <stdlib.h>
#define INT8U unsigned char
#define INT16U unsigned int
//按键定义
#define Write_1_21_Key_DOWN() ((PINB&0x01)==0x00)
#define Write_Random_Key_DOWN() ((PINB&0x08)==0x00)
#define Loop_Show_Key_DOWN() ((PINB&0x40)==0x00)
//蜂鸣器定义
#define BEEP() (PORTD ^= 0x80)
//将字节变量eepromx分配于EEPROM存储器(地址不透明)
INT8U eepromx __attribute__((section("eeprom")));
//下面的数组也被分配于EEPROM,编译后生成EEP文件.
//(其中EEMEM即__attribute__((section("eeprom")))
//后续代码未使用本数组.
INT8U eeprom_array[] EEMEM =
{
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 INT8U SEG_CODE[] =
{0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};
//分解后的待显示数位
INT8U Display_Buffer[] = {0,0};
//-----------------------------------------------------------------
// 数码管显示字节
//-----------------------------------------------------------------
void Show_Count_ON_DSY()
{
PORTD = 0xFF;
PORTC = SEG_CODE[Display_Buffer[1]];
PORTD = 0xFE;
_delay_ms(2);
PORTD = 0xFF;
PORTC = SEG_CODE[Display_Buffer[0]];
PORTD = 0xFD;
_delay_ms(2);
}
//-----------------------------------------------------------------
// 响铃子程序
//-----------------------------------------------------------------
void Play_BEEP()
{
INT16U i;
for(i = 0;i<300;i++)
{
BEEP();
_delay_us(200);
}
}
//------------------------------------------------------------------
// 主程序
//------------------------------------------------------------------
int main()
{
INT8U Current_Data,LOOP_SHOW_FLAG = 0;
INT16U i,Current_Read_Addr = 0x0001;
DDRC = 0xFF; PORTD = 0xFF; //配置输出端口
DDRD = 0xFF; PORTD = 0xFF;
DDRB = 0x00; PORTB = 0xFF; //配置输入端口
srand(200); //设置随机种子
while(1)
{
start:
//K1:循环显示------------------------------------------------
if(Loop_Show_Key_DOWN())
{
Current_Read_Addr = 0x0001;
eeprom_busy_wait();
Current_Data = eeprom_read_byte((INT8U*)Current_Read_Addr);
if(Current_Data != 0xFF) LOOP_SHOW_FLAG = 1;
Play_BEEP();
while(Loop_Show_Key_DOWN());
}
//K2:写入1~21(0x01~0x15)-------------------------------------
if (Write_1_21_Key_DOWN())
{
LOOP_SHOW_FLAG = 0;
for(i = 1;i<=20;i++)
{
eeprom_busy_wait();
eeprom_write_byte((INT8U*)i,(INT8U)i);
}
eeprom_busy_wait();
eeprom_write_byte(&eepromx,0x15);
Play_BEEP();
while(Write_1_21_Key_DOWN());
}
//K3:写入21个随机数------------------------------------------
if (Write_Random_Key_DOWN())
{
LOOP_SHOW_FLAG=0;
for(i = 1;i<=20;i++)
{
eeprom_busy_wait();
eeprom_write_byte((INT8U*)i,rand()%100);
}
eeprom_busy_wait();
eeprom_write_byte(&eepromx,rand()%100);
Play_BEEP();
while(Write_Random_Key_DOWN());
}
if (LOOP_SHOW_FLAG)//----------------------------------------
{
eeprom_busy_wait();
if(Current_Read_Addr != 21)
Current_Data = eeprom_read_byte((INT8U*)Current_Read_Addr);
else
Current_Data = eeprom_read_byte(&eepromx);
Display_Buffer[1] = Current_Data/10;
Display_Buffer[0] = Current_Data%10;
for(i = 0;i<160;i++)
{
Show_Count_ON_DSY();
if(Write_1_21_Key_DOWN()||Write_Random_Key_DOWN())
{
LOOP_SHOW_FLAG = 0;
PORTD = 0xFF;
goto start;
}
}
Current_Read_Addr = Current_Read_Addr%21+1;
}
}
}