文档库 最新最全的文档下载
当前位置:文档库 › STC单片机EEPROM读写程序

STC单片机EEPROM读写程序

STC单片机EEPROM读写程序
STC单片机EEPROM读写程序

/* STC89C54RD+的flash空间从0x4000~0xf3ff 共90个扇区,每扇区512字节*/ // #define BaseAddr 0x1000 /* 51rc */

// #define EndSectoraddr 0x3d00 /* 51rc */

// #define EndAddr 0x3fff /* 51rc 12K eeprom */

#define BaseAddr 0x4000

#define EndSectoraddr 0xf200

#define EndAddr 0xf3ff

#define UseAddr 0x1000

/* ------------- 定义扇区大小------------- */

#define PerSector 512

/* 用户程序需要记忆的数组, 用户实际使用了n-1个数据,数组长度规整到

2 4 8 16 32 64 上*/

uchar Ttotal[16] =

{

0x55, /* 作为判别引导头使用,用户程序请不要修改它*/

/* 用户保存记忆的数据*/

0x01, /* 用途说明....*/

0x02,

0x03,

0x04,

0x05,

0x06,

0x07,

0x08,

0x09,

0x0a,

0x0b,

0x0c,

0x0d,

0x0e,

0x0f,

};

uint timerForDelay, /* 专供延时用的变量*/

i, /* 循环变量*/

EepromPtr; /* eeprom读写指针*/

/* --------------- 命令定义--------------- */

#define RdCommand 0x01 /* 字节读*/

#define PrgCommand 0x02 /* 字节写*/

#define EraseCommand 0x03 /* 扇区擦除*/

/* 定义常量*/

#define Error 1

#define Ok 0

/* 定义Flash对应于20MHz晶振系统的操作等待时间*/

/* 时钟倍频时WaitTime用0x00*/

#define WaitTime 0x01

/* ================ 打开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_();

}

/* ==================== 字节读======================== */ uchar byte_read(uint byte_addr){

ISP_ADDRH = (uchar)(byte_addr >> 8); /* 地址赋值*/

ISP_ADDRL = (uchar)(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(uint sector_addr){

uint iSectorAddr;

iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址*/

ISP_ADDRH = (uchar)(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(uint byte_addr, uchar original_data){

ISP_ADDRH = (uchar)(byte_addr >> 8); /* 取地址*/

ISP_ADDRL = (uchar)(byte_addr & 0x00ff);

ISP_CMD = ISP_CMD & 0xf8; /* 清低3位*/ ISP_CMD = ISP_CMD | PrgCommand; /* 写命令2 */

ISP_DATA = original_data; /* 写入数据准备*/

ISPgoon(); /* 触发执行*/

ISP_IAP_disable(); /* 关闭IAP功能*/

}

/* =================== 字节写并校验=================== */ uchar byte_write_verify(uint byte_addr, uchar original_data){

ISP_ADDRH = (uchar)(byte_addr >> 8); /* 取地址*/

ISP_ADDRL = (uchar)(byte_addr & 0xff);

ISP_CMD = ISP_CMD & 0xf8; /* 清低3位*/

ISP_CMD = ISP_CMD | PrgCommand; /* 写命令2 */

ISP_DATA = original_data;

ISPgoon(); /* 触发执行*/

/* 开始读,没有在此重复给地址,地址不会被自动改变*/

ISP_DATA = 0x00; /* 清数据传递寄存器*/

ISP_CMD = ISP_CMD & 0xf8; /* 清低3位*/

ISP_CMD = ISP_CMD | RdCommand; /* 读命令1 */

ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */ ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */

_nop_(); /* 延时*/

ISP_IAP_disable(); /* 关闭IAP功能*/

if(ISP_DATA == original_data){ /* 读写数据校验*/

return Ok; /* 返回校验结果*/ }

else{

return Error;

}

}

/* ===================== 数组写入===================== */ uchar ArrayWrite(uint begin_addr, uint len, uchar *array){

uint i;

uint in_addr;

/* 判是否是有效范围,此函数不允许跨扇区操作*/

if(len > PerSector){

return Error;

}

in_addr = begin_addr & 0x01ff; /* 扇区内偏移量*/

if((in_addr + len) > PerSector){

return Error;

}

in_addr = begin_addr;

/* 逐个写入并校对*/

ISP_IAP_enable(); /* 打开IAP功能*/

for(i = 0; i< len; i++){

/* 写一个字节*/

ISP_ADDRH = (uchar)(in_addr >> 8);

ISP_ADDRL = (uchar)(in_addr & 0x00ff);

ISP_DATA = array[i]; /* 取数据*/

ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */

ISP_CMD = ISP_CMD | PrgCommand; /* 写命令2 */

ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */

ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */

_nop_();

/* 读回来*/

ISP_DATA = 0x00;

ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */

ISP_CMD = ISP_CMD | RdCommand; /* 读命令1 */

ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */

ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */

_nop_();

/* 比较对错*/

if(ISP_DA TA != array[i]){

ISP_IAP_disable();

return Error;

}

in_addr++; /* 指向下一个字节*/ }

ISP_IAP_disable();

return Ok;

}

/* ========================= 扇区读出========================= */ /* 程序对地址没有作有效性判断,请调用方事先保证他在规定范围内*/

void ArrayRead(uint begin_addr, uchar len){

// uchar xdata data_buffer[]; /* 整个扇区读取缓存区*/ uint iSectorAddr;

uint i;

iSectorAddr = begin_addr; // & 0xfe00; /* 取扇区地址*/

ISP_IAP_enable();

for(i = 0; i < len; i++){

ISP_ADDRH = (uchar)(iSectorAddr >> 8);

ISP_ADDRL = (uchar)(iSectorAddr & 0x00ff);

ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */

ISP_CMD = ISP_CMD | RdCommand; /* 读命令1 */

ISP_DATA = 0;

ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */

ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */

_nop_();

Ttotal[i] = ISP_DA TA;

iSectorAddr++;

}

ISP_IAP_disable(); /* 关闭IAP功能*/

}

/* ============================================================== 从eeprom中读取数据

============================================================== */ void DataRestore()

{

EepromPtr = BaseAddr; /* 指向eeprom的起始点*/

while(EepromPtr < EndAddr) /* 在eeprom的可用区域内 */

{

if(byte_read(EepromPtr) == 0x55)/* 找到了上一次有效纪录*/

{

break; /* 寻找完成*/ }

EepromPtr += 0x10; /* 指向下一个小区*/ }

if(EepromPtr >= EndAddr) /* 如果照遍都没有,是新片*/

{

EepromPtr = BaseAddr; /* 指向eeprom的起始点*/

for(i=0;i<90;i++)

{

SectorErase(EepromPtr+0x200*i); /* 全部扇区擦除*/

}

while(ArrayWrite(EepromPtr, 0x10, Ttotal)) /* 写默认值*/

{ /* 写入失败才运行的部分*/

byte_write(EepromPtr, 0); /* 该单元已经失效*/

if(EepromPtr < EndAddr)

{

EepromPtr += 0x10; /* 换一块新的小区*/

}

else

{

P1=0; /* 指示芯片内eeprom全坏 */

EA= 0; /* 不再做任何事*/

while(1); /* 死机*/

}

}

}

ArrayRead(EepromPtr, 16);

}

/* ============================================================== 将需要记忆的数据保存到eeprom

============================================================== */ void DataSave()

{

uint wrPtr; /* 临时指针*/

NextArea:

byte_write_verify(EepromPtr, 0); /* 将原来的标记清除*/

wrPtr = EepromPtr & 0xfe00; /* 上一个扇区的起始地址*/

EepromPtr += 0x10; /* 目标存入地址*/

/* ------------------ 判断是否启用新的扇区---------------- */

if((EepromPtr & 0x1ff)==0)

{

SectorErase(wrPtr); /* 将上一个扇区擦除,备用*/

if(EepromPtr>=EndAddr) /* 已经用完了最后一个区域*/

{

EepromPtr = BaseAddr; /* 从头开始*/

}

}

/* -------------------- 数据存入前的准备------------------ */

/* 。。。。。。。。。。。。。。转移、处理*/

Ttotal[0] = 0x55; /* 重申启用标记*/

if(ArrayWrite(EepromPtr, 0x10, Ttotal))

{ /* 数据写入,如果有错换一块*/ goto NextArea;

}

}

单片机EEPROM的使用函数

/******************************************************************** 这是EEROM.h文件 ********************************************************************/ #ifndef _EEPROMus_h //对EEROM进行操作 #define _EEPROMus_h #include #include extern void EEw(unsigned int m,unsigned int,unsigned char w); //将第m扇区的第n个存储空间数据改成w extern void EEr(unsigned int m,unsigned int n,unsigned char *r); //将第m扇区的第n个存储空间数据读到r extern void EEe(unsigned int m); //删除第m扇区内的内容 extern void EEwa(unsigned int m,unsigned int n,unsigned char w[]); //在m扇区,从0x00写到第n个,写数组w里的数 extern void EEra(unsigned int m,unsigned int n,unsigned char r[]); //在m扇区,从0x00读到第n个,读到数组r里 #endif /******************************************************************** 这是EEPROM.c文件 ********************************************************************/ /******************************************************************** IAP_CONTR: B7: 0:禁止IAP 1:允许IAP B6和B5配合让程序从AP区和ISP监控区复位及程序的开始 B4:当IAP_TRIG触发的5a/a5失败,则为1,且由软件清零 B3:/ B2B1B0:设置CPU等待时间 IAP_TRIG: 每次发送命令后要用此寄存器发送5a,然后a5后,命令生效 IAP_CMD: 对IAP进行命令输入: 0x00:无操作 0x01:读 0x02:写

单片机内的Flash与EEPROM作用及区别(精)

单片机内的 Flash 与 EEPROM 作用及区别 单片机运行时的数据都存在于 RAM (随机存储器中, 在掉电后 RAM 中的数据是无 法保留的,那么怎样使数据在掉电后不丢失呢?这就需要使用 EEPROM 或FLASHROM 等 存储器来实现。在传统的单片机系统中, 一般是在片外扩展存储器, 单片机与存储器之间通 过 IIC 或 SPI 等接口来进行数据通信。这样不光会增加开发成本,同时在程序开发上也要花 更多的心思。在 STC 单片机中内置了 EEPROM (其实是采用 IAP 技术读写内部 FLASH 来 实现 EEPROM ,这样就节省了片外资源,使用起来也更加方便。下面就详细介绍 STC 单 片机内置 EEPROM 及其使用方法。 flash 是用来放程序的,可以称之为程序存储器,可以擦出写入但是基本都是整个扇区进行的 . 一般来说单片机里的 flash 都用于存放运行代码,在运行过程中不能改; EEPROM 是用来保存用户数据,运行过程中可以改变,比如一个时钟的闹铃时 间初始化设定为 12:00,后来在运行中改为 6:00,这是保存在 EEPROM 里, 不怕掉电,就算重新上电也不需要重新调整到 6:00 下面是网上详细的说法,感觉不错:

FLASH 和 EEPROM 的最大区别是 FLASH 按扇区操作, EEPROM 则按字节操作, 二者寻址方法不同,存储单元的结构也不同, FLASH 的电路结构较简单,同样容量占芯片面积较小,成本自然比 EEPROM 低,因而适合用作程序存储器, EEPROM 则更多的用作非易失的数据存储器。当然用 FLASH 做数据存储器也行, 但操作比EEPROM 麻烦的多,所以更“人性化”的 MCU 设计会集成 FLASH 和 EEPROM 两种非易失性存储器,而廉价型设计往往只有 FLASH ,早期可电擦写型 MCU 则都是EEPRM 结构,现在已基本上停产了。 在芯片的内电路中, FLASH 和 EEPROM 不仅电路不同,地址空间也不同,操作方法和指令自然也不同, 不论冯诺伊曼结构还是哈佛结构都是这样。技术上, 程序存储器和非易失数据存储器都可以只用 FALSH 结构或 EEPROM 结构, 甚至可以用“变通”的技术手段在程序存储区模拟“数据存储区” ,但就算如此,概念上二者依然不同,这是基本常识问题。 EEPROM :电可擦除可编程只读存储器, Flash 的操作特性完全符合 EEPROM 的定义,属 EEPROM 无疑,首款 Flash 推出时其数据手册上也清楚的标明是EEPROM ,现在的多数 Flash 手册上也是这么标明的,二者的关系是“白马”和 “马” 。至于为什么业界要区分二者, 主要的原因是 Flash EEPROM 的操作方法和传统 EEPROM 截然不同,次要的原因是为了语言的简练,非正式文件和口语中Flash EEPROM 就简称为 Flash , 这里要强调的是白马的“白” 属性而非其“马” 属性以区别 Flash 和传统 EEPROM 。 Flash 的特点是结构简单, 同样工艺和同样晶元面积下可以得到更高容量且大数据量 下的操作速度更快,但缺点是操作过程麻烦,特别是在小数据量反复重写时, 所以在 MCU 中 Flash 结构适于不需频繁改写的程序存储器。 很多应用中,需要频繁的改写某些小量数据且需掉电非易失,传统结构的EEPROM 在此非常适合, 所以很多 MCU 内部设计了两种 EEPROM 结构, FLASH

Eeprom的读写

所看过的对24系列I2C读写时序描述最准确最容易理解的资料,尤其是关于主从器件的应答描述和页写描述,看完后明白了很多。关于页写的描述,网络上绝大部分范程都没提到页写时的数据地址必须是每页的首地址才能准确写入,而且如果写入超过一页的数据会循环覆盖当前页的数据。 关于IIC总线 I2C总线:i2c总线是Philips 公司首先推出的一种两线制串行传输总线。它由一根数据线(SDA)和一根时钟线(SDL)组成。i2c总线的数据传输过程如图3所示,基本过程为: 1、主机发出开始信号。 2、主机接着送出1字节的从机地址信息,其中最低位为读写控制码(1为读、0为写),高7位为从机器件地址代码。 3、从机发出认可信号。 4、主机开始发送信息,每发完一字节后,从机发出认可信号给主机。 5、主机发出停止信号。 I2C总线上各信号的具体说明: 开始信号:在时钟线(SCL)为高电平其间,数据线(SDA)由高变低,将产生一个开始信号。 停止信号:在时钟线(SCL)为高电平其间,数据线(SDA)由低变高,将产生一个停止信号。 应答信号:既认可信号,主机写从机时每写完一字节,如果正确从机将在下一个时钟周期将数据线(SDA)拉低,以告诉主机操作有效。在主机读从机时正确读完一字节后,主机在下一个时钟周期同样也要将数据线(SDA)拉低,发出认可信号,告诉从机所发数据已经收妥。(注:读从机时主机在最后1字节数据接收完以后不发应答,直接发停止信号)。 注意:在I2C通信过程中,所有的数据改变都必须在时钟线SCL为低电平时改变,在时钟线SCL为高电平时必须保持数据SDA信号的稳定,任何在时钟线为高电平时数据线上的电平改变都被认为是起始或停止信号。 作为一种非易失性存储器(NVM),24系列EEPROM使用的很普遍,一般作为数据量不太大的数据存储器。下面总结一下其应用的一些要点。从命名上看,24CXX中XX的单位是kbit,如24C08,其存储容量为8k bit,即1k Byte=1024 Byte。 一、工作条件 1.工作电压(VCC) 24CXX:4.5V-5.5V 24CXX-W:2.5V-5.5V 24CXX-R:1.8V-5.5V 2.输入电平定义(VIH,VIL) VIH:0.7VCC-VCC+1 VIL:-0.45V-0.3VCC 二、硬件连接 1.上拉电阻RP的取值 由于I2C总线电容要满足小于400pf的条件。从以下波形可以看出,上拉电阻越大,总线的电容越小,可以实现的数据传输率就越大,可达400khz。 [点击图片可在新窗口打开] 2.写保护脚 芯片写保护脚是高电平有效,即WP接高电平时禁止写入

STC单片机EEPROM读写程序

/* STC89C54RD+的flash空间从0x4000~0xf3ff 共90个扇区,每扇区512字节*/ // #define BaseAddr 0x1000 /* 51rc */ // #define EndSectoraddr 0x3d00 /* 51rc */ // #define EndAddr 0x3fff /* 51rc 12K eeprom */ #define BaseAddr 0x4000 #define EndSectoraddr 0xf200 #define EndAddr 0xf3ff #define UseAddr 0x1000 /* ------------- 定义扇区大小------------- */ #define PerSector 512 /* 用户程序需要记忆的数组, 用户实际使用了n-1个数据,数组长度规整到 2 4 8 16 32 64 上*/ uchar Ttotal[16] = { 0x55, /* 作为判别引导头使用,用户程序请不要修改它*/ /* 用户保存记忆的数据*/ 0x01, /* 用途说明....*/ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, }; uint timerForDelay, /* 专供延时用的变量*/ i, /* 循环变量*/ EepromPtr; /* eeprom读写指针*/ /* --------------- 命令定义--------------- */ #define RdCommand 0x01 /* 字节读*/ #define PrgCommand 0x02 /* 字节写*/

51单片机内部EEPROM的应用

用51hei-5板子学习单片机内部EEPROM的应用 STC89C51、52内部都自带有2K字节的EEPROM,54、55和58都自带有16K字节的EEPRO M,STC单片机是利用IAP技术实现的EEPROM,内部Flash擦写次数可达100,000 次以上,先来介绍下ISP与IAP的区别和特点。 ISP:In System Programable 是指在系统编程,通俗的讲,就是片子已经焊板子上,不用取下,就可以简单而方便地对其进行编程。比如我们通过电脑给STC单片机下载程序,或给AT89S51单片机下载程序,这就是利用了ISP技术。 IAP:In Application Programable 是指在应用编程,就是片子提供一系列的机制(硬件/软件上的)当片子在运行程序的时候可以提供一种改变flash数据的方法。通俗点讲,也就是说程序自己可以往程序存储器里写数据或修改程序。这种方式的典型应用就是用一小段代码来实现程序的下载,实际上单片机的ISP功能就是通过IAP技术来实现的,即片子在出厂前就已经有一段小的boot程序在里面,片子上电后,开始运行这段程序,当检测到上位机有下载要求时,便和上位机通信,然后下载数据到存储区。大家要注意千万不要尝试去擦除这段ISP引导程序,否则恐怕以后再也下载不了程序了。STC单片机内部有几个专门的特殊功能寄存器负责管理ISP/IAP 功能的,见表1。 表1 ISP/IAP相关寄存器列表 名称地址功能描述D7D6D5D4D3D2D1D0复位值ISP_DATA E2h Flash数据寄存器1111 1111 ISP_ADDRH E3h Flash高字节地址寄 存器0000 0000 ISP_ADDRL E4h Flash低字节地址寄 存器0000 0000 ISP_CMD E5h Flash命令模式寄存 器 ----------MS2MS1MS0xxxx x000 ISP_TRIG E6h Flash命令触发寄存 器 xxxx xxxx ISP_CONTR E7h ISP/IAP 控制寄存器ISPEN SWBS SWRST----WT2WT1WT0000x x000 ISP_DATA:ISP/IAP操作时的数据寄存器。

IIC总线的使用EEPROM芯片的读写程序

51单片机第二十二课IIC总线的使用EEPROM芯片的读写 所属类别:课程代码发布日期:2011-03-05 点击量:341 #include #include #define uchar unsigned char #define uint unsigned int sbit sda=P2^1; sbit scl=P2^0; unsigned char code smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e, 0x79,0x71,0x00}; unsigned char code smg_we[]={0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78}; void start(void); void stop(void); void ack(void); void noack(void); void iicwr_byte(uchar dat); uchar iicre_byte(void); void delay (void); void init(void); void delay1(void); void write_byte(uchar add,uchar dat); uchar read_byte(uchar add); /////////////////////////////////// void delay1(void) { uint a=30000; while(a--); } void delay (void) { _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); }

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 操作时的地址寄存器低八位。 ISP_CMD:ISP/IAP 操作时的命令模式寄存器,须命令触发寄存器触发方可生效。 ISP_TRIG:ISP/IAP 操作时的命令触发寄存器。 当ISPEN(ISP_CONTR.7)=1 时,对ISP_TRIG 先写入0x46,再写入0xb9,ISP/IAP 命令才会生效。 单片机芯片型号起始地址内置EEPROM 容量(每扇区512 字节) STC89C51RC,STC89LE51RC 0x2000 共八个扇区 STC89C52RC,STC89LE52RC 0x2000 共八个扇区 STC89C54RD+,STC89LE54RD+ 0x8000 共五十八个扇区 STC89C55RD+,STC89LE55RD+ 0x8000 共五十八个扇区 STC89C58RD+,STC89LE58RD+ 0x8000 共五十八个扇区 寄存器标识地址名称7 6 5 4 3 2 1 0 初始值 ISP_DATA 0xE2 ISP/IAP闪存数据寄存器11111111 ISP_ADDRH 0xE3 ISP/IAP 闪存地址高位00000000

52单片机内部EEPROM

#include #include #define uchar unsigned char #define uint unsigned int sbit en=P2^7; sbit rs=P2^6; sbit rw=P2^5; void delay(unsigned char z) { unsigned char j,i; for (i=0;i> 8); //送地址高字节

51内部eeprom读写,实现掉电存储

主函数: #include #include"EEPROM.h" #include"smg.h" void main() { num=byte_read(DEBUG_Data_Memory_Begin_Sector_addr);//字节读(程序开始时读取EEPROM中数据) if(num>=60)num=0;//防止首次上电时读取出错?? while(1) { if(num<60) { display(num); num++;delay(5); delay1(DELAY_CONST); sector_erase(DEBUG_Data_Memory_Begin_Sector_addr);//擦出扇区 byte_program (DEBUG_Data_Memory_Begin_Sector_addr,num);//字节编程} if(num==60)num=0; } } EEPROM.h: /*STC89C51RC,STC89LE51RC 0x2000 共八个扇区 STC89C52RC,STC89LE52RC 0x2000 共八个扇区 STC89C54RD+,STC89LE54RD+ 0x8000 共五十八个扇区 STC89C55RD+,STC89LE55RD+ 0x8000 共五十八个扇区 STC89C58RD+,STC89LE58RD+ 0x8000 共五十八个扇区*/ #include #include //sfr定义特殊功能寄存器 sfr ISP_DA TA =0xe2;//ISP/IAP 操作时的数据寄存器,从Flash 读出的数据放在此处,向Flash 写的数据也需放在此处 sfr ISP_ADDRH =0xe3;//ISP/IAP 操作时的地址寄存器高八位 sfr ISP_ADDRL =0xe4;//ISP/IAP 操作时的地址寄存器低八位 sfr ISP_CMD =0xe5;//ISP/IAP 操作时的命令模式寄存器,须命令触发寄存器触发方可生效 sfr ISP_TRIG =0xe6;//ISP/IAP 操作时的命令触发寄存器 sfr ISP_CONTR =0xe7;//ISP/IAP 控制寄存器 /* 定义命令*/

AT24C02EEPROM读写程序

;--------------------------------------------------------------------------------------------------------------------- ;本程序是针对AT89S52单片机编制的EEPROM读写程序(2013.8.4测试通过) ;本程序在4MHZ、12MHZ和24MHZ分别测试通过 ;AT24C02的A0、A1、A2均接GND,设备地址高7位为(1010)000;WP接GND,充许对EEPROM正常读写 ;本程序仅作学习交流之用。 ;--------------------------------------------------------------------------------------------------------------------- SCl equ P2.0 ;SCL接A T89S52的P2.0端口,作为EEPROM的串行输入时钟 SDA equ P2.1 ;SDA接AT89S52的P2.1端口,作为主机与EEPROM之间信息串行传输总线WRITEDATA equ 08H;拟写入EEPROM的数据在主机中的存贮单元地址 READDATA equ 09H ;从EEPROM读取的数据存放到主机存贮单元地址EPROMADDRESS equ 0AH;拟随机读写EEPROM的存贮单元地址 ;------------------------------------------------ ORG 00H LJMP MAIN ;------------------------------------------------ ORG 50H MAIN: MOV SP,#20H;防止堆栈影响已用内存数据 ;以下为写EEPROM过程 mov EPROMADDRESS,#09H;该地址可以随意输入(00H~FFH),但读和写的地址须相同 MOV WRITEDA TA,#01010010B;该数字可以随意输入,并将读和写的数据进行比较;如读数正确则按将读出数据在P1口输出,可在P1口各位分别接LED灯直观显示出来。 LCALL WRITEEEPROMR ;以下为读EEPROM过程 mov EPROMADDRESS,#09H;该地址可以随意输入(00H~FFH),但读和写的地址须相同 LCALL READEEPROMR ;以下为EEPROM读写操作验证 MOV A,WRITEdata MOV B,A MOV A,READDATA CJNE A,B,MAIN1 MOV P1,READDATA;写入数和读出数相等时,读出的数据在P1口输出并按位分别控制LED灯直观显示 sJMP $ MAIN1: MOV P1,#00H;写入数和读出数相等时,LED灯全亮 ;以下可接其它主程序,此处暂为死循环 SJMP $ ;--------------------------------------------------------------------------------------------------------------------- ;WRITEEEPROMR是随机写EEPROM(AT24C02)子程序 ;入口1:EEPROMADRESS(拟读写EEPROM存贮单元地址,00~FFH) ;入口2:WRITEDATA(拟写入EEPROM的字节数据在主机的存放地址)

IC读写EEPROM问题总结

I C读写E E P R O M问题 总结 文件管理序列号:[K8UY-K9IO69-O6M243-OL889-F88688]

2017年6月30日星期五 目的:利用TMS320F2801芯片上外设I2C(2线串口)读写EEPROM数据(24LC128) 关键点1:24LC时钟频率400KHz,寄存器设置如下: I2caRegs.I2CPSC.all = 9; // Prescaler - need 7-12 Mhz on module clk I2caRegs.I2CCLKL = 10; // NOTE: must be non zero I2caRegs.I2CCLKH = 5; // NOTE: must be non zero 时钟频率也可设为200KHz,三个参数分别为9、20、20(CPU时钟频率为100MHz)(未测试?) 关键点2:波形分析 问题:I2C模块是不是只有I2CCNT 减到0才会发出停止信号 I2C模块是硬件的,当检测到发送完了就会发结束自动发信号,不需要人为干预 问题1:字节写操作正常,但是字节读函数出错 原因:写EEPROM是在七位器件地址后添加写标志,而读EEPROM需要在七位器件地址后添加写标志。 关键点:读EEPROM数据需要发送两次命令。第一次为写地址(此地址会被赋值给EEPROM内的地址指针),因此需要添加写标志;第二次为读数据,将写标志改为读标志。

问题2:主机接收时,SDA数据线上有数据传输,且I2CDRR接收数据寄存器有数据更新,但寄存器显示不可读,即CPU认为一直没接收到数据,一直停在下面语句 while 关键点:初始化设置时采用的是FIFO接收方式,因此无效,应查询FIFO 接收中断位while方式查询位。 此位只有在非FIFO中断接收方式时才有效。 问题3:断续单字节读写正常,但是采用连续的单字节读写出错。 原因:EEPROM写过程的结束并不是I2C总线写结束就结束,实际上I2C 总线的写入数据先被保存到了EEPROM内部的缓冲区,当遇到I2C结束条件后,EEPROM才启动内部写过程,这个过程才是保存数据的过程。非常悲哀的是这个过程比较长,官方文档标注为5ms。如果在这5ms以内对EEPROM芯片访问将被忽略。 关键点:读写EEPROM应延时至少5ms,软件延时10ms do{}while(EEPROM_Timer <= 10); //10ms 问题4:查询EEPROM写过程是否结束造成死机,只能查询EEPROM读过程。 官方文档说EEPROM内部写周期最长为5ms,在很多情况下是远远低于 5ms的,为了节约时间,官方给出一个解决办法。当写周期完毕后就开始进行应答查询,来确定EEPROM写周期何时结束。所谓应答查询官方解释为:就是向EEPROM发送一个I2C起始条件后发送器件地址和一个读写标

PIC单片机的EEPROM读写实例及说明

PIC单片机的EEPROM读写实例及说明 ; PIC 单片机的EEPROM 读写实例及说明; ******************************************************************** ********; This is a program to test the function of readingwritting for EEPROM.; You can observe the value of register(30H--?) buy changing “VALU” and “WRC_”.; Notice that:it must be { ADDR+WRC_=0ffh } !;******************************************************************* *********include “p16f877.inc”ADDR EQU 20H ;写入地址寄存器VALU EQU 21H ;写入值REC_ EQU 22H ;读计数WRC_ EQU 24H ;写计数org 0goto mainmainbcf STATUS,RP1bcf STATUS,RP0 ;bank0movlw 10hmovwf ADDR ;写入EEPROM 初始值movlw 90hmovwf VALU ;初始写入值movlw 30hmovwf FSR ;间址,读出值初始存放地址movlw 0Fhmovwf WRC_ ;写入次数movwf REC_;incf REC_ ;读出次数wri_ ;写子程序bsf STATUS,RP1bsf STATUS,RP0 ;bank3btfsc EECON1,WRgoto $-1bcf STATUS,RP0bcf STATUS,RP1 ;bank0movf ADDR,Wbsf STATUS,RP1 ;bank2movwf EEADRbcf STATUS,RP1 ;bank0movf VALU,Wbsf STATUS,RP1 ;bank2movwf EEDATAbsf STATUS,RP0 ;bank3bcf EECON1,EEPGD ;to data memorybsf EECON1,WRENbcf INTCON,GIEmovlw 55hmovwf EECON2movlw 0aahmovwf EECON2bsf EECON1,WRbcf STATUS,RP0bcf STATUS,RP1 ;bank0incf ADDR,1decf VALU,1decfsz WRC_ ;all write,to read_goto wri_read_ ;读子程序bcf STATUS,RP1bcf STATUS,RP0 ;bank0decf ADDR ;next valuebsf STATUS,RP1 ;bank2movwf EEADRbsf STATUS,RP0 ;bank3EEwr.asm 程序说明:1、本程序是对PIC16F877 单片机的EEPROM 数据区进行读写的演示程序;

IIC读写EEPROM

u32 ulTimeOut_Time; /* ******************************************************************************* ************************** * I2C_EE_WriteStr() * * Description : 将一个数据块写入EEPROM 的指定的地址 * * Argument(s) : xChip - 从器件地址 * xAddr - EEPROM存储空间地址 * xpBuf - 数据缓冲区指针 * xLen - 数据长度 * * Return(s) : none. * * Caller(s) : Application. * * Note(s) : (1) *------------------------------------------------------------------------------------------------------- * Modified by : * Modified date : * Description : *------------------------------------------------------------------------------------------------------- ******************************************************************************* ************************** */ void I2C_EE_WriteStr(u8 xChip, u16 xAddr, u8 *xpBuf, u16 xLen) { u8 *pbuf; u8 err; u8 retry; u16 addr; u16 len; // pbuf = xpBuf; addr = xAddr; len = xLen; I2C_EE_Drv_BusEn(); // 允许总线,写允许

PIC单片机片内EEPROM的读写程序

PIC单片机片内EEPROM的读写程序 因为也是摸索着学习PIC单片机,当要用到EEPROM存储部分系统参数,看单片机手册上的资料,觉得还是比较麻烦,然后还是不太会,然后就想找找看网上有没有现成的PIC单片机的片内EEPROM的读写程序,然后都没有找到想要的,而且对汇编语言的也不知道,所以搜索了下最后终于发现PICC编译器里面其实对内部的EEPROM的读写有头文件,可以直接来用,方法如下: PICC的安装目录下C:\Program Files\HI-TECH Software\PICC\9.81\include(这是我的电脑里目录)里面有一个eeprom_routines.h的文件这个就是关于EEPROM 中的读写程序,具体程序如下: // This header file should not be included directly // Inclusion of this file is provided indirectly by including htc.h /******************************************************************** ***/ /****** EEPROM memory read/write macros and function definitions *******/ /******************************************************************** ***/ /* NOTE WELL: The macro EEPROM_READ() is NOT safe to use immediately after any write to EEPROM, as it does NOT wait for WR to clear. This is by design, to allow minimal code size if a sequence of reads is desired. To guarantee uncorrupted writes, use the function eeprom_read() or insert while(WR)continue; before calling EEPROM_READ(). */ #if EEPROM_SIZE > 0 #ifdef __FLASHTYPE // macro versions of EEPROM write and read #define EEPROM_WRITE(addr, value) \ do{ \ while(WR)continue;EEADRL=(addr);EEDATA=(value); \ EECON1&=0x3F;CARRY=0;if(GIE)CARRY=1;GIE=0; \ WREN=1;EECON2=0x55;EECON2=0xAA;WR=1;WREN=0; \ if(CARRY)GIE=1; \ }while(0) #define EEPROM_READ(addr) ((EEADRL=(addr)),(EECON1&=0x3F),(RD=1),EEDATA)

Stc单片机eeprom使用心得

Stc单片机eeprom使用心得 STC单片机利用IAP技术实现了EEPROM功能,相比外置存储芯片而言,在操作上比较方便。涉及STC单片机EEPROM操作的特殊功能寄存器有6个,地址分别是E2H、E3H、E4H、E5H、E6H和E7H。在STC单片机使用手册中,作者分别将它们定义为: 一、IAP_DATA(E2H) 二、IAP_ADDRH(E3H) 三、IAP_ADDRL(E4H) 四、IAP_CMD(E5H) 五、IAP_TRIG(E6H) 六、IAP_CONTR(E7H) 本人认为,手册中给每个地址单元定义的英文词组太长,而且有点哆嗦,占的篇幅又大,感觉对正常阅读和理解产生了一定的干扰,反倒不好了解作者的意图了,还不如让使用者自己定义为好。我自己对这些单元分别定义为DA T ADDRH ADDRL CMD TRIG CONTR。 一、DAT(E2H)从EEPROM中读取到的数据首先进入这里。要把数据写入EEPROM中,也要把数据放到这个单元中。也就是说,这个单元起到了中转站的作用,写入和读出都要通过这个单元。 二、ADDRH、ADDRL分别是EEPROM地址单元高8位和低8位。如要把数据存储到1000H 单元中,那么在程序中,ADDRH的数值为10H,ADDRL的数值为00H。 三、CMD表示操作类型。数值为1是读,数值为2是写,数值为3是擦除。简单点说,就是“1读2写3擦除”。 四、CONTR寄存器,说明书上作了好多功能表述,但对于一般使用者来说,寄存器的前5位可以不作过多了解,只要掌握后3位意义就可以了。一般理解为,选择好后3位的数值,为的是确保在不同数值晶振下正确读写擦除EEPROM。考虑到TRIG这个寄存器的要求,一般使用时,可将前5位设置为10000,后3位根据不同晶振频率来确定(这个见使用手册)。 五、TRIG这个寄存器,看了好长时间手册才了解它的一般使用,对这个寄存器理解应当放到最后。说明书是这样写的:为isp/iap操作时的命令模式寄存器。在ispen(isp_contr.7)=1时,对isp_trig先写入46h,再写入b9h,isp/iap命令才会生效。 其实也可以这样理解,当选择好EEPROM地址单元,选择好操作类型,以及在写入状态时准备好写入数据后,先向该寄存器送入46H数据,之后再向该寄存器送入B9H数值。EEPROM的读、写、擦除就完成了。 以上是本人对STC单片机的EEPROM使用的一些心得,若有不当或错误之处,请高手多多批评指正。 本人常用的STC_EEPROM基本操作程序 dat equ 0e2h drh equ 0e3h drl equ 0e4h cmd equ 0e5h trig equ 0e6h contr equ 0e7h

STC单片机内部EEPROM的应用

TX-1C开发板学习单片机内部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。 表1 ISP/IAP相关寄存器列表 ISP/IAP从Flash读出的数据放在此处,向Flash写入的数据也需放在此处。 ISP_ADDRH:ISP/IAP操作时的地址寄存器高八位。 ISP_ADDRL:ISP/IAP操作时的地址寄存器低八位。 ISP_CMD:ISP/IAP操作时的命令模式寄存器,须命令触发寄存器触发方可生效。命令模式如表2所示。 区擦除;程序在用户应用程序区时,仅可以对数据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所示,其它型号单片机请查阅相关资料。

51单片机EEPROM的读写

STC单片机的内部EEPROM是用DATAFLASH模拟出来的,不是真正的EEPROM存储器,不能用普通的方法来操作 下面是一些注意点: 1.字节写之前要先将这个字节所在扇区的其它有效数据读取到RAM暂存(这步不是必须的) 2.暂存完之后再对整个扇区(512字节)进行擦除操作,擦拭完后,整个扇区每个地址中数据都变成0xFF 3.将欲写入的N个字节数据,用字节写函数写入EEPROM 4.将暂存到RAM的其它有用的EEPROM值再用字节写函数写回EEPROM 5.STC用FLASH模拟出来的EEPROM的字节写功能只能将1变成0,而不能将0变成1,只有扇区擦除后数据才是全1, 例如:在地址0x21f0处第1次写11010110,第2次写111010,读出结果是这2个值的相与10010 所以如果一个地址处的值不是0xff时写入新的数据是不对的,要先执行扇区擦除,变为0xff, 对于单个字节的写入,我们可以先检查该地址处的数据是否为0xff,是的话就不用擦除扇区了 ---------------------------------------------------------------------- STC89C52单片机内部EEPROM 的读写过程 1 配置ISP_CONTR寄存器,使能第7位ISPEN,让ISP_IAP功能生效,并配置低3位的等待时间 2 写指令: 读/写/擦除扇区这3个命令 3 赋值: ISP_ADDRH和ISP_ADDRL的地址值 4 关闭总中断EA,因为下面要写的2个触发指令必须是连续操作的,不能被中断 5 执行公用的ISP_IAP 触发指令,触发后读写操作才能进行 6 打开中断EA, 关闭ISP_IAP功能:清相关寄存器

相关文档