第一个程序最简单易懂,看懂了基本就会读写51单片机内部EEPROM了。
第二个程序和第一个读写EEPROM原理差不多,包含有LCD1602操作方法,有写字符串的方法。 第三个程序在原有基础上增加了外部中断功能,细心的人会发现,操作内部EEPROM过程会将总中断关闭,实际上程序要用到中断时只需在原有的EEPROM操作后加上开总中断即可。
验证第二、第三个程序时需按程序内主程序中的操作说明进行烧录单片机,以验证是否成功操作单片机内部EEPROM。
程序1:
/***************************************************************
作品:EEPROM实验,开机还原关电前LED的亮灭状况
单片机:STC89C52RC
晶振:12M
编译环境:Keil uVision4 V9.00
余华
***************************************************************/
//#include <STC89C52RC.H>
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
/****************特殊功能寄存器声明****************/
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 LED1 = P2^0;
sbit LED2 = P2^1;
sbit K1 = P3^2; //按钮1
sbit K2 = P3^3; //按钮2
void cc(uint addr);
void xcx(uint addr,uchar dat);
uchar dcx(uint addr);
void Q0();
/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:主程序
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
/*
void main(void)
{
uchar V;
V = dcx(0x2002); // 开机读取EEPROM区2002h数据,还原关电前LED的亮灭状况
if(V == 2) {LED1=0;LED2=1;}
else if(V == 6){LED1=0;LED2=0;}
while(1)
{
if(!K1)
{
while(!K1);
LED1=0;LED2=1;
cc(0x2000); // 擦除第1个扇区(2000h~21FFh)
xcx(0x2002,2); // 对EEPROM区2002h写入2
}
if(!K2)
{
while(!K2);
LED1=0;LED2=0;
cc(0x2000); // 擦除第1个扇区(2000h~21FFh)
xcx(0x2002,6); // 对EEPROM区2002h写入6
}
}
华北水利水电学院学报}
*/
/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:擦除某一扇区(每个扇区512字节)
咨询机构┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void cc(uint addr)
{
// 打开 IAP 功能(ISP_CONTR.7)=1:允许编程改变Flash, 设置Flash操作等待时间
// 0x83(晶振<5M) 0x82(晶振<10M) 0x81(晶振<20M) 0x80(晶振<40M)
ISP_CONTR = 0x81;
ISP_CMD = 0x03; // 用户可以对"Data Flash/EEPROM区"进行扇区擦除
ISP_ADDRL = addr; // ISP/IAP操作时的地址寄存器低八位,
ISP_ADDRH = addr>>8; // ISP/IAP操作时的地址寄存器高八位。
EA =0;
ISP_TRIG = 0x46; // 在ISPEN(ISP_CONTR.7)=1时,对ISP_TRIG先写入46h,
ISP_TRIG = 0xB9; // 再写入B9h,ISP/IAP命令才会生效。
_nop_();
Q0(); // 关闭ISP/IAP
}
/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:写一字节
入口:addr = 扇区单元地址 , dat = 待写入数据
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void xcx(uint addr,uchar dat)
{
ISP_CONTR = 0x81;
ISP_CMD = 0x02; // 用户可以对"Data Flash/EEPROM区"进行字节编程
ISP_ADDRL = addr;
ISP_ADDRH = addr>>8;
ISP_DATA = dat; // 数据进ISP_DATA
EA = 0;
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9;
_nop_();
北京联合大学学报
Q0(); // 关闭ISP/IAP
}
/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:读一字节
入口:addr = 扇区单元地址
出口:dat = 读出的数据
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
uchar dcx(uint addr)
{
uchar dat;
ISP_CONTR = 0x81;
ISP_CMD = 0x01; // 用户可以对"Data Flash/EEPROM区"进行字节读
ISP_ADDRL = addr;
ISP_ADDRH = addr>>8;
EA = 0;
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9;
_nop_();
dat = ISP_DATA; // 取出数据
Q0(); // 关闭ISP/IAP
return dat;
}
/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:关闭ISP/IAP操作
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void Q0()
{
ISP_CONTR = 0; // 关闭IAP功能
ISP_CMD = 0; // 待机模式,无ISP操作
ISP_TRIG = 0; // 关闭IAP功能, 清与ISP有关的特殊功能寄存器
}
/*
STC89C52RC内部EEPROM详细地址表:
第一扇区 第二扇区 第三扇区 第四扇区
起始地址 结束地址 起始地址 结束地址 起始地址 结束地址 起始地址 结束地址
2000h 21FFh 2200h 23FFh 2400h 25FFh 2600h 27FFH
第五扇区 第六扇区 第七扇区 第八扇区
起始地址 结束地址 起始地址 结束地址 起始地址 结束地址 起始地址 结束地址
2800h 29FFh 2A00h 2BFFh 2C00h 2DFFh 2E00h 2FFFh
*/
程序2:
/***************************************************************
作品:EEPROM实验,开机还原关电前LED的亮灭状况
单片机:STC89C52RC
晶振:12M
编译环境:Keil uVision4 V9.00
***************************************************************/
//#include <STC89C52RC.H>
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
/****************特殊功能寄存器声明****************/
sfr ISP_DATA = 0xe2;
sfr ISP_ADDRH = 0xe3;
sfr ISP_ADDRL = 0xe4;