STC89C52单片机如何在运行时向EEPROM内写入数据,使数据断电后不消失,下次运行继续用.

kuaidi.ping-jia.net  作者:佚名   更新日期:2024-08-27
怎样在STC89c52单片机的EEPROM里写入和读出一个unsigned int型的数据啊?

下面是我之前写的stc的程序,你可以参考下,都是差不多的。
#include<at89x52.h>
unsigned char data TSET1,TSET2;
void eeprom_write(void); //eeprom写
unsigned char eeprom_read(void); //eeprom读
void eeprom_erase(void); //eeprom擦出
void delay(unsigned char t); //延时
void timerset(void); //延时时间的设定
sfr ISP_DATA = 0xe2; /*ISP/IAP操作时的数据寄存器*/
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控制寄存器*/
/**************************************************
main主程序
***************************************************/
main()
{
unsigned char flag2=0;
TSET1=10;
eeprom_erase();//擦出
eeprom_write();//写
TSET2=eeprom_read();//读
P1_0=1;//开启振动
while(1)
{
while(flag2==0)
{
timerset();
while(P3_2==1);
if(P3_2==0)
{ delay(TSET2);
P1_0=0;
flag2=1;
}
}

while(flag2==1)
{
timerset();
while(P3_2==0);//等待
if(P3_2==1)
{
delay(TSET2);
P1_0=1;
flag2=0;
}
}


}

}
/*************************************************
延时时间设定程序
*************************************************/
void timerset(void)
{
unsigned char flag3=0,a=0;
if(P3_3==0)//增加
{
for(a=0;a<10;a++);
if(P3_3==0)
{
while(P3_3==0);
if(TSET1<20) TSET1++;
flag3=1;
}
}

if(P3_4==0)//减小
{
for(a=0;a<10;a++);
if(P3_4==0)
{
while(P3_4==0);
if(TSET1>1) TSET1--;
flag3=1;
}
}


if(flag3) //设定完毕后更新EEPROM
{
eeprom_erase();//擦出
eeprom_write();//写
TSET2=eeprom_read();//读
flag3=0;
}
}
/*************************************************
EEPROM写程序
*************************************************/
void eeprom_write(void)
{
unsigned char j;

ISP_ADDRH=0x22;//选择存放数据的高八位地址寄存器
ISP_ADDRL=0x22;//选择存放数据的低八位地址寄存器

ISP_CMD=0x02;//命令模式触发对flash写 ,0x01读,0x02写,0x03擦除

ISP_DATA=TSET1;//存放数据



ISP_CONTR=0x9a;//使能ISP、IAP,,ISPEN=1允许改变FLASH,SWBS=0程序从主程序启动,等待时间为010

ISP_TRIG=0X46;//对ISP_TRIG先写0x46
ISP_TRIG=0XB9;//对ISP_TRIG先写0xB9,使ISP/IAP命令生效

for(j=0;j<2;j++);


}
/********************************************
EEPROM读程序
********************************************/
unsigned char eeprom_read(void)
{
unsigned char j;

ISP_ADDRH=0x22;
ISP_ADDRL=0x22;

ISP_CMD=0x01;

ISP_CONTR=0x9a;

ISP_TRIG=0X46;
ISP_TRIG=0XB9;

for(j=0;j<2;j++);
return(ISP_DATA);


}

/***********************************************
EEPROM擦出程序
***********************************************/
void eeprom_erase(void)
{
unsigned char j;

ISP_ADDRH=0x22;
ISP_ADDRL=0x22;

ISP_CMD=0x03;

ISP_CONTR=0x9a;

ISP_TRIG=0X46;
ISP_TRIG=0XB9;

for(j=0;j<2;j++);

}
/***********************************************
延时子程序
**********************************************/
void delay(unsigned char t)
{
unsigned int i,j;
while(t--)
{
for(i=0;i<600;i++)
for(j=0;j<600;j++);
}
}

STC89C52单片机内部EEPROM应用,断电保护的方法,
需要 外电路触发,即 在断电时 给一个触发 信号 产生一个中断,
如 5 V 单片机 在 4.5 V 时产生 触发中断 就可以。
中断服务程序 完成 把需要保存的数据 写入 EEPROM 中。上电时读出恢复。
STC 系列单片机 有些型号 内部 就有 低电压 检测电路,就可以直接用低电压 中断。

1、首先打开电脑中的keil软件。

2、在页面中点击“工程”新建一个工程,命名为“点亮LED”,点击确定。

3、出现一个选择芯片型号的对话框,选择"Atmel"里面的“89C52”,点击确定进行下一步。

4、点击如图所示,新建一个文件,在文件里先输入几个字符。

5、然后点击窗口右上角的打叉,接下来在出现的对话框里选择“是”,重命名为“11.c”文件,点击保存即可完成。



STC89C52RC,有4K的eepROM。

以下是个实例:
/***************************************************************
作品:EEPROM实验,开机还原关电前LED的亮灭状况
单片机:STC89C52RC
晶振:12M
编译环境:Keil uVision4 V9.00
***************************************************************/
#include <STC89C52RC.H>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int

sbit LED1 = P1^1;
sbit LED2 = P1^2;
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字节)
入口:addr = 某一扇区首地址
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void cc(uint addr)
{
// 0x83(晶振<5M) 0x82(晶振<10M) 0x81(晶振<20M) 0x80(晶振<40M)
ISP_CONTR = 0x81; // 打开 IAP 功能(ISPEN(ISP_CONTR.7)=1:允许编程改变Flash, 设置 Flash 操作等待时间。
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

EEPROM是程序存储器,把数据写入进去后就不会消失。

  • STC89C52单片机如何在运行时向EEPROM内写入数据,使数据断电后不消失...
    答:1、首先打开电脑中的keil软件。2、在页面中点击“工程”新建一个工程,命名为“点亮LED”,点击确定。3、出现一个选择芯片型号的对话框,选择"Atmel"里面的“89C52”,点击确定进行下一步。4、点击如图所示,新建一个文件,在文件里先输入几个字符。5、然后点击窗口右上角的打叉,接下来在出现的对话...
  • stc89c52单片机什么时候会自动复位
    答:STC89C52单片机在程序执行过程中会自动复位。通常情况下,复位是由于某种外部事件触发的,比如电源断电、时钟错误、软件复位等。在STC89C52单片机中,复位信号是通过复位引脚(RSTL)传递到CPU内部的复位控制器(RCM),然后由RCM控制CPU的复位状态。当复位信号被触发时,CPU会立即进入复位状态,执行复位程序。在...
  • 请问高手STC89C52单片机如何进入掉电模式工作,又如何唤...
    答:追问: 当单片机进入掉电模式时程序就不运行了,当进入空闲模式时程序还在运行,时这样吗??如果我要设置一个按键,按一下就进入掉电模式,能这样编写吗:#include<reg52.h>sbit key1=P3^0; \\定义按键位置void delay(unsigned int a){while(a--);} \\延时子程序void main(){while(1) {P1...
  • 求STC89C52单片机运算及共阴4位八段数码管显示运算结果的C语言程序...
    答:运行时按下INT0开始计时,再按下INT1得到速度 由于我只有公阳极数码管,(因为要调试)P2为片选端因为我加了三极管,所以也是低电平有效,你是共阴极,片选端可以直接连P2上,你自己把数字取反再调试看看 速度的单位是厘米每秒,定义的L是1米,由于用浮点数表示速度在显示部分会麻烦一点,所以就偷了下...
  • 89c52单片机怎么进入掉电模式?
    答:不是所有的89C52单片机都可以进入掉电模式的,STC89C52可以进入掉电模式。1、当PCON寄存器的D1也就是PCON.1或者叫PD位置1时,单片机进入掉电模式,该模式也叫停机模式。2、进入掉电模式后,内部晶振停震,CPU、定时器、看门狗、串口都停止工作,外部中断继续工作。如果低电压检测被允许,也可以继续工作...
  • 当stc89c52RC单片机运行出错或程序陷入死循环时,如何来摆脱困境?_百度...
    答:单片机运行出错,说明程序有错误,必须查出来修改的,不能就这样错下去吧。程序陷入 死循环 ,这是人为的造成的,要避免写出死循环程序。如何来摆脱困境?很简单,查出 程序错误 ,加以修改,改掉死循环程序。这都是人为的,也要人为的改正。靠单片机自己能改掉吗?
  • 下面51单片机(STC89C52R)当中断执行时,蜂鸣器响,但程序没停,怎么回事...
    答:中断了,程序肯定还是在执行完中断还是继续的,你中断只执行beep=0后程序继续走呀,除非你用一个if去判断beep后把整个程序关闭
  • ...STC89C52单片机, 不用外部中断的前提下,如何对外部信号处理。_百 ...
    答:可以实现 但只能用扫描方式实现 方法:1、把输入端值1,如果输入信号为0的话,会把该端口拉到0电位,这时采集的话,就是0电平。2、该信号的采集在简单程序的时候可在主程序执行,如果主程序过于复杂,可用定时器定时中断进行定时扫描。3、输入端的信号确定了 就可控制输出了。
  • 求STC89C52单片机的详细资料?包括引脚功能,存储器等等的详细介绍,越...
    答:如有必要,可通过对特殊功能寄存器(sfr)区中的8eh单元的d0位置位,可禁止ale操作。该位置位后,只有一条movx和movc指令才能将ale激活。此外,该引脚会被微弱拉高,单片机执行外部程序时,应设置ale禁止位无效。psen——程序储存允许(psen)输出是外部程序存储器的读选通信号,当stc89c52由外部程序存储器...
  • 当stc89c52RC单片机运行出错或程序陷入死循环时,如何来摆脱困境?_百度...
    答:单片机运行出错,说明程序有错误,必须查出来修改的,不能就这样错下去吧。程序陷入死循环,这是人为的造成的,要避免写出死循环程序。如何来摆脱困境?很简单,查出程序错误,加以修改,改掉死循环程序。这都是人为的,也要人为的改正。靠单片机自己能改掉吗?