单片机内部EEPROM的应用
2013-04-19 09:58
393 查看
STC89C51、52内部都自带有2K字节的EEPROM,54、55和58都自带有16K字节的EEPROM,STC单片机是利用IAP技术实现的EEPROM,内部Flash擦写次数可达100,000 次以上,先来介绍下ISP与IAP的区别和特点。
[align=left]知识点:ISP与IAP介绍[/align]
[align=left]ISP:In System Programable 是指在系统编程,通俗的讲,就是片子已经焊板子上,不用取下,就可以简单而方便地对其进行编程。比如我们通过电脑给STC单片机下载程序,或给AT89S51单片机下载程序,这就是利用了ISP技术。[/align]
[align=left]IAP:In Application Programable 是指在应用编程,就是片子提供一系列的机制(硬件/软件上的)当片子在运行程序的时候可以提供一种改变flash数据的方法。通俗点讲,也就是说程序自己可以往程序存储器里写数据或修改程序。这种方式的典型应用就是用一小段代码来实现程序的下载,实际上单片机的ISP功能就是通过IAP技术来实现的,即片子在出厂前就已经有一段小的boot程序在里面,片子上电后,开始运行这段程序,当检测到上位机有下载要求时,便和上位机通信,然后下载数据到存储区。大家要注意千万不要尝试去擦除这段ISP引导程序,否则恐怕以后再也下载不了程序了。[/align]
STC单片机内部有几个专门的特殊功能寄存器负责管理ISP/IAP功能的,见表1。
[align=center]表1 ISP/IAP相关寄存器列表[/align]
ISP_DATA:ISP/IAP操作时的数据寄存器。
ISP/IAP从Flash读出的数据放在此处,向Flash写入的数据也需放在此处。
ISP_ADDRH:ISP/IAP操作时的地址寄存器高八位。
ISP_ADDRL:ISP/IAP操作时的地址寄存器低八位。
ISP_CMD:ISP/IAP操作时的命令模式寄存器,须命令触发寄存器触发方可生效。命令模式如表2所示。
[align=center]表2 ISP_CMD寄存器模式设置[/align]
程序在系统ISP程序区时可以对用户应用程序区/数据Flash区(EEPROM)进行字节读/字节编程/扇区擦除;程序在用户应用程序区时,仅可以对数据Flash区(EEPROM)进行字节读/字节编程/扇区擦除。STC89C51RC/RD+系列单片机出厂时已经固化有ISP引导码,并设置为上电复位进入ISP程序区,并且出厂时就已完全加密。
ISP_TRIG:ISP/IAP操作时的命令触发寄存器。
在ISPEN(ISP_CONTR.7) =1时,对ISP_TRIG 先写入46h,再写入B9h,ISP/IAP命令才会生效。
STC89C52RC,STC89LE52RC单片机内部可用Data Flash(EEPROM)的地址如表3所示,其它型号单片机请查阅相关资料。
[align=center]表3 STC89C52RC、STC89LE52RC单片机内部EEPROM地址表[/align]
[align=left]每个扇区为512字节,建议大家在写程序时,将同一次修改的数据放在同一个扇区,方便修改,因为在执行擦除命令时,一次最少要擦除一个扇区的数据(需要提供扇区的首地址),每次在更新数据前都必须要擦除原数据方可重新写入新数据,不能直接在原来数据基础上更新内容。[/align]
注意:上面的是数据存储区的地址,程序存储区地址是从0~1FFF,共8K,程序区只能是ISP编程。
下面通过一个例子来讲解STC系列单片机EEPROM的具体用法。
【例】:在TX-1C实验板上实现如下描述,操作STC单片机自带的EEPROM,存储一组按秒递增的二位数据,并且将数据实时显示在数码管上,数据每变化一次就往EEPROM中写入一次,当关闭实验板电源,再次开启电源时,从EEPROM中读取先前存储的数据,接着递增显示。
新建文件part3.4.4.c,程序代码如下:
#include
#include //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
#define RdCommand 0x01 //定义ISP的操作命令
#define PrgCommand 0x02
#define EraseCommand 0x03
#define Error 1
#define Ok 0
#define WaitTime 0x01 //定义CPU的等待时间
sfr ISP_DATA=0xe2; //寄存器申明
sfr ISP_ADDRH=0xe3;
sfr ISP_ADDRL=0xe4;
sfr ISP_CMD=0xe5;
sfr ISP_TRIG=0xe6;
sfr ISP_CONTR=0xe7;
sbit dula=P2^6; //申明U1锁存器的锁存端
sbit wela=P2^7; //申明U2锁存器的锁存端
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uchar num;
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
void display(uchar shi,uchar ge) //显示子函数
{
dula=1;
P0=table[shi]; //送十位段选数据
dula=0;
P0=0xff; //送位选数据前关闭所有显示,防止打开位选锁存时
wela=1; //原来段选数据通过位选锁存器造成混乱
P0=0xfe; //送位选数据
wela=0;
delayms(5); //延时
dula=1;
P0=table[ge]; //送个位段选数据
dula=0;
P0=0xff;
wela=1;
P0=0xfd;
wela=0;
delayms(5);
}
/* ================ 打开 ISP,IAP 功能 ================= */
void ISP_IAP_enable(void)
{
EA = 0; /* 关中断 */
ISP_CONTR = ISP_CONTR & 0x18; /* 0001,1000 */
ISP_CONTR = ISP_CONTR | WaitTime; /* 写入硬件延时 */
ISP_CONTR = ISP_CONTR | 0x80; /* ISPEN=1 */
}
/* =============== 关闭 ISP,IAP 功能 ================== */
void ISP_IAP_disable(void)
{
ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
ISP_TRIG = 0x00;
EA = 1; /* 开中断 */
}
/* ================ 公用的触发代码 ==================== */
void ISPgoon(void)
{
ISP_IAP_enable(); /* 打开 ISP,IAP 功能 */
ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */
ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */
_nop_();
}
/* ==================== 字节读 ======================== */
unsigned char byte_read(unsigned int byte_addr)
{
ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址赋值 */
ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
ISP_CMD = ISP_CMD & 0xf8; /* 清除低3位 */
ISP_CMD = ISP_CMD | RdCommand; /* 写入读命令 */
ISPgoon(); /* 触发执行 */
ISP_IAP_disable(); /* 关闭ISP,IAP功能 */
return (ISP_DATA); /* 返回读到的数据 */
}
/* ================== 扇区擦除 ======================== */
void SectorErase(unsigned int sector_addr)
{
unsigned int iSectorAddr;
iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */
ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
ISP_ADDRL = 0x00;
ISP_CMD = ISP_CMD & 0xf8; /* 清空低3位 */
ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3 */
ISPgoon(); /* 触发执行 */
ISP_IAP_disable(); /* 关闭ISP,IAP功能 */
}
/* ==================== 字节写 ======================== */
void byte_write(unsigned int byte_addr, unsigned char original_data)
{
ISP_ADDRH = (unsigned char)(byte_addr >> 8); /* 取地址 */
ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */
ISP_CMD = ISP_CMD | PrgCommand; /* 写命令2 */
ISP_DATA = original_data; /* 写入数据准备 */
ISPgoon(); /* 触发执行 */
ISP_IAP_disable(); /* 关闭IAP功能 */
}
void main()
{
uchar a,b,num1;
TMOD=0x01; //设置定时器0为工作方式1(0000 0001)
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
num1=byte_read(0x2000);//程序开始时读取EEPROM中数据
if(num1>=60) //防止首次上电时读取出错
num1=0;
while(1)
{
if(num>=20)
{
num=0;
num1++;
SectorErase(0x2000);//擦除扇区
byte_write(0x2000,num1);//重新写入数据
if(num1==60)
{
num1=0;
}
a=num1/10;
b=num1%10;
}
display(a,b);
}
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
num++;
}
分析:程序中关健部分已经用注释加以说明,请读者编译程序下载后观察实际演示效果。
[align=left]知识点:ISP与IAP介绍[/align]
[align=left]ISP:In System Programable 是指在系统编程,通俗的讲,就是片子已经焊板子上,不用取下,就可以简单而方便地对其进行编程。比如我们通过电脑给STC单片机下载程序,或给AT89S51单片机下载程序,这就是利用了ISP技术。[/align]
[align=left]IAP:In Application Programable 是指在应用编程,就是片子提供一系列的机制(硬件/软件上的)当片子在运行程序的时候可以提供一种改变flash数据的方法。通俗点讲,也就是说程序自己可以往程序存储器里写数据或修改程序。这种方式的典型应用就是用一小段代码来实现程序的下载,实际上单片机的ISP功能就是通过IAP技术来实现的,即片子在出厂前就已经有一段小的boot程序在里面,片子上电后,开始运行这段程序,当检测到上位机有下载要求时,便和上位机通信,然后下载数据到存储区。大家要注意千万不要尝试去擦除这段ISP引导程序,否则恐怕以后再也下载不了程序了。[/align]
STC单片机内部有几个专门的特殊功能寄存器负责管理ISP/IAP功能的,见表1。
[align=center]表1 ISP/IAP相关寄存器列表[/align]
[align=center]名称[/align] | [align=center]地址[/align] | [align=center]功能描述[/align] | [align=center]D7[/align] | [align=center]D6[/align] | [align=center]D5[/align] | [align=center]D4[/align] | [align=center]D3[/align] | [align=center]D2[/align] | [align=center]D1[/align] | [align=center]D0[/align] | [align=center]复位值[/align] |
[align=left]ISP_DATA[/align] | [align=center]E2h[/align] | [align=left]Flash数据寄存器[/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center]1111 1111[/align] |
[align=left]ISP_ADDRH[/align] | [align=center]E3h[/align] | [align=left]Flash高字节地址寄存器[/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center]0000 0000[/align] |
[align=left]ISP_ADDRL[/align] | [align=center]E4h[/align] | [align=left]Flash低字节地址寄存器[/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center]0000 0000[/align] |
[align=left]ISP_CMD[/align] | [align=center]E5h[/align] | [align=left]Flash命令模式寄存器[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]MS2[/align] | [align=center]MS1[/align] | [align=center]MS0[/align] | [align=center]xxxx x000[/align] |
[align=left]ISP_TRIG[/align] | [align=center]E6h[/align] | [align=left]Flash命令触发寄存器[/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center][/align] | [align=center]xxxx xxxx[/align] |
[align=left]ISP_CONTR[/align] | [align=center]E7h[/align] | [align=left]ISP/IAP 控制寄存器[/align] | [align=center]ISPEN[/align] | [align=center]SWBS[/align] | [align=center]SWRST[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]WT2[/align] | [align=center]WT1[/align] | [align=center]WT0[/align] | [align=center]000x x000[/align] |
ISP/IAP从Flash读出的数据放在此处,向Flash写入的数据也需放在此处。
ISP_ADDRH:ISP/IAP操作时的地址寄存器高八位。
ISP_ADDRL:ISP/IAP操作时的地址寄存器低八位。
ISP_CMD:ISP/IAP操作时的命令模式寄存器,须命令触发寄存器触发方可生效。命令模式如表2所示。
[align=center]表2 ISP_CMD寄存器模式设置[/align]
[align=center]D7[/align] | [align=center]D6[/align] | [align=center]D5[/align] | [align=center]D4[/align] | [align=center]D3[/align] | [align=center]D2[/align] | [align=center]D1[/align] | [align=center]D0[/align] | [align=center]模式选择[/align] |
[align=center]保留[/align] | [align=center]命令选择[/align] | [align=center][/align] | ||||||
[align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=left]待机模式,无ISP操作[/align] |
[align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]1[/align] | [align=left]对用户的应用程序flash区及数据flash区字节读[/align] |
[align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]0[/align] | [align=center]1[/align] | [align=center]0[/align] | [align=left]对用户的应用程序flash区及数据flash区字节编程[/align] |
[align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]--[/align] | [align=center]0[/align] | [align=center]1[/align] | [align=center]1[/align] | [align=left]对用户的应用程序flash区及数据flash区扇区擦除[/align] |
ISP_TRIG:ISP/IAP操作时的命令触发寄存器。
在ISPEN(ISP_CONTR.7) =1时,对ISP_TRIG 先写入46h,再写入B9h,ISP/IAP命令才会生效。
STC89C52RC,STC89LE52RC单片机内部可用Data Flash(EEPROM)的地址如表3所示,其它型号单片机请查阅相关资料。
[align=center]表3 STC89C52RC、STC89LE52RC单片机内部EEPROM地址表[/align]
[align=center]第一扇区[/align] | [align=center]第二扇区[/align] | [align=center]第三扇区[/align] | [align=center]第四扇区[/align] | ||||
[align=center]起始地址[/align] | [align=center]结束地址[/align] | [align=center]起始地址[/align] | [align=center]结束地址[/align] | [align=center]起始地址[/align] | [align=center]结束地址[/align] | [align=center]起始地址[/align] | [align=center]结束地址[/align] |
[align=center]2000H[/align] | [align=center]21FFH[/align] | [align=center]2200H[/align] | [align=center]23FFH[/align] | [align=center]2400H[/align] | [align=center]25FFH[/align] | [align=center]2600H[/align] | [align=center]27FFH[/align] |
[align=center]第五扇区[/align] | [align=center]第六扇区[/align] | [align=center]第七扇区[/align] | [align=center]第八扇区[/align] | ||||
[align=center]起始地址[/align] | [align=center]结束地址[/align] | [align=center]起始地址[/align] | [align=center]结束地址[/align] | [align=center]起始地址[/align] | [align=center]结束地址[/align] | [align=center]起始地址[/align] | [align=center]结束地址[/align] |
[align=center]2800H[/align] | [align=center]29FFH[/align] | [align=center]2A00H[/align] | [align=center]2BFFH[/align] | [align=center]2C00H[/align] | [align=center]2DFFH[/align] | [align=center]2E00H[/align] | [align=center]2FFFH[/align] |
注意:上面的是数据存储区的地址,程序存储区地址是从0~1FFF,共8K,程序区只能是ISP编程。
下面通过一个例子来讲解STC系列单片机EEPROM的具体用法。
【例】:在TX-1C实验板上实现如下描述,操作STC单片机自带的EEPROM,存储一组按秒递增的二位数据,并且将数据实时显示在数码管上,数据每变化一次就往EEPROM中写入一次,当关闭实验板电源,再次开启电源时,从EEPROM中读取先前存储的数据,接着递增显示。
新建文件part3.4.4.c,程序代码如下:
#include
#include //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
#define RdCommand 0x01 //定义ISP的操作命令
#define PrgCommand 0x02
#define EraseCommand 0x03
#define Error 1
#define Ok 0
#define WaitTime 0x01 //定义CPU的等待时间
sfr ISP_DATA=0xe2; //寄存器申明
sfr ISP_ADDRH=0xe3;
sfr ISP_ADDRL=0xe4;
sfr ISP_CMD=0xe5;
sfr ISP_TRIG=0xe6;
sfr ISP_CONTR=0xe7;
sbit dula=P2^6; //申明U1锁存器的锁存端
sbit wela=P2^7; //申明U2锁存器的锁存端
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uchar num;
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
void display(uchar shi,uchar ge) //显示子函数
{
dula=1;
P0=table[shi]; //送十位段选数据
dula=0;
P0=0xff; //送位选数据前关闭所有显示,防止打开位选锁存时
wela=1; //原来段选数据通过位选锁存器造成混乱
P0=0xfe; //送位选数据
wela=0;
delayms(5); //延时
dula=1;
P0=table[ge]; //送个位段选数据
dula=0;
P0=0xff;
wela=1;
P0=0xfd;
wela=0;
delayms(5);
}
/* ================ 打开 ISP,IAP 功能 ================= */
void ISP_IAP_enable(void)
{
EA = 0; /* 关中断 */
ISP_CONTR = ISP_CONTR & 0x18; /* 0001,1000 */
ISP_CONTR = ISP_CONTR | WaitTime; /* 写入硬件延时 */
ISP_CONTR = ISP_CONTR | 0x80; /* ISPEN=1 */
}
/* =============== 关闭 ISP,IAP 功能 ================== */
void ISP_IAP_disable(void)
{
ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
ISP_TRIG = 0x00;
EA = 1; /* 开中断 */
}
/* ================ 公用的触发代码 ==================== */
void ISPgoon(void)
{
ISP_IAP_enable(); /* 打开 ISP,IAP 功能 */
ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */
ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */
_nop_();
}
/* ==================== 字节读 ======================== */
unsigned char byte_read(unsigned int byte_addr)
{
ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址赋值 */
ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
ISP_CMD = ISP_CMD & 0xf8; /* 清除低3位 */
ISP_CMD = ISP_CMD | RdCommand; /* 写入读命令 */
ISPgoon(); /* 触发执行 */
ISP_IAP_disable(); /* 关闭ISP,IAP功能 */
return (ISP_DATA); /* 返回读到的数据 */
}
/* ================== 扇区擦除 ======================== */
void SectorErase(unsigned int sector_addr)
{
unsigned int iSectorAddr;
iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */
ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
ISP_ADDRL = 0x00;
ISP_CMD = ISP_CMD & 0xf8; /* 清空低3位 */
ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3 */
ISPgoon(); /* 触发执行 */
ISP_IAP_disable(); /* 关闭ISP,IAP功能 */
}
/* ==================== 字节写 ======================== */
void byte_write(unsigned int byte_addr, unsigned char original_data)
{
ISP_ADDRH = (unsigned char)(byte_addr >> 8); /* 取地址 */
ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */
ISP_CMD = ISP_CMD | PrgCommand; /* 写命令2 */
ISP_DATA = original_data; /* 写入数据准备 */
ISPgoon(); /* 触发执行 */
ISP_IAP_disable(); /* 关闭IAP功能 */
}
void main()
{
uchar a,b,num1;
TMOD=0x01; //设置定时器0为工作方式1(0000 0001)
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
num1=byte_read(0x2000);//程序开始时读取EEPROM中数据
if(num1>=60) //防止首次上电时读取出错
num1=0;
while(1)
{
if(num>=20)
{
num=0;
num1++;
SectorErase(0x2000);//擦除扇区
byte_write(0x2000,num1);//重新写入数据
if(num1==60)
{
num1=0;
}
a=num1/10;
b=num1%10;
}
display(a,b);
}
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
num++;
}
分析:程序中关健部分已经用注释加以说明,请读者编译程序下载后观察实际演示效果。
相关文章推荐
- 用TX-1C开发板学习单片机内部EEPROM的应用
- STC单片机内部EEPROM的应用
- AVR单片机内部EEPROM应用方法
- 51单片机内部EEPROM的应用
- 单片机内部扩展RAM的应用
- STM32L系列单片机内部EEPROM的读写
- stc15单片机内部EEPROM读写接口函数整理
- 十天学会单片机Day5 IIC总线AT2402芯片(EEPROM)应用
- STC系列单片机内部AD的应用
- STC89C52MCU --内部EEPROM的应用和内部扩展RAM的应用
- STC内部EEPROM的应用
- stm8单片机内部存储EEPROM字节读写实例解析
- 单片机学习札记之8 内部EEPROM的配置和使用
- STM32L系列单片机内部EEPROM的读写
- STM32单片机内部EEPROM的读写
- STC89C52单片机内部eeprom的应用
- mysql 数据库内部日期函数应用(转)
- 单片机中应用观察者模式
- 在企业内部门户如何构建社区应用?
- Operating System-进程/线程内部通信-信号量、PV操作的实现和应用(解决哲学家进餐和生产者消费者问题)