欢迎光临散文网 会员登陆 & 注册

完整的51单片机EEPROM 使用代码!

2022-01-30 12:58 作者:技术流阿宅  | 我要投稿

版权声明:此文章与内容皆为科技小宅神原创!仅供参考学习,禁止一切商用目的与盈利用途!违者必究!


#ifndef _EEPROM51_H_

#define _EEPROM51_H_

/********STC89C51扇区分布*******

第一扇区:1000H--11FF

第二扇区:1200H--13FF

第三扇区:1400H--15FF

第四扇区:1600H--17FF

第五扇区:1800H--19FF

第六扇区:1A00H--1BFF

第七扇区:1C00H--1DFF

第八扇区:1E00H--1FFF

*****************/


/********STC89C52扇区分布*******

第一扇区:2000H--21FF

第二扇区:2200H--23FF

第三扇区:2400H--25FF

第四扇区:2600H--27FF

第五扇区:2800H--29FF

第六扇区:2A00H--2BFF

第七扇区:2C00H--2DFF

第八扇区:2E00H--2FFF

*****************/

//注释:本程序是对51和52本身自带的eeprom的操作!

//完全按照芯片数据手册编写


//定义ISP的操作命令

#define RdCommand 0x01    //对用户的应用程序flash区及数据flash区字节读 

#define PrgCommand 0x02   //对用户的应用程序flash区及数据flash区字节编程

#define EraseCommand 0x03 //对用户的应用程序flash区及数据flash区扇区擦除

#define Error 1  //应答1

#define Ok 0     //应答0

#define WaitTime 0x01 //定义CPU的等待时间


 //寄存器申明(寄存器地址)

sfr ISP_DATA=0xe2;   //Flash数据寄存器 

sfr ISP_ADDRH=0xe3;  //Flash高字节地址寄存器

sfr ISP_ADDRL=0xe4;  //Flash低字节地址寄存器

sfr ISP_CMD=0xe5;    //Flash命令模式寄存器

sfr ISP_TRIG=0xe6;   //Flash命令触发寄存器

sfr ISP_CONTR=0xe7;  //ISP/IAP 控制寄存器 从Flash读出的数据放在此处,向Flash写入的数据也需放在此处。


// ==========打开 ISP,IAP 功能 ============ //

void ISP_IAP_enable(void)

{

 EA = 0;  

// 关中断, 此时各中断请求,会被挂起,一开中断,立即响应

 ISP_CONTR = ISP_CONTR & 0x18;  

 // 0001,1000 

 // 左到右看,第一个0:ISPEN: ISP/IAP 功能允许位 —— 0:禁止ISP/IAP编程改变Flash,1:允许编程改变 Flash

 // 左到右看,第二个0:SWBS  —— 软件选择从用户主程序区启动 ( 0 ),还是从 ISP 程序区启动( 1 )。

 // 左到右看,第三个0:SWRST —— 0: 不操作; 1: 产生软件系统复位,硬件自动清零。

 // 左到右看,第四个1: 无意义,此处填1、0都可

 // 左到右看,第五个1: 无意义,此处填1、0都可

 // 左到右看,第6-8的0: WT2-WT1-WT0 ——为CPU等待时间(周期),000为40MHZ。 

ISP_CONTR = ISP_CONTR | WaitTime; /* 写入硬件延时 */

ISP_CONTR = ISP_CONTR | 0x80;     //ISPEN=1 允许ISP/IAP 操作  此两句可以合成一句,并且只送一次就够了

}


// ==========关闭 ISP,IAP 功能 ============= //

void ISP_IAP_disable(void)

{

ISP_CONTR = ISP_CONTR & 0x7f; 

// ISPEN = 0  0:禁止ISP/IAP编程改变Flash

ISP_TRIG = 0x00; 

//防止ISP/IAP 命令误触发

EA   =   1;      

//开中断  

}


// ========== 公用的触发代码 ============== //

void ISPgoon(void)

{

ISP_IAP_enable(); //打开 ISP,IAP 功能  

ISP_TRIG = 0x46;  

//触发ISP_IAP命令字节1 先送46h,再送B9h 到ISP/IAP 触发寄存器,每次都需如此

ISP_TRIG = 0xb9;  

//触发ISP_IAP命令字节2 送完 B9h 后,ISP/IAP 命令立即被触发起动

_nop_(); 

//数据读出到 ISP_DATA 寄存器后,CPU 继续执行程序

}


// ============== 字节读 ================= //

unsigned char byte_read(unsigned int byte_addr)

{

EA = 0;

//---地址需要改变时才需重新送地址

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功能 

EA  = 1;

return (ISP_DATA);    //返回读到的数据 


// CPU等待 IAP 动作完成后,才会继续执行程序,要先关中断(EA ),

//再送 46h,B9h 到 ISP/IAP 触发寄存器,起动ISP/IAP 命令,关中断在触发之前即可

}


// ============= 扇区擦除================ //

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; //擦除命令

ISPgoon();  //触发执行  

ISP_IAP_disable();  //关闭ISP,IAP功能 

}


// ============ 字节写 ============//

void byte_write(unsigned int byte_addr, unsigned char original_data)

{

EA  = 0;

 //---地址需要改变时才需重新送地址

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功能 

EA =1;  

//开中断,CPU 处理完 ISP/IAP 动作即可开中断


// CPU等待 IAP 动作完成后,才会继续执行程序,要先关中断(EA ),

//再送 46h,B9h 到 ISP/IAP 触发寄存器,起动ISP/IAP 命令,关中断在触发之前即可

}

#endif


完整的51单片机EEPROM 使用代码!的评论 (共 条)

分享到微博请遵守国家法律