本文为原创,转载请注明出处!
本例在win10操作系统下,使用keil4"c51v956"版本下完成
STC89C52RC的扇区分布:
/********STC89C52扇区分布*******
第一扇区:2000H--21FF
第二扇区:2200H--23FF
第三扇区:2400H--25FF
第四扇区:2600H--27FF
第五扇区:2800H--29FF
第六扇区:2A00H--2BFF
第七扇区:2C00H--2DFF
第八扇区:2E00H--2FFF
***************************************/
stc89c52rc内部EEPROM操作步骤:
1.擦除EEPROM
2.写EEPROM
3.读EEPROM
将字节写入EEPROM,然后从EEPROM读出字节并发送至串口,可以通过串口调试助手查看并验证
附代码:
主函数:
/** ****************************************************************************** * @file main.c * @author waitstory * @version V1.0 * @date 2018-4-11 * @brief STC89C52RC内部EEPROM的读写 ****************************************************************************** * @attention * * 实验平台:STC89C52RC芯片,晶振11.0592MHz * ****************************************************************************** **/ #include <eeprom.h> void InitUART(uint baud); //串口初始化函数 void UartTXData(uchar str[]); //串口发送函数 void Delay_ms(uint z); //延时函数 uchar TxStr[3] = {0}; uchar dat[2] ={0x01,0x02}; /********STC89C52扇区分布******* 第一扇区:2000H--21FF 第二扇区:2200H--23FF 第三扇区:2400H--25FF 第四扇区:2600H--27FF 第五扇区:2800H--29FF 第六扇区:2A00H--2BFF 第七扇区:2C00H--2DFF 第八扇区:2E00H--2FFF *******************************/ void main() { SectorErase(0x2000); //擦除第一扇区 byte_write(0x2001,dat[0]); //在地址为0x2001的内存写入一个字节 byte_write(0x2002,dat[1]); //在地址为0x2002的内存写入一个字节 Delay_ms(1000); //延时1s InitUART(9600); //串口初始化函数 while(1) { TxStr[0] = byte_read(0x2001); //从地址0x2001读取一个字节 TxStr[1] = byte_read(0x2002); //从地址0x2002读取一个字节 UartTXData(TxStr); //将读取的字节发送至串口 Delay_ms(2000); //延时2s } } /* 串口配置函数,baud-通信波特率 */ void InitUART(uint baud) { EA = 1; //使能中断总开关 SCON = 0x50; //配置串口为模式1 TMOD &= 0x0F; //清零T1的控制位 TMOD |= 0x20; //配置T1为模式2 TH1 = 256 - (11059200/12/32)/baud; //计算T1重载值 TL1 = TH1; //初值等于重载值 ET1 = 0; //禁止T1中断 ES = 1; //使能串口中断 TR1 = 1; //启动T1 } /*串口发送字符串函数*/ void UartTXData(uchar str[]) { uchar i = 0; while(str[i] != '\0') { SBUF= str[i]; i++; while(!TI); TI=0; } } /*延时函数*/ void Delay_ms(uint z) { uint i,j; for(i=z;i>0;i--) for(j=110;j>0;j--); }
EEPROM头文件:
#ifndef _EEPROM_H_ #define _EEPROM_H_ #include <intrins.h> #include <reg52.h> typedef unsigned int uint; typedef unsigned char uchar; /********STC89C52扇区分布******* 第一扇区:2000H--21FF 第二扇区:2200H--23FF 第三扇区:2400H--25FF 第四扇区:2600H--27FF 第五扇区:2800H--29FF 第六扇区:2A00H--2BFF 第七扇区:2C00H--2DFF 第八扇区:2E00H--2FFF *******************************/ #define RdCommand 0x01 //字节编程数据命令 #define PrgCommand 0x02 //字节读数据命令 #define EraseCommand 0x03 //扇区擦除数据命令 #define Error 1 #define Ok 0 #define WaitTime 0x01 //定义CPU的等待时间,40M以下为0,20M以下为1,10M以下为2,5M以下为3 /*****ISP/IAP特殊功能寄存器声明********/ sfr ISP_DATA = 0xE2; sfr ISP_ADDRH = 0xE3; sfr ISP_ADDRL = 0xE4; sfr ISP_CMD = 0xE5; sfr ISP_TRIG = 0xE6; sfr ISP_CONTR = 0xE7; unsigned char byte_read(unsigned int byte_addr); void byte_write(unsigned int byte_addr,unsigned char Orig_data); void SectorErase(unsigned int sector_addr); #endif
EEPROM的C文件:
#include "eeprom.h" /**********打开ISP/IAP功能**************/ void ISP_IAP_Enable(void) { EA = 0; //关中断 ISP_CONTR = ISP_CONTR & 0x18; ISP_CONTR = ISP_CONTR | WaitTime; // 设置等待时间 ISP_CONTR = ISP_CONTR | 0x80; //允许ISP/IAP操作 } /**********关闭ISP/IAP功能**************/ void ISP_IAP_Disable(void) { ISP_CONTR = ISP_CONTR & 0x7f; //禁止ISP/IAP操作 ISP_CMD = 0x00; //去除ISP/IAP命令 ISP_TRIG = 0x00; //防止ISP/IAP命令无触发 EA = 1; // 开中断 } /**********触发ISP/IAP**************/ void ISPTrig(void) { ISP_TRIG = 0x46; //先送46h,再送B9h到ISP/IAP触发寄存器,每次都需如此 ISP_TRIG = 0xb9; //送完B9h后,ISP/IAP命令立即被触发启动 _nop_(); } /**********字节读**************/ unsigned char byte_read(unsigned int byte_addr) { unsigned char dat = 0; //读EEPROM数据缓存 EA = 0; //关中断 ISP_ADDRH = (unsigned char)(byte_addr >> 8); //送地址高字节 ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff); //送地址低字节 ISP_IAP_Enable(); //打开ISP/IAP功能 ISP_CMD = ISP_CMD & 0xf8; //清除ISP_CMD寄存器低3位 ISP_CMD = ISP_CMD | RdCommand; //写入读数据命令 ISPTrig(); //触发ISP/IAP dat = ISP_DATA; //将ISP_DATA寄存器中的数据保存起来 ISP_IAP_Disable(); //关闭ISP/IAP功能 EA = 1; //使能中断 return dat; //返回读到的数据 } /**********字节写**************/ void byte_write(unsigned int byte_addr,unsigned char Orig_data) { EA = 0; //关中断 ISP_ADDRH = (unsigned char)(byte_addr >> 8); //送地址高字节 ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff); //送地址低字节 ISP_IAP_Enable(); //打开ISP/IAP功能 ISP_CMD = ISP_CMD & 0xf8; //清除ISP_CMD寄存器低3位 ISP_CMD = ISP_CMD | PrgCommand; //写入写数据命令 ISP_DATA = Orig_data; //写入数据到ISP_DATA寄存器 ISPTrig(); //触发ISP/IAP ISP_IAP_Disable(); //关闭ISP/IAP功能 EA =1; //使能中断 } /**********扇区擦除**************/ void SectorErase(unsigned int sector_addr) { EA = 0; ISP_ADDRH = (unsigned char)(sector_addr >> 8); //送擦除地址高字节 ISP_ADDRL = (unsigned char)(sector_addr & 0x00ff); //送擦除地址低字节 ISP_IAP_Enable(); ISP_CMD = ISP_CMD & 0xf8; //清除ISP_CMD寄存器低3位 ISP_CMD = ISP_CMD | EraseCommand; //写入擦除数据命令 ISPTrig(); //触发ISP/IAP ISP_IAP_Disable(); //关闭ISP/IAP功能 }
实验结果:
将数据打印至串口,在电脑串口调试助手显示出来