STC89C52单片机内部EEPROM保存数据的应用例子程序

合集下载

stc单片机eeprom读写程序

stc单片机eeprom读写程序

stc单片机eeprom读写程序以下是STC单片机使用EEPROM进行读写的示例程序:#include <reg52.h>#include <intrins.h>#define EEPROM_ADDR 0xA0 // EEPROM的I2C地址sbit SDA = P2^0; // I2C的数据线sbit SCL = P2^1; // I2C的时钟线// I2C开始信号void I2C_Start(){SDA = 1;_nop_(); // 延时一段时间SCL = 1;_nop_(); // 延时一段时间SDA = 0;_nop_(); // 延时一段时间SCL = 0;_nop_(); // 延时一段时间}// I2C停止信号void I2C_Stop(){SDA = 0;_nop_(); // 延时一段时间SCL = 1;_nop_(); // 延时一段时间SDA = 1;_nop_(); // 延时一段时间}// I2C发送一个字节的数据void I2C_SendByte(unsigned char dat){unsigned char i;for (i = 0; i < 8; i++){SDA = dat & 0x80; // 获取最高位dat <<= 1;_nop_(); // 延时一段时间SCL = 1;_nop_(); // 延时一段时间SCL = 0;_nop_(); // 延时一段时间}SDA = 1;_nop_(); // 延时一段时间SCL = 1;_nop_(); // 延时一段时间SCL = 0;_nop_(); // 延时一段时间}// I2C接收一个字节的数据unsigned char I2C_ReceiveByte(){unsigned char i, dat = 0;SDA = 1;for (i = 0; i < 8; i++){_nop_(); // 延时一段时间SCL = 1;_nop_(); // 延时一段时间dat <<= 1;dat |= SDA;SCL = 0;}return dat;}// 在EEPROM中写入一个字节的数据void EEPROM_WriteByte(unsigned char addr, unsigned char dat) {I2C_Start();I2C_SendByte(EEPROM_ADDR | 0); // 发送写入指令I2C_SendByte(addr); // 发送地址I2C_SendByte(dat); // 发送数据I2C_Stop();}// 从EEPROM中读取一个字节的数据unsigned char EEPROM_ReadByte(unsigned char addr){unsigned char dat;I2C_Start();I2C_SendByte(EEPROM_ADDR | 0); // 发送写入指令 I2C_SendByte(addr); // 发送地址I2C_Start();I2C_SendByte(EEPROM_ADDR | 1); // 发送读取指令 dat = I2C_ReceiveByte(); // 读取数据I2C_Stop();return dat;}。

STC系列单片机片内EEPROM的应用

STC系列单片机片内EEPROM的应用

(2)向STC12C5A60S2单片机片内EEPROM中某单元写入数据 (假设系统时钟频率为20MHz):
MOV IAP_DATA,#DATA;先将要写入旳数据送至IAP_DATA寄 存器
MOV IAP_ADDRH,#BYTE_ADDRH;送单元地址旳高8位 MOV IAP_ADDRL,#BYTE_ADDRL;送单元地址旳低8位 MOV IAP_CONTR,#10000010B;设置等待时间且允许对
MS1 MS0 • 操作任务旳选择
0
0
待机模式,不操作
0
1
对EEPROM进行读操作
1
0
对EEPROM进行写操作
1
1 对EEPROM进行擦除操作
2.控制寄存器IAP_CONTR
WT2 WT1 WT0 读(2个 时钟)
1 1 1 2个时钟
写(55us) 55个时钟
扇区擦除( 21ms) 21012个时钟
MOV IAP_ADDRH,DPH;送地址旳高8位
MOV IAP_TRIG,#5AH;开启写操作
MOV IAP_TRIG ,#0A5H
LCALL DELAY_55μs ;延时等待
RET
BYTE_READ:
;读
MOV IAP_CONTR,#82H
MOV IAP_CMD,#01H ;读EEPROM命令
• EEPROM分为若干个扇区,每个扇区旳大小为512B,数据 存储器旳擦除操作是按扇区进行旳,能够擦写旳次数在10 万次以上。
• 使用时,同一次修改旳数据应该存储于同一种扇区,不是 同一次修改旳数据最佳存储在不同旳扇区,不一定要存满 。内部EEPROM旳扇区地址如表10-1所示。
起始地址 结束地址 起始地址 结束地址

stc89c52中EEPROM使用方法

stc89c52中EEPROM使用方法

单片机STC‎89C52R‎C内部EEPR‎O M单片机运行时‎的数据都存在‎于RAM(随机存储器)中,在掉电后RA‎M中的数据是无‎法保留的,那么怎样使数据在掉‎电后不丢失呢‎?这就需要使用‎E EPROM‎或FLASH‎R OM 等存储器来实‎现。

在传统的单片‎机系统中,一般是在片外‎扩展存储器,单片机与存储‎器之间通过I‎I C 或SPI 等接口来进行‎数据通信。

这样不光会增‎加开发成本,同时在程序开‎发上也要花更‎多的心思。

在STC 单片机中内置‎了EEPRO‎M(其实是采用ISP/IAP 技术读写内部‎F LASH 来实现EEP‎R OM),这样就节省了‎片外资源,使用起来也更‎加方便。

下面就详细介绍S‎T C 单片机内置E‎E PROM 及其使用方法‎STC 各型号单片机‎内置的EEP‎R OM 的容量最小有‎2K,最大有16K‎,基本上很好地‎满足项目的需‎要,更方便之处就是‎节省了周边的‎E EPROM‎器件,达到节省成本‎的目的,而且内部EE‎P ROM 的速度比外部‎的EEPROM‎的速度快很多‎。

STC 各型号单片机‎内置的EEP‎R OM 是以512 字节为一个扇‎区,EEPROM‎的起始地址=FALSH 容量值+1,那么STC8‎9C52RC‎的起始地址为‎0x2000‎,第一扇区的起‎始地址和结束‎地址0x20‎00~0x21FF‎,第二扇区的起始地址和‎结束地址0x‎2200~0x23FF‎,其他扇区如此‎类推。

深入重点:�传统的EEP‎R OM 是电可擦可编‎程只读存储一‎种掉电后数据‎不丢失的存储‎芯片。

�STC89C‎52RC 的EEPRO‎M是通过ISP‎/IAP 技术读写内部‎F LASH 来实现EEP‎R OM。

�STC89C‎52RC 的EEPRO‎M起始地址为0‎x2000,以512 字节为一个扇‎区,EERPOM‎的大小为2K‎字节。

STC89C‎52RC 与EEPOR‎M实现的寄存器‎有6 个,分别是ISP‎_DATA、ISP_AD‎D RH、ISP_AD‎D RLISP_TR‎I G、ISP_CM‎D、ISP_CO‎N TR。

STC单片机EEPROM的应用和程序

STC单片机EEPROM的应用和程序

STC单片机EEPROM的应用和程序STC单片机EEPROM的应用和程序(2009-04-22 21:58:34)转载▼标签:杂谈分类:Program最近,由于工作的需要,用STC89C52来开发新产品,要用天STC的Eeprom的功能,上网也找了一点资料,得到很大帮助,真的非常感谢。

程序是我在网上摘录的,调试通过了,不过我产品在用动态扫描显示的,由于在Eeprom擦除时要用几十毫秒,会有一闪烁的。

不过这是正常的。

单片机运行时的数据都存在于RAM(随机存储器)中,在掉电后RAM 中的数据是无法保留的,那么怎样使数据在掉电后不丢失呢?这就需要使用EEPROM 或FLASHROM 等存储器来实现。

在传统的单片机系统中,一般是在片外扩展存储器,单片机与存储器之间通过IIC 或SPI 等接口来进行数据通信。

这样不光会增加开发成本,同时在程序开发上也要花更多的心思。

在STC 单片机中内置了EEPROM(其实是采用IAP 技术读写内部FLASH 来实现EEPROM),这样就节省了片外资源,使用起来也更加方便。

下面就详细介绍STC 单片机内置EEPROM 及其使用方法。

STC 各型号单片机内置的EEPROM 的容量各有不同,见下表:(内部EEPROM 可以擦写100000 次以上)上面提到了IAP,它的意思是"在应用编程",即在程序运行时程序存储器可由程序自身进行擦写。

正是是因为有了IAP,从而可以使单片机可以将数据写入到程序存储器中,使得数据如同烧入的程序一样,掉电不丢失。

当然写入数据的区域与程序存储区要分开来,以使程序不会遭到破坏。

要使用IAP 功能,与以下几个特殊功能寄存器相关:ISP_DATA:ISP/IAP 操作时的数据寄存器。

ISP/IAP 从Flash 读出的数据放在此处,向Flash 写的数据也需放在此处ISP_ADDRH:ISP/IAP 操作时的地址寄存器高八位。

ISP_ADDRL:ISP/IAP 操作时的地址寄存器低八位。

STC89C52单片机内部EEPROM保存数据的应用例子程序

STC89C52单片机内部EEPROM保存数据的应用例子程序

STC89C52单片机内部EEPROM保存数据的应用例子程序STC89C51、52内部都自带有2K字节的EEPROM,54、55和58都自带有16K字节的EEPROM,STC单片机是利用IAP技术实现的EEPROM,内部Flash擦写次数可达100,000 次以上,先来介绍下ISP与IAP的区别和特点。

知识点:ISP与IAP介绍ISP:In System Programable 是指在系统编程,通俗的讲,就是片子已经焊板子上,不用取下,就可以简单而方便地对其进行编程。

比如我们通过电脑给STC单片机下载程序,或给AT89S51单片机下载程序,这就是利用了ISP技术。

IAP:In Application Programable 是指在应用编程,就是片子提供一系列的机制(硬件/软件上的)当片子在运行程序的时候可以提供一种改变flash数据的方法。

通俗点讲,也就是说程序自己可以往程序存储器里写数据或修改程序。

这种方式的典型应用就是用一小段代码来实现程序的下载,实际上单片机的ISP功能就是通过IAP技术来实现的,即片子在出厂前就已经有一段小的boot程序在里面,片子上电后,开始运行这段程序,当检测到上位机有下载要求时,便和上位机通信,然后下载数据到存储区。

大家要注意千万不要尝试去擦除这段ISP引导程序,否则恐怕以后再也下载不了程序了。

STC单片机内部有几个专门的特殊功能寄存器负责管理ISP/IAP功能的,见表1。

每个扇区为512字节,建议大家在写程序时,将同一次修改的数据放在同一个扇区,方便修改,因为在执行擦除命令时,一次最少要擦除一个扇区的数据,每次在更新数据前都必须要擦除原数据方可重新写入新数据,不能直接在原来数据基础上更新内容。

下面通过一个例子来讲解STC系列单片机EEPROM的具体用法。

【例】:在TX-1C实验板上实现如下描述,操作STC单片机自带的EEPROM,存储一组按秒递增的二位数据,并且将数据实时显示在数码管上,数据每变化一次就往EEPROM中写入一次,当关闭实验板电源,再次开启电源时,从EEPROM中读取先前存储的数据,接着递增显示。

熟悉stc89c5152rc的EEPROM操

熟悉stc89c5152rc的EEPROM操
自己写的代码,按键部分有问题,请大家帮忙看一下
这个代码脱离按键部分时,EEPROM的操作是对的,就是在主程序中对EEPROM操作有效,按键部分好像不能控制EEPROM的读擦写。
表现为:按键确认部分是正确的,但是按键按下以后好像一直处于按下状态,不能走后面的程序了。
代码是用T0一秒定时代替按键的防抖。
自己想不出问题出在什么地方了,请大家帮忙给看一下啊。
复制内容到剪贴板代码:
//====================================================================
//目的:熟悉stc89c51/52rc的EEPROM操作
//
//版本日期:09-03-04
sfr ISP_ADDRL = 0xE4; //定义EEPROM地址寄存器的低8位
sfr ISP_CMD = 0xE5; //定义ISP的命令寄存器地址
sfr ISP_TRIG = 0xE6; //定义ISP命令触发寄存器地址
sfr ISP_CONTR = 0xE7; //定义ISP控制寄存器地址
{
uchar Addrh,Addrl;
ISP_CONTR = ENABLE_ISP;
ISP_CMD = ISP_BYTE_PROGRAM;
Addrh = Address >> 8;
Addrl = Address & 0x00ff;
ISP_ADDRH = Addrh;
void IspErase(uint Address)
{
uchar Addrh,Addrl;
ISP_CONTR = ENABLE_ISP;

stc89le52rc内部EEPROM的C51读写程序

stc89le52rc内部EEPROM的C51读写程序

stc89le52rc内部EEPROM的C51读写程序/*stc89le52rc内部EEPROM的C51读写程序串口命令(9600)1.0x35可以写eeprom第一个字节数据0x0c2.0x34可以使用检查eeprom第一个字节的数据,正确就会反馈一串字符3.0x33可以读取eeprom前256个字节数据*/#include<math.h>#include<stdio.h>#include<reg52.h>#include <intrins.h>#define NOP5 _nop_();_nop_();_nop_(); _nop_();_nop_();#define uchar unsigned char#define uint unsigned intsfr AUXR = 0x8e;sfr AUXR1 = 0xa2;sfr P4 = 0xe8;sfr XICON = 0xc0;sfr IPH = 0xb7;sfr WDT_CONTR = 0xe1;sfr ISP_DATA = 0xe2;sfr ISP_ADDRH = 0xe3;sfr ISP_ADDRL = 0xe4;sfr ISP_CMD = 0xe5;sfr ISP_TRIG = 0xe6;sfr ISP_CONTR = 0xe7;#define ENABLE_ISP 0x81 //小于20MHZ使用#define DATA_FLASH_START_ADDR 0x2000//stc89le52rc eeprom起始地址#define TEST_CODE 0x34uchar code start_string[]={"EEPROM first data correct!\n"};uint i=0,k;uchar EEPROM_READ(uint flash_addres);void IAP_disable();void EEPROM_FORMAT(uint flash_addres);void EEPROM_WRITE(uint flash_addres, isp_data);void test_read();void send_byte(uchar bt);void send_string(uchar *ptr, uchar len);void read_string(uint start_addr,uint num);void read_string(uint start_addr, uint num){static uint j,temp;for(j=0;j<num;j++){temp=EEPROM_READ(start_addr+j);NOP5;send_byte(temp);}}void send_string(uchar * ptr, uchar len){static uint j;for(j=0;j<len;j++){send_byte(*(ptr+j));}void send_byte(uchar by){SBUF=by;while(!TI);TI=0;}void IAP_disable(){ISP_CONTR=0;ISP_CMD=0;ISP_TRIG=0;}uchar EEPROM_READ(uint flash_addres) //读取数据{uchar read;ISP_ADDRH=flash_addres>>8;ISP_ADDRL=flash_addres;ISP_CONTR=ENABLE_ISP;ISP_CMD=0x01 ;EA=0;ISP_TRIG=0x46;ISP_TRIG=0xb9 ;NOP5;read=ISP_DATA;IAP_disable();EA=1;return(ISP_DATA);}void EEPROM_WRITE(uint flash_addres,isp_data) //写入数据ISP_ADDRH=flash_addres>>8;ISP_ADDRL=flash_addres;ISP_CONTR=ENABLE_ISP;ISP_CMD=0x02 ;EA=0;ISP_DATA=isp_data;ISP_TRIG=0x46;ISP_TRIG=0xb9;IAP_disable();EA=1;}void EEPROM_FORMAT(uint flash_addres) //擦除{ISP_ADDRH=flash_addres>>8;ISP_ADDRL=flash_addres;ISP_CONTR=ENABLE_ISP;ISP_CMD=0x03;EA=0;ISP_TRIG=0x46;ISP_TRIG=0xb9;IAP_disable();EA=1;}void test_read(){if(RI){RI=0;switch(SBUF)case 0x34:k=EEPROM_READ(DATA_FLASH_START_ADDR);NOP5;if(0x0c==k){send_string(start_string,sizeof(start_string));}send_byte(k);k=0;break;case 0x33:read_string(DATA_FLASH_START_ADDR, 256);break;case 0x35:EEPROM_FORMAT(DATA_FLASH_START_ADDR); //写已经有数据的扇区前要写擦除NOP5;NOP5;NOP5; //可以适当增减延时NOP5;NOP5;NOP5;NOP5;EEPROM_WRITE(DATA_FLASH_START_ADDR,TEST_CODE);//写一个0x0cbreak;default:if(0xff==i)i=0;}k=EEPROM_READ(DATA_FLASH_START_ADDR+(i++)); send_byte(DATA_FLASH_START_ADDR+i);send_byte(k);k=0;break;}}}void init(){TMOD=0x20;SCON=0x50;TL1=0xfd;TH1=0xfd;TR1=1;ET1=1;ES=1;}void main(){init();while(1){test_read();}}。

stc89c52中EEPROM使用方法

stc89c52中EEPROM使用方法

单片机STC89C52RC 内部EEPROM单片机运行时的数据都存在于RAM(随机存储器)中,在掉电后RAM 中的数据是无法保留的,那么怎样使数据在掉电后不丢失呢?这就需要使用EEPROM 或FLASHROM 等存储器来实现。

在传统的单片机系统中,一般是在片外扩展存储器,单片机与存储器之间通过IIC 或SPI 等接口来进行数据通信。

这样不光会增加开发成本,同时在程序开发上也要花更多的心思。

在STC 单片机中内置了EEPROM(其实是采用ISP/IAP 技术读写内部FLASH 来实现EEPROM),这样就节省了片外资源,使用起来也更加方便。

下面就详细介绍STC 单片机内置EEPROM 及其使用方法STC 各型号单片机内置的EEPROM 的容量最小有2K,最大有16K,基本上很好地满足项目的需要,更方便之处就是节省了周边的EEPROM 器件,达到节省成本的目的,而且内部EEPROM 的速度比外部的EEPROM 的速度快很多。

STC 各型号单片机内置的EEPROM 是以512 字节为一个扇区,EEPROM 的起始地址=FALSH 容量值+1,那么STC89C52RC 的起始地址为0x2000,第一扇区的起始地址和结束地址0x2000~0x21FF,第二扇区的起始地址和结束地址0x2200~0x23FF,其他扇区如此类推。

深入重点:�传统的EEPROM 是电可擦可编程只读存储一种掉电后数据不丢失的存储芯片。

�STC89C52RC 的EEPROM 是通过ISP/IAP 技术读写内部FLASH 来实现EEPROM。

�STC89C52RC 的EEPROM 起始地址为0x2000,以512 字节为一个扇区,EERPOM 的大小为2K 字节。

STC89C52RC 与EEPORM 实现的寄存器有6 个,分别是ISP_DATA、ISP_ADDRH、ISP_ADDRLISP_TRIG、ISP_CMD、ISP_CONTR。

STC89C52RC内部EEPROM应用

STC89C52RC内部EEPROM应用
函数:关闭ISP/IAP操作
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
voidclose_isp_iap()
{
ISP_CONTR = 0;//关闭IAP功能
ISP_CMD = 0;//待机模式,无ISP操作
ISP_TRIG = 0;//关闭IAP功能,清与ISP有关的特殊功能寄存器
STC89C52RC内部EEPROM应用
【源码】
/************************************
功能:STC89C52RC EEPROM保存关电前LED的亮灭状况
单片机:STC89C52RC
晶振:11.0592MHz
编译环境:Keil uVision4 V9.00
************************************/
LED1 = 1;
LED2 = 0;//亮第二个灯
}
while(1)
{
if(!K1)
{
while(!K1);
eraser(0x2000);//擦除第1个扇区(2000h~21FFh)
write(0x2002, 1);//对EEPROM区2002h写入1
LED1 = 0;
LED2 = 1;
}
if(!K2)
ISP_ADDRL =addr;
ISP_ADDRH =addr>> 8;
EA = 0;
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9;
_nop_();
dat = ISP_DATA;//取出数据
close_isp_iap();//关闭ISP/IAP
returndat;

stc89c52内部EEPROM连续写入并识别成功

stc89c52内部EEPROM连续写入并识别成功
for(y=110;y>0;y--);
}
void init() //初始化,每次操作EEPROM都要做
{
delay(200); //开始不知道为什么不能读取和写入,后来查书说初始化的时候加200ms延时就好。果然
EA=0;
ISP_CONTR=0X81;
}
void shengxiao()//程序生效。每次程序执行前都要运行
{
ISP_CMD=0X03;
ISP_ADDRL=addr;
ISP_ADDRH=addr>>8;
}
void write(uint addr,uchar dat)//把一个字节数据写入某地址
{
ISP_CMD=0X02;
ISP_ADDRL=addr;
ISP_ADDRH=addr>>8;
shengxiao();
quit();
}
void read(uint addr)//读取某地址的一个字节数据
{
ISP_CMD=0X01;
ISP_ADDRL=addr;
ISP_ADDRH=addr>>8;
shengxiao();
_nop_();
dat=ISP_DATA;
write(table1[t],table2[t]);
shengxiao();
quit();
}
while(1); */
init();
read(0x2003);
shengxiao();
quit();
}
ISP_DATA=dat; //没想到一直没办法写入会是这里的原因我原来为什么非得要ISP_DATA&dat呢?没道理呀!成功!原来第二次写入的时候里面的数变成第一次写入的数了,然后第二次写入的数与第一次写入的数相与,全为0.如第一次写入00000001第二次写入00000010,那么相与就成了00000000.这就是为什么会是全0的原因。

STC单片机内部EEPROM使用程序

STC单片机内部EEPROM使用程序

END
;定义Flash 操作等待时间及允许IAP/ISP/EEPROM操作的常数
;ENABLE_IAP EQU 80H ;系统工作时钟<30MHz时,对IAP_CONTR寄存器设置此值
ENABLE_IAP EQU 81H ;系统工作时钟<24MHz时,对IAP_CONTR寄存器设置此值
MOV IAP_ADDRL, DPL ;设置目标单元地址的低8位地址
CLR EA
MOV IAP_TRIG, #46H ;先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV IAP_TRIG, #0B9H ;送完A5h后,ISP/IAP命令立即被触发起动
NOP
MOV A, IAP_DATA ;读出的数据在IAP_DATA单元中,送入累加器A
ACALL IAP_Disable ;关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,
;一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
CLR EA
MOV IAP_TRIG, #46H ;先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV IAP_TRIG, #0B9H ;送完A5h后,ISP/IAP命令立即被触发起动
NOP
MOV IAP_TRIG, #0 ;清命令触发寄存器,使命令触发寄存器无触发,此句可不用
MOV IAP_ADDRH, #0FFH ;送地址高字节单元为00,指向非EEPROM区
MOV IAP_ADDRL, #0FFH ;送地址低字节单元为00,防止误操作
ACALL IAP_Disable ;关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,

stc系列单片机eeprom操作

stc系列单片机eeprom操作

stc系列单片机eeprom操作前言: stc单片机在中国大陆在中低端市场中占有大半壁江山.片内EEPROM是掉电保存数据的最理想选择.stc单片机的片内eeprom以扇区为单位,每个扇区大小是512 字节.以下是我亲自编写的对stc单片机(89系列除外)操作子函数,可以模块化使用,欢迎电子爱好者与我多多交流.本人QQ704157083 tel :186******** .工作地点:深圳..南山区. 从事软件和电子这行,爱好交朋友,一起开发有创意的产品.过目请留言!----------------------------------------------------------------------------------------------------------------------//增加寄存器sfr IAP_CONTR =0xC7; // ;软复位寄存器sfr IAP_DATA =0xC2 ; //数据寄存器;寄存器的地址不能改sfr IAP_adrRH =0xC3; // 地址高8位寄存器sfr IAP_adrRL = 0xC4; //命令触发器sfr IAP_CMD=0xC5; //;命令寄存器sfr IAP_TRIG=0xC6; //;命令触发器//************************************************************* **************** ****//增加通用函数.//(1) eeprom 函数写一个数据eg1: rom_writearea(1,100,0x99,12); 在片区1 地址100 中写入0x99 晶振12M// 读一个数据: eg2: rom_readarea(1,100,12); 在片区1 地址100 中读出数据晶振12M// 写一个数组:eg3: rom_write_array(1,100,a,10,12); 在片区1,起始地址100, 写入数组a ,数组大小10,晶振12Mxdata char xram[512] ; // 定义一个备份片区的数组.rom_readbyte(unsigned int adr,unsigned char fso);rom_readarea(unsigned int area,unsigned int adr_toread,unsigned char fso);void rom_writebyte(unsigned int adr,unsigned char dat,unsigned char fso);void rom_clear(unsigned int adr,unsigned char fso) ;void iap_disable();void rom_writearea(unsigned int area,unsigned int adr,unsigned char dat,unsigned char fso); // 写之前备份,扇区地址,字节地址,数据内容void rom_write_array(unsigned int area,unsigned int adr_towrite,unsigned char *p,unsigned int num,unsigned char fso);choose_area(unsigned char area); //选择片区//^^^^^^^^^^^^^^^^^^^^^^^^rom_readbyte(unsigned int adr,unsigned char fso){DPH=adr>>8; //取高字节DPL=adr; //取低字节if(fso==6){IAP_CONTR=0X84 ;}else if(fso==12){IAP_CONTR=0X8B; //;,<=12m晶振固定写法允许改变rom <=6M IAP_CONTR=0X84}IAP_CMD=0X01; //;01h为读取命令IAP_adrRH=DPH; //获取指针高八位IAP_adrRL=DPL; //获取指针低八位//EA=0;IAP_TRIG=0X5A; //两条触发命令,使命令执行IAP_TRIG=0XA5;// a=IAP_DATA; //;获取数据iap_disable();return(IAP_DATA);}//^^^^^^^^^^^^^^^^^^^^^^^^rom_readarea(unsigned int area,unsigned int adr_toread,unsigned char fso){unsigned int adr ; //扇区首地址adr=choose_area(area);IAP_DATA= rom_readbyte(adr+adr_toread,fso);//读取数据return(IAP_DATA);}//^^^^^^^^^^^^^^^^^^^^^^^^void rom_writebyte(unsigned int adr,unsigned char dat,unsigned char fso){DPH=adr>>8; //取高字节DPL=adr; //取低字节if(fso==6){IAP_CONTR=0X84 ;}else if(fso==12){IAP_CONTR=0X8B; //;,<=12m晶振固定写法允许改变rom <=6M IAP_CONTR=0X84}IAP_CMD=0X02; //;02h为写入命令IAP_adrRH=DPH; //获取指针高八位IAP_adrRL=DPL; //获取指针低八位IAP_DATA=dat; //把数据放入数据寄存器中,用于写//EA=0;IAP_TRIG=0X5A; //两条触发命令,使命令执行IAP_TRIG=0XA5;iap_disable();}//^^^^^^^^^^^^^^^^^^^^^^^^void rom_writearea(unsigned int area,unsigned int adr_towrite,unsigned char dat,unsigned char fso){unsigned int i,j ; //循环变量unsigned int adr ; //扇区首地址adr=choose_area(area);for (i=0;i<512;i++) //读扇区的所有数据,进行备份.{xram[i]=rom_readbyte(adr+i,fso);}rom_clear(area,fso); //清除要写入的扇区xram[adr_towrite]=dat ; //要写入的数据先放到数组中来for (j=0;j<512;j++) //将数组中的数据写入扇区中..{rom_writebyte(adr+j,xram[j],fso);}}//^^^^^^^^^^^^^^^^^^^^^^^^void rom_write_array(unsigned int area,unsigned int adr_towrite,unsigned char *p,unsigned int num,unsigned char fso){unsigned int i,j ; //循环变量unsigned int adr ; //扇区首地址adr=choose_area(area);for (i=0;i<512;i++) //读扇区的所有数据,进行备份.xram[i]=rom_readbyte(adr+i,fso);}rom_clear(area,fso); //清除要写入的扇区for(i=0;i<num;i++)< p="">{xram[adr_towrite+i]=*(p+i); //将数组的内容写入备份数组XRAM中}for (j=0;j<512;j++) //将数组中的数据写入扇区中..{rom_writebyte(adr+j,xram[j],fso);}}//^^^^^^^^^^^^^^^^^^^^^^^^void rom_clear(unsigned int area,unsigned char fso) //清除一片扇区{unsigned int adr ; //扇区首地址adr=choose_area(area);DPH=adr>>8; //取高字节DPL=adr; //取低字节if(fso==6){IAP_CONTR=0X84 ;}else if(fso==12){IAP_CONTR=0X8B; //;,<=12m晶振固定写法允许改变rom <=6M IAP_CONTR=0X84}IAP_CMD=0X03; //;03h为擦除命令IAP_adrRH=DPH; //获取指针高八位IAP_adrRL=DPL; //获取指针低八位//EA=0;IAP_TRIG=0X5A; //两条触发命令,使命令执行IAP_TRIG=0XA5;iap_disable();}//^^^^^^^^^^^^^^^^^^^^^^^^void iap_disable() // 关闭iap编程{IAP_CONTR=0X00; //关闭rom控制器命令IAP_CMD=0X00; //清除读写擦命令choose_area(unsigned char area){unsigned int adr;switch (area) //扇区编号从1开始到16扇区. {case 1: adr=0x0000;break;case 2: adr=0x0200;break;case 3: adr=0x0400;break;case 4: adr=0x0600;break;case 5: adr=0x0800;break;case 6: adr=0x0A00;break;case 7: adr=0x0C00;break;case 8: adr=0x0E00;break;case 9: adr=0x1000;break;case 10: adr=0x1200;break;case 11: adr=0x1400;break;case 12: adr=0x1600;break;case 13: adr=0x1800;break;case 14: adr=0x1A00;break;case 15: adr=0x1C00;break;case 16: adr=0x1E00;break;}return (adr);}//**********************************************************en d</num;i++)<>。

STC89_EEPROM程序

STC89_EEPROM程序

/**********************************************************************文件名: STC89_EEPROM.h**创建人: 动车组**日期: 2012-8-24**功能描述:对STC89的IAP/EEPROM进行操作即对EEPROM的字节读写和扇区的擦除**占用资源:使用STC9系列单片机的EEPROM********************************************************************/#ifndef __STC89_EEPROM_H__#define __STC89_EEPROM_H__#include "STC89.h"#define uchar unsigned char#define uint unsigned int#define First_Sector_AddH 0x20;//第一个扇区地址高字节/****************************************************************************** STC89系列EEPROM字节数(K) 扇区起始扇区的首地址结束扇区末尾地址51 4 8 2000H 2FFFH52 5 10 2000H 30FFH54 45 90 4000H F3FFH58 29 58 8000H F3FFH510 21 42 A000H F3FFH512 13 26 C000H F3FFH514 5 10 E000H F3FFH******************************************************************************/ #define ENABLE_IAP 0x81 //允许IAP读/写/擦除Data Flash/EEPROM//WT2/WT1/WT0=001 读:22个周期写:120个擦除:21885个时钟≤20MHz/*对STC89的EEPROM 的第Sector个扇区进行擦除*/voidIap_Erase_Sector(uchar Sector);/*在扇区Sector 写入number个uchar型数*p 最多可以写256个正常返回1*/bitWrite_Eeprom_More_Byte(ucharSector,ucharnumber,uchar *p);/*在扇区Sector d读出number个uchar型数据*p 最多可以读256个正常返回1*/ voidRead_Eeprom_More_Byte(ucharSector,ucharnumber,uchar tab[]);#endif/***************************************************//*************************************************头文件:STC89_EEPROM.h**文件名: STC89_EEPROM.c**创建人: 动车组**日期: 2012-8-24**功能描述:对STC89的IAP/EEPROM进行操作即对EEPROM的字节读写和扇区的擦除**占用资源:使用STC89系列单片机的EEPROM***********************************************/#include "STC89_EEPROM.h"/*----------------------------Disable ISP/IAP/EEPROM functionMake MCU in a safe state----------------------------*/voidIap_Idel(){ISP_CONTR = 0; //Close ISP functionISP_CMD = 0; //Clear command to standbyISP_TRIG = 0; //Clear trigger registerISP_ADDRH = 0xff; //Data ptr point to non-EEPROM areaISP_ADDRL = 0; //Clear ISP address to prevent misuse}/*对STC89的EEPROM 的第Sector个扇区进行擦除时间为21ms*/ voidIap_Erase_Sector(uchar Sector){ISP_CONTR = ENABLE_IAP;//开IAP功能设置等待时间ISP_CMD = ISP_ERASE; //对"Data Flash/EEPROM区"进行扇区擦除ISP_ADDRL = 0; //设置擦除第几个扇区低地址可以直接为0 ISP_ADDRH =(Sector<<1)-1+First_Sector_AddH;//高地址为扇区数*2-1 ISP_TRIG = ISP_TRIG0; //命令触发寄存器先写0x46ISP_TRIG = ISP_TRIG1; //再写0xB9 ISP/IAP 命令才会生效Iap_Idel(); //置为闲置状态避免误操作}///*用IAP对STC89的EEPROM 字节编程时间为55us*///void Iap_Program_Byte(uintaddr, uchardat)//{// ISP_CONTR = ENABLE_IAP;//开IAP功能设置等待时间// ISP_CMD = ISP_PROGRAM;//对"Data Flash/EEPROM区"进行字节编程// ISP_ADDRL = addr; //设置IAP EEPROM低地址// ISP_ADDRH = addr>> 8; //设置IAP EEPROM高地址// ISP_DATA = dat; //写EEPROM 数据// ISP_TRIG = ISP_TRIG0; //命令触发寄存器先写0x46// ISP_TRIG = ISP_TRIG1; //再写0xB9 ISP/IAP 命令才会生效// Iap_Idel(); //置为闲置状态避免误操作//}///*用IAP对STC89的EEPROM 字节读时间为两个时钟周期*///ucharIap_Read_Byte(uintaddr)//{// uchar temp=0;// ISP_CONTR = ENABLE_IAP;//开IAP功能设置等待时间// ISP_CMD = ISP_READ; //对"Data Flash/EEPROM区"进行字节读// ISP_ADDRL = addr; //设置IAP EEPROM低地址// ISP_ADDRH = addr>> 8; //设置IAP EEPROM高地址// ISP_TRIG = ISP_TRIG0; //命令触发寄存器先写0x46// ISP_TRIG = ISP_TRIG1; //再写0xB9 ISP/IAP 命令才会生效// temp = ISP_DATA; //读出EEPROM的数据// Iap_Idel(); //置为闲置状态避免误操作// return temp;//}/*检测EEPROM的操作是否有效有效返回1 无效返回0*/bitEeprom_Test(uchar Sector){bitval=0;Iap_Erase_Sector(Sector); //字节编程之前一定要进行扇区擦除否则EEpROM的数据全部变成0了ISP_CONTR = ENABLE_IAP; //开IAP功能设置等待时间ISP_ADDRH =(Sector<<1)-2+First_Sector_AddH; //设置IAP EEPROM高地址// ISP_ADDRL = 0; //设置低地址可以直接为0ISP_CMD = ISP_PROGRAM;//对"Data Flash/EEPROM区"进行字节编程ISP_DATA = 68; //写EEPROM 数据ISP_TRIG = ISP_TRIG0; //命令触发寄存器先写0x46ISP_TRIG = ISP_TRIG1; //再写0xB9 ISP/IAP 命令才会生效ISP_DATA = 1;ISP_CMD = ISP_READ; //对"Data Flash/EEPROM区"进行字节读ISP_TRIG = ISP_TRIG0; //命令触发寄存器先写0x46ISP_TRIG = ISP_TRIG1; //再写0xB9 ISP/IAP 命令才会生效if(ISP_DATA==68)val=1;Iap_Idel(); //置为闲置状态避免误操作returnval;}/*在扇区Sector 写入number个uchar型数据*p 最多可以写256个正常返回1*/ bitWrite_Eeprom_More_Byte(ucharSector,ucharnumber,uchar *p){uchar i=0;bitval=0;val=Eeprom_Test(Sector);if(val) //EEPROM的操作有效{Iap_Erase_Sector(Sector); //字节编程之前一定要进行扇区擦除否则EEpROM的数据全部变成0了ISP_CONTR = ENABLE_IAP; //开IAP功能设置等待时间ISP_CMD = ISP_PROGRAM; //对"Data Flash/EEPROM区"进行字节编程ISP_ADDRH =(Sector<<1)-2+First_Sector_AddH; //设置IAP EEPROM高地址for(i=0;i<number;){ISP_ADDRL = i++; //设置IAP EEPROM低地址ISP_DATA = *p++; //写EEPROM 数据ISP_TRIG = ISP_TRIG0; //命令触发寄存器先写0x46ISP_TRIG = ISP_TRIG1; //再写0xB9 ISP/IAP 命令才会生效}Iap_Idel(); //置为闲置状态避免误操作}returnval;}/*在扇区Sector 写入number个uchar型数据*p 最多可以写256个正常返回1*/ voidRead_Eeprom_More_Byte(ucharSector,ucharnumber,uchar *p){uchar i=0;ISP_CONTR = ENABLE_IAP; //开IAP功能设置等待时间ISP_CMD = ISP_READ; //对"Data Flash/EEPROM区"进行字节读ISP_ADDRH =(Sector<<1)-2+First_Sector_AddH; //设置IAP EEPROM高地址for(i=0;i<number;){ISP_ADDRL = i++; //设置IAP EEPROM低地址ISP_TRIG = ISP_TRIG0; //命令触发寄存器先写0x46ISP_TRIG = ISP_TRIG1; //再写0xB9 ISP/IAP 命令才会生效*p++ = ISP_DATA; //读出EEPROM的数据}Iap_Idel(); //置为闲置状态避免误操作}/*********************************************/#include <REG52.H>#include "STC89_EEPROM.h"#include"C_Ko.h"#define uchar unsigned char#define uint unsigned intvoid main(){uchar i;ucharxdata temp[20];UATR_Init(); //串口初始化for(i=0;i<20;i++) //数组赋值{temp[i]=2*i;}if((Write_Eeprom_More_Byte(10,20,temp))) //如果写入成功{Read_Eeprom_More_Byte(10,20,temp); //则读出刚才写入的数据for(i=0;i<20;i++) //通过串口发送到电脑{Uatr_Print_Long(temp[i]);Uatr_Prints("\t\n");}Iap_Erase_Sector(10); //全部擦除Read_Eeprom_More_Byte(10,20,temp); //再读数据{for(i=0;i<20;i++) //发到电脑看是否全1{Uatr_Print_Long(temp[i]);Uatr_Prints("\t\n");}}}elseUatr_Prints("编程错误!\n");while(1);}/**********************************STC89。

stc89c52单片机EEPROM地址读写数据库函数

stc89c52单片机EEPROM地址读写数据库函数
EA = 1; /*开中断*/
Read_isp_data=isp_data;
return(Read_isp_data);
}
/**************************************************************/
/*******************************************************************************/
isp_trig = 0;
isp_addrh = 0;
isp_addrl = 0;
EA = 1; /*开中断*/
}
/**************************************************************/
/***************STC89CXX_EEPROM字节读程序*************************/
STC89CXX_EEPROM_Char_Write(0x20,0x01,0x11);
STC89CXX_EEPROM_Char_Write(0x20,0x02,0x22);
STC89CXX_EEPROM_Char_Write(0x20,0x03,0x33);
STC89CXX_EEPROM_Char_Write(0x20,0x04,0x44);
void main (void)
{
unsigned char temp;
Delay1ms(10); //开机延时
STC89CXX_EEPROM_Erase(0x20); //擦除整个扇区
STC89CXX_EEPROM_Char_Write(0x20,0x00,0x00); //指定EEPROM地址写数据

STC89C52内部EEPROM读写驱动

STC89C52内部EEPROM读写驱动
ISP_TRIG = 0x00;
}
/*******************字节读***************************/
uchar Byte_read(uint byte_addr)
{
EA = 0; //关中断
Byte_program(0x2000, 0X88); //写EEPROM
_nop_();
_nop_();
_nop_();
_op_();
_nop_();
_nop_();
#define Read_COM 0X01 //字节读数据存储区
#define Prog_COM 0X02 //字节编程数据存储区
#define Dele_COM 0X03 //扇区擦除数据存储区
#define En_Wait_TIME 0X81 //设置等待时间 ,并使能ISP/IAP
P0=Byte_read(0x2000); //读EEPROM
while(1)
{
;
}
}
_nop_();
ISP_IAP_disable(); //关闭ISP/IAP功能
EA = 1; //开中断
return (ISP_DATA);
_nop_();
ISP_IAP_disable(); //关闭ISP/IAP功能
EA = 1;
}
void main()
{
Sector_erase(0x2000); //扇区擦除
}
/********************* 扇区擦除*********************/
void Sector_erase(uint sector_addr)
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
for(j=110;j>0;j--);
}
void display(uchar shi,uchar ge) //显示子函数
{
dula=1;
P0=table[shi]; //送十位段选数据
dula=0;
P0=0xff; //送位选数据前关闭所有显示,防止打开位选锁存时
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);
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x
uchar num;
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
}
/* ================ 打开 ISP,IAP 功能 ================= */
void ISP_IAP_enable(void)
{
EA = 0; /* 关中断 */
ISP_CONTR = ISP_CONTR & 0x18; /* 0001,1000 */
STC89C51、52内部都自带有2K字节的EEPROM,54、55和58都自带有16K字节的EEPROM,STC单片机是利用IAP技术实现的EEPROM,内部Flash擦写次数可达100,000 次以上,先来介绍下ISP与IAP的区别和特点。
知识点:ISP与IAP介绍
ISP:In System Programable 是指在系统编程,通俗的讲,就是片子已经焊板子上,不用取下,就可以简单而方便地对其进行编程。比如我们通过电脑给STC单片机下载程序,或给AT89S51单片机下载程序,这就是利用了ISP技术。
}
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
num++;
}
新建文件part3.4.4.c,程序代码如下:
#include <intrins.h>
#include <reg52.h> //52系列单片机头文件
#define uchar unsigned char
#define uint unsigned int
#define RdCommand 0x01 //定义ISP的操作命令
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[]={
STC单片机内部有几个专门的特殊功能寄存器负责管理ISP/IAP功能的,见表1。
每个扇区为512字节,建议大家在写程序时,将同一次修改的数据放在同一个扇区,方便修改,因为在执行擦除命令时,一次最少要擦除一个扇区的数据,每次在更新数据前都必须要擦除原数据方可重新写入新数据,不能直接在原来数据基础上更新内容。
#define PrgCommand 0x02
#define EraseCommand 0x03
#define Error 1
#define Ok 0
#define WaitTime 0x01 //定义CPU的等待时间
sfr ISP_DATA=0xe2; //寄存器申明
sfr ISP_ADDRH=0xe3;
ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */
ISP_CMD = ISP_CMD | PrgCommand; /* 写命令2 */
ISP_DATA = original_data; /* 写入数据准备 */
ISPgoon(); /* 触发执行 */
void ISPgoon(void)
{
ISP_IAP_enable(); /* 打开 ISP,IAP 功能 */
ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */
ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */
_nop_();
}
下面通过一个例子来讲解STC系列单片机EEPROM的具体用法。
【例】:在TX-1C实验板上实现如下描述,操作STC单片机自带的EEPROM,存储一组按秒递增的二位数据,并且将数据实时显示在数码管上,数据每变化一次就往EEPROM中写入一次,当关闭实验板电源,再次开启电源时,从EEPROM中读取先前存储的数据,接着递增显示。
ISP_IAP_disable(); /* 关闭ISP,IAP功能 */
return (ISP_DATA); /* 返回读到的数据 */
}
/* ================== 扇区擦除 ======================== */
void SectorErase(unsigned int sector_addr)
ISP_CONTR = ISP_CONTR | WaitTime; /* 写入硬件延时 */
ISP_CONTR = ISP_CONTR | 0x80; /* ISPEN=1 */
}
/* =============== 关闭 ISP,IAP 功能 ================== */
ISP_IAP_disable(); /* 关闭IAP功能 */
}
void main()
{
uchar a,b,num1;
TMOD=0x01; //设置定时器0为工作方式1(0000 0001)
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
IAP:In Application Programable 是指在应用编程,就是片子提供一系列的机制(硬件/软件上的)当片子在运行程序的时候可以提供一种改变flash数据的方法。通俗点讲,也就是说程序自己可以往程序存储器里写数据或修改程序。这种方式的典型应用就是用一小段代码来实现程序的下载,实际上单片机的ISP功能就是通过IAP技术来实现的,即片子在出厂前就已经有一段小的boot程序在里面,片子上电后,开始运行这段程序,当检测到上位机有下载要求时,便和上位机通信,然后下载数据到存储区。大家要注意千万不要尝试去擦除这段ISP引导程序,否则恐怕以后再也下载不了程序了。
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);
void ISP_IAP_disable(void)
{
ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
ISP_TRIG = 0x00;
EA = 1; /* 开中断 */
}
/* ================ 公用的触发代码 ==================== */
ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3 */
ISPgoon(); /* 触发执行 */
ISP_IAP_disable(); /* 关闭ISP,IAP功能 */
}
/* ==================== 字节写 ======================== */
EA=1;
ET0=1;
TR0=1;
num1=byte_read(0x2000);//程序开始时读取EEPROM中数据
if(num1>=60) //防止首次上电时读取出错
num1=0;
while(1)
{
if(num>=20)
{
num=0;
num1++;
ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
ISP_CMD = ISP_CMD & 0xf8; /* 清除低3位 */
ISP_CMD = ISP_CMD | RdCommand; /* 写入读命令 */
ISPgoon(); /* 触发执行 */
/* ==================== 字节读 ======================== */
unsigned char byte_read(unsigned int byte_addr)
{
ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址赋值 */
{
unsigned int iSectorAddr;
iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */
相关文档
最新文档