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

合集下载

stc单片机内部eeprom的应用(转)

stc单片机内部eeprom的应用(转)

STC单片机内部EEPROM的应用(转)STC单片机内部EEPROM的应用(转)2008-05-18 02:47:27| 分类:AVR与C51单片机技| 标签:|字号大中小订阅STC单片机内部EEPROM的应用单片机运行时的数据都存在于RAM(随机存储器)中,在掉电后RAM中的数据是无法保留的,那么怎样使数据在掉电后不丢失呢?这就需要使用EEPROM或FLASHROM 等存储器来实现。

在传统的单片机系统中,一般是在片外扩展存储器,单片机与存储器之间通过IIC或SPI等接口来进行数据通信。

这样不光会增加开发成本,同时在程序开发上也要花更多的心思。

在STC单片机中内置了EEPROM(其实是采用IAP技术读写内部FLASH来实现EEPROM),这样就节省了片外资源,使用起来也更加方便。

下面就详细介绍STC单片机内置EEPROM及其使用方法。

STC各型号单片机内置的EEPROM的容量各有不同,见下表: 单片机芯片型号 起始地址 内置EEPROM容量(每扇区512字节)  STC89C51RC,STC89LE51RC 0x2000 共八个扇区 STC89C52RC,STC89LE52RC 0x2000 共八个扇区  STC89C54RD+,STC89LE54RD+ 0x8000 共五十八个扇区  STC89C55RD+,STC89LE55RD+ 0x8000 共五十八个扇区  STC89C58RD+,STC89LE58RD+ 0x8000 共五十八个扇区。

51单片机模拟IIC工作时序,以EEPROM器件进行掉电保护数据

51单片机模拟IIC工作时序,以EEPROM器件进行掉电保护数据

51单片机软件模拟I2C时序,进行掉电保护数据在数码管上按顺序显示数据0—f(十六进制)模拟断电-切断单片机电源复位后接着断电前数据显示#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit sda=P2^0;sbit scl=P2^1;uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39 ,0x5e,0x79,0x71} ;uchar num,sec,panju;//由定时器进行计数,计时,以数组的形式显示于数码管每隔1S读一次AT24C16中的数据//-------------------------------定时器0进行精确的计时,由AT24C16进行掉电保护----------------------------------//void delay(){;;}void init_timer0()//定时器初始化{TMOD=0X01;//工作方式1,GATE=0,C/~T=0,M0=0,M1=1;TH0=15536/256;//求模TL0=15536%256;//求余装入初值EA=1;ET0=1;//中断允许寄存器TR0=1;//TCON寄存器}//------------------------------------------------------------------------------------------------------------//void init_AT()//EEPROM器件初始化释放总线{scl=0;delay();//微秒延时sda=1;delay();scl=1;delay();}//----------------------------------------------------------------------------------------------------------//void start() //起始信号{scl=0;delay();sda=1;delay();scl=1;delay();sda=0;delay();sda=1;//释放数据总线//--------------------------------------------------------------------------------------------------------//void write_byte(uchar date)//字节写{uchar s,temp;//局部变量temp=date;//由高位一位一位的写入for(s=0;s<8;s++){temp=temp<<1;//左移溢出到PSW寄存器CY位scl=0;//允许sda进行的变化delay();sda=CY;//进行一位一位的送入数据总线delay();scl=1;//符合读走数据总线上数据的要求delay();//稳定一段时间}scl=0;//允许sda变化,以便于接受应答信号delay();sda=1;//释放数据总线,准备接收应答信号delay();}//--------------------------------------------------------------------------------------------------------//void response()//应答,可以看书page181,由接收设备发出的第九位数据,要经由sda传输给发送设备{uchar t;//局部变量scl=1;delay();while((sda==1)&&(t<250)){t++;//等待应答有一定的时间限制,sda被拉低表示有应答,由硬件控制}scl=0;delay();}//------------------------------------------------------------------------------------------------------//void stop()//停止信号,scl=1,sda形成一个正跳变{scl=0;//允许sda变化delay();sda=0;//准备形成正跳变delay();scl=1;//信号有效前提1delay();sda=1;//形成正跳变delay();//信号有效前提1}//-----------------------------------------------------------------------------------------------------//void delay1(uint z)//毫秒级延时{for(x=z;x>0;x--)for(y=10;y>0;y--);}//---------------------------------------------------------------------------------------------------------------//uchar read_byte()//带有返回值,将所读到的数据作为返回值{uchar i,d;//局部变量d=0x00;//清空存储变量的空间for(i=0;i<8;i++){scl=0;//允许变化,即允许传送数据,sda是serial dual date busdelay();scl=1;//允许读走数据delay();d=(d<<1)|sda;//将sda上数据放入存储变量d,也是8位ucharscl=0;delay();}return d;}//----------------------------------------------------------------------------------------------------------//void write_add(uchar address,uchar date) //任意位置,写任意内容{start();//起始信号write_byte(0xa0);//写入EEPROM器件地址,写入分为数据,地址数据,地址又分为器件地址和内部存储地址,例如某班级某学生座位response();//等待应答write_byte(address);//内部存储地址实际参数addressresponse();write_byte(date);//写入真正意义上的数据,由引入的实际参数dateresponse();//等待应答stop();//停止读取数据信号delay1(1);}//-------------------------------------------------------------------------------------------------------//uchar read_add(uchar address){uchar shu;start();write_byte(0xa0);//申明所读器件地址response();write_byte(address);//申明该器件中所要求读数据的位置response();start();write_byte(0xa1);response();shu=read_byte();//进行读数据操作后,非应答,budaixingcan,而是将返回值直接赋予变量stop();}//------------------------------------------------------------------------------------------------------------// void main(){P0=0X00;init_AT();sec=read_add(0X03);//将芯片中数据读出;作为基数init_timer0();//定时器初始化设置if(sec==16)sec=0;while(1){P0=table[sec];if(panju==1){panju=0;write_add(0x03,sec);}}}//---------------------------------------------------------------------------------------------------------// void timer0_break() interrupt 1{TH0=15536/256;//求模TL0=15536%256;//求余装入初值num++;if(num==20){num=0;sec++;panju=1;if(sec==16) sec=0;}}。

51单片机空闲和掉电模式详解

51单片机空闲和掉电模式详解

51单片机空闲和掉电模式应用我们知道单片机内部有一个电源管理寄存器PCON,这个寄存器的最低两位,IDL和PD这两位分别用来设定是否使单片机进入空闲模式和掉电模式。

1. 空闲模式当单片机进入空闲模式时,除CPU处于休眠状态外,其余硬件全部处于活动状态,芯片中程序未涉及到的数据存储器和特殊功能寄存器中的数据在空闲模式期间都将保持原值。

但假若定时器正在运行,那么计数器寄存器中的值还将会增加。

单片机在空闲模式下可由任一个中断或硬件复位唤醒,需要注意的是,使用中断唤醒单片机时,程序从原来停止处继续运行,当使用硬件复位唤醒单片机时,程序将从头开始执行。

让单片机进入空闲模式的目的通常是为了降低系统的功耗,举个很简单的例子,大家都用过数字万用表,在正常使用的时候表内部的单片机处于正常工作模式,当不用时,又忘记了关掉万用表的电源,大多数表在等待数分钟后,若没有人为操作,它便会自动将液晶显示关闭,以降低系统功耗,通常类似这种功能的实现就是使用了单片机的空闲模式或是掉电模式。

以STC89系列单片机为例,当单片机正常工作时的功耗通常为4mA~7mA,进入空闲模式时其功耗降至2mA,当进入掉电模式时功耗可降至0.1μA以下。

2. 休眠-掉电模式当单片机进入掉电模式时,外部晶振停振、CPU、定时器、串行口全部停止工作,只有外部中断继续工作。

使单片机进入休眠模式的指令将成为休眠前单片机执行的最后一条指令,进入休眠模式后,芯片中程序未涉及到的数据存储器和特殊功能寄存器中的数据都将保持原值。

可由外部中断低电平触发或由下降沿触发中断或者硬件复位模式换醒单片机,需要注意的是,使用中断唤醒单片机时,程序从原来停止处继续运行,当使用硬件复位唤醒单片机时,程序将从头开始执行。

【例】:开启两个外部中断,设置低电平触发中断,用定时器计数并且显示在数码管的前两位,当计到5时,使单片机进入空闲(休眠)模式,同时关闭定时器,当单片机响应外部中断后,从空闲(休眠)模式返回,同时开启定时器。

51单片机内部EEPROM读写

51单片机内部EEPROM读写

51单⽚机内部EEPROM读写#include <reg52.h>#include <intrins.h>//定义类型,⽅便代码移植typedef unsigned char UINT8;typedef unsigned int UINT16;typedef unsigned long UINT32;typedef char INT8;typedef int INT16;typedef long INT32;static UINT8 i=0;/*定义寄存器 ISP*/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 控制寄存器#define NOP() _nop_()#define EEPROM_START_ADDRESS 0X2000#define LED_PORT P2//微秒级延时void DelayNus(UINT16 t){UINT16 d=0;d=t;do{NOP();}while(--d > 0);}//毫秒级延时void DelayNms(UINT16 t){do{DelayNus(1000);}while(--t > 0);}//EEPROM使能void EEPROMEnable(void){ISP_CONTR=0x81;//使能并设置好等待时间}//EEPROM禁⽤void EEPROMDisable(void){ISP_CONTR=0x00;//禁⽌EEPROMISP_CMD = 0X00;//⽆ISP操作ISP_TRIG = 0X00;//清零ISP_ADDRH = 0X00;//清零ISP_ADDRL = 0X00;//清零}//eeprom 设置读写地址(相对地址)void EEPROMSetAddress(UINT16 addr){addr+=EEPROM_START_ADDRESS;//初始化地址ISP_ADDRH=(UINT8)(addr>>8);//设置读写地址⾼字节ISP_ADDRL=(UINT8) addr; //设置读写地址低字节}//EEPROM启动void EEPROMStart(void){ISP_TRIG=0x46;ISP_TRIG=0xB9;}//EEPROM读取单个字节UINT8 EEPROMReadByte(UINT16 addr){ISP_DATA=0X00;ISP_CMD=0X01;EEPROMEnable();EEPROMSetAddress(addr);EEPROMStart();DelayNus(10);//读取⼀个字节需要10usEEPROMDisable();return (ISP_DATA);}//EEPROM写⼊单个字节UINT8 EEPROMWriteByte(UINT16 addr,UINT8 byte) {EEPROMEnable();ISP_CMD=0X02;EEPROMSetAddress(addr);ISP_DATA=byte;EEPROMStart();DelayNus(60);EEPROMDisable();}//EEPROM扇区擦除UINT8 EEPROMSectorErase(UINT16 addr){ISP_CMD=0X03;EEPROMEnable();EEPROMSetAddress(addr);EEPROMStart();DelayNus(10);//EEPROMDisable();}void main(void){EEPROMSectorErase(0);EEPROMWriteByte(0,0x0f);i=EEPROMReadByte(0);LED_PORT = i;while(1);}现象:。

STC51单片机 内部EEPROM操作

STC51单片机 内部EEPROM操作

#include<reg52.h>#include<intrins.h>typedef unsigned char BYTE;typedef unsigned int WORD;//声明SFR IAP联系在一起的sfr IAP_DATA=0xE2; // flash data registersfr IAP_ADDRH=0xE3; //flash address highsfr IAP_ADDRL=0xe4; //falsh address lowsfr IAP_CMD=0Xe5; //FALSH COMMAND TRGGERsfr IAP_TRIG=0xE6; //flash command triggersfr IAP_CONTR=0xE7; //flash control register//定义ISP/IAP/EEPROM 命令#define CMD_IDIE 0 //stand-by#define CMD_READ 1 //BYTE - READ#define CMD_PROGRAM 2 // BYTE- PROGRAM#define CMD_ERASE 3 //SECTOR --ERASE//define ISP/IAP/EEPROM operation const for IAP_CONTR//#define ENABLE_IAP 0X80 //SYSCLK<40MHZ#define ENABLE_IAP 0X81 // SYSCLK<20MHZ//#define ENABLE_IAP 0x82 //SYSCLK<10MHZ//#define ENABLE_IAP 0X83 //SYSCLK<5MHZ//Start addtess for STC89C58 eeprom#define IAP_ADDRESS 0x08000void Delay(BYTE n);void IapIdle();BYTE IapReadByte(WORD addr);void IapProgramByte(WORD addr,BYTE dat);void IapEraseSector(WORD addr);void main(){WORD i;P1=0xfe; //1111,1110 system reset okDelay(5);IapEraseSector(IAP_ADDRESS); //ERASE CURRENT SECTOR for(i=0;i<512;i++) //check whether all sector data is ff {if(IapReadByte(IAP_ADDRESS+i)!=0xff)goto Error; //if error ,break}P1=0xfc; //1111,1100 erase successfulDelay(5);for(i=0;i<256;i++) //program 512 bytes data into data flash{IapProgramByte(IAP_ADDRESS+i,(BYTE)i);}P1=0XF8; //1111,1000 program successfulDelay(5);for(i=0;i<256;i++) //verify 512 bytes data{if(IapReadByte(IAP_ADDRESS+i)!=(BYTE)i)goto Error;}P1=0xf0; //1111,0000 verify successfulwhile(1);Error:P1&=0x7f; //oxxx,xxxx IAP operation failwhile(1);}// software delay functionvoid Delay(BYTE n){WORD x;while(n--){x=0;while(++x);}}//disable ISP/IAP/EEPROM function MAKE MCU in a safe state void IapIdle(){IAP_CONTR=0; //CLOSE IAP FUNCTIONIAP_CMD=0; //CLEAR COMMAND TO STANDBYIAP_TRIG=0; //CLEAR TRIGGER REGISTERIAP_ADDRH=0X80; //DATA PTR POINT TO NON-EEPROM AREA IAP_ADDRL=0; //CLEAR IAP ADDRESS TO PREVENT MISUSE }//Read one byte from ISP/IAP/EEPROM area//Input:addr (ISP/IAP/EEPROM address//Output: flash adataBYTE IapReadByte(WORD addr){BYTE dat;IAP_CONTR=ENABLE_IAP; //OPEN IAP FUNCTION ,AND SET WAIT TIMEIAP_CMD=CMD_READ; //SET ISP/IAP/EEPROM READ COMMANDIAP_ADDRL=addr; //SET ISP/IAP/EEPROM address lowIAP_ADDRH=addr>>8; //SET ISP//IAP//EEPROM address HIGHIAP_TRIG=0X46; //SEND TRIGGER COMMAND1 OX46IAP_TRIG=0XB9; //SEND TRIGGER COMMAND2 0XB9_nop_();dat=IAP_DATA; //read ISP/IAP/EEPROM dataIapIdle(); // close ISP/IAP/EEPROM FUNCITONreturn dat; //RETURN FLAH DATA}//Program one byte to ISP/IAP/EEPROM area//INPUT :addr (ISP/IAP/EEPROM address)//dat(ISP/IAP/EEPROM data)//Output:-void IapProgramByte(WORD addr, BYTE dat){IAP_CONTR=ENABLE_IAP; //OPEN IAP FUNTION AND SET WAIT TIMEIAP_CMD=CMD_PROGRAM; //SET ISP/IAP/EEPROM PROGRAM COMMAND IAP_ADDRL=addr; //set ISP/IAP/EEPROM ADDRESS LOWIAP_ADDRH=addr>>8; //set ISP/IAP/EEPROM address highIAP_DATA=dat; // WRITE ISP/IAP/EEPROM dataIAP_TRIG=0X46;IAP_TRIG=0XB9;_nop_();IapIdle();}void IapEraseSector(WORD addr){IAP_CONTR=ENABLE_IAP;IAP_CMD=CMD_ERASE;IAP_ADDRL=addr;IAP_ADDRH=addr>>8;IAP_TRIG=0X46;IAP_TRIG=0XB9;_nop_();IapIdle();}。

掉电时保存数据到EEPROM中的这些问题

掉电时保存数据到EEPROM中的这些问题

掉电时保存数据到EEPROM中的这些问题我想在掉电时保存数据(3个字节)到EEPROM中,用BOD掉电检测,不知怎样使用。

望高手指点:1.在BOOT区设置好BODEN,BODLEVEL,后软件还要怎样设置?2.掉电中断是否是产生复位?我的写EEPROM程序应该放在什么地方?他和其他复位怎样区别?3.设置了BOOT区后,硬件上是否要加电源到一个管脚比较后才产生中断?掉电检测BOD的误解AVR自带的BOD(Brown-out Detection)电路,作用是在电压过低(低于设定值)时产生复位信号,防止CPU意外动作.对EEPROM的保护作用是当电压过低时保持RESET信号为低,防止CPU意外动作,错误修改了EEPROM的内容而我们所理解的掉电检测功能是指 具有预测功能的可以进行软件处理的功能。

例如,用户想在电源掉电时把SRAM数据转存到EEPROM,可行的方法是外接一个在4.5V翻转的电压比较器(VCC=5.0V,BOD=2.7V),输出接到外部中断引脚(或其他中断),一但电压低于4.5V,马上触发中断,在中断服务程序中把数据写到EEPROM中保护起来。

注意: 写一个字节的EEPROM时间长达8mS,所以不能写入太多数据,电源滤波电容也要选大一些。

将AVR的BOD设为2.7V,从4.5v到2.7这段时间写EEPROM。

掉电检测使用IMP809。

参考电路如下:在图中,外部9V电源通过7805稳压到5V,作为系统电源使用。

而AVR的工作电源则是单独提供的,由5v系统电源通过低压差肖特基二极管1N5817后得到。

IN5817的正向压降为0.3v,因此,AVR的工作电压为4.7v。

电源监控芯片IMP809-L的监控电压为4.63V,当系统电源的电压低于4.63V时,在R脚上产生由高电平到低电平的变化,使AVR进入INT0中断。

该电路的工作原理为:首先通过配置AVR的熔丝位,设置BOD掉电检测电压门限为2.7V,并允许BOD检测。

51单片机空闲和掉电模式应用

51单片机空闲和掉电模式应用

51单片机空闲和掉电模式应用我们知道单片机内部有一个电源管理寄存器PCON,这个寄存器的最低两位,IDL和PD这两位分别用来设定是否使单片机进入空闲模式和掉电模式。

1. 空闲模式当单片机进入空闲模式时,除CPU处于休眠状态外,其余硬件全部处于活动状态,芯片中程序未涉及到的数据存储器和特殊功能寄存器中的数据在空闲模式期间都将保持原值。

但假若定时器正在运行,那么计数器寄存器中的值还将会增加。

单片机在空闲模式下可由任一个中断或硬件复位唤醒,需要注意的是,使用中断唤醒单片机时,程序从原来停止处继续运行,当使用硬件复位唤醒单片机时,程序将从头开始执行。

让单片机进入空闲模式的目的通常是为了降低系统的功耗,举个很简单的例子,大家都用过数字万用表,在正常使用的时候表内部的单片机处于正常工作模式,当不用时,又忘记了关掉万用表的电源,大多数表在等待数分钟后,若没有人为操作,它便会自动将液晶显示关闭,以降低系统功耗,通常类似这种功能的实现就是使用了单片机的空闲模式或是掉电模式。

以STC89系列单片机为例,当单片机正常工作时的功耗通常为4mA~7mA,进入空闲模式时其功耗降至2mA,当进入掉电模式时功耗可降至0.1μA以下。

2. 休眠模式当单片机进入掉电模式时,外部晶振停振、CPU、定时器、串行口全部停止工作,只有外部中断继续工作。

使单片机进入休眠模式的指令将成为休眠前单片机执行的最后一条指令,进入休眠模式后,芯片中程序未涉及到的数据存储器和特殊功能寄存器中的数据都将保持原值。

可由外部中断低电平触发或由下降沿触发中断或者硬件复位模式换醒单片机,需要注意的是,使用中断唤醒单片机时,程序从原来停止处继续运行,当使用硬件复位唤醒单片机时,程序将从头开始执行。

【例】:开启两个外部中断,设置低电平触发中断,用定时器计数并且显示在数码管的前两位,当计到5时,使单片机进入空闲(休眠)模式,同时关闭定时器,当单片机响应外部中断后,从空闲(休眠)模式返回,同时开启定时器。

51单片机读写内部EEPROM详解

51单片机读写内部EEPROM详解
void Lcd1602_Delay1ms(uint c); //误差0us
/*LCD1602写入8位命令子函数*/
void LcdWriteCom(uchar com);
/*LCD1602写入8位数据子函数*/
void LcdWriteData(uchar dat);
/*LCD1602初始化子程序*/
{
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;址
出口:dat =读出的数据
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
uchar dcx(uint addr)
{
uchar dat;
ISP_CONTR = 0x81;
ISP_CMD = 0x01; //用户可以对"Data Flash/EEPROM区"进行字节读
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();
#ifndef uchar
#define uchar unsigned char
sfr ISP_DATA = 0xe2;
sfr ISP_ADDRH = 0xe3;

51单片机读写内部EEPROM详解

51单片机读写内部EEPROM详解
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
特殊功能寄存器声明****************
sfr ISP_DATA=0xe2;
sfr ISP_ADDRH=0xe3;
sfr ISP_ADDRL=0xe4;
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;
uchar dcx(uint addr);
voidQ0();
/*
*/
/*
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;}
验证第二、第三个程序时需按程序内主程序中的操作说明进行烧录单片
机,以验证是否成功操作单片机内部EEPROM。
程序1:
/***************************************************************
作品:EEP ROM实验,开机还原关电前LED的亮灭状况
ISP_ADDRH=addr>>8;

单片机原理与应用基于汇编、C51及混合编程第10章STC系列单片机片内EEPROM的应用PPT课件

单片机原理与应用基于汇编、C51及混合编程第10章STC系列单片机片内EEPROM的应用PPT课件
EEPROM进行读、写、擦除操作 MOV IAP_CMD,#00000001B ;送字节读指令 MOV IAP_TRIG,#5AH ;启动内部读取工作
MOV IAP_TRIG,#0A5H NOP ;等待2个时钟周期的时间
NOP MOV A,ISP_DATA ;将读出的数据存入A寄存器
• 对STC10/10Fxx、STC12C5Axx等系列单片机 启动读、写、擦除工作时,先给IAP_TRIG寄 存器送立即数5AH,再送A5H作为触发信号; 而对STC12C56xx、STC12C54xx、 STC89/90C51xx等系列单片机需先送46H, 再送B9H作为触发信号。
11111111B
IAP_ADDRH C3H/E3H 地址寄存器高8位 00000000B
IAP_ADDRL C4H/E4H 地址寄存器低8位 00000000B
IAP_CMD
C5H/E5H 命令寄存器
xxxxxx00B
IAP_TRIG
C6H/E6H 命令触发寄存器 xxxxxxxxB
IAP_CONTR C7H/E7H 控制寄存器
RET
BYTE_PROGRAM:
;写
MOV A,@R0 ;读取片内RAM单元50H-5FH的内容
MOV IAP_DATA,A ;将数据送至数据寄存器
MOV IAP_CONTR,#82H ;允许对EERPOM操作并设置等待 时间
MOV IAP_CMD,#02H ;对EEPROM进行写操作指令
MOV IAP_ADDRL,DPL;送地址的低8位
ORG 0000H LJMP MAIN ORG 0100H MAIN: MOV SP,#0BFH;初始化堆栈指针 START0: MOV DPTR,#SECTION_ADDR ;第一扇区的首地址 送DPTR LCALL SECTION_ERASE;调用扇区擦除子程序 MOV A,IAP_CONTR ;读控制寄存控制器 JNB ACC.4,START;若此位为0,表示擦除成功,可进行编程 LJMP START0 ;若擦除失败,须重新进行擦除

单片机51省电工作方式

单片机51省电工作方式

AT89C51省电工作方式AT89C51有两种可用软件来选择的省电方式——空闲工作方式和掉电工作方式。

这两个方式是由专用寄存器PCON(电源控制寄存器)中PD(PCON.1)和IDL(PCON.0)位来控制的。

PD是掉电方式,当PD=1时,激活掉电工作方式,IDL是空闲方式位,当IDL=1时,激活空闲工作方式。

若PD和IDL同时为1,则先激活掉电方式。

1、空闲工作方式执行完一条IDL(PCON.0)置1的指令后,单片机就进入空闲方式,该指令是CPU执行的最后一条指令,这条指令执行完以后CPU停止工作。

在空闲方式下.CPU处于睡眠状态,但片内的其他部件仍然工作,而且片内RAM的内容和所有专用寄存器的内容在空闲方式期间都被保留起来。

有两条途经可以终止空闲方式。

一个方法是激活任何一个被允许的中断,IDL(PCON.0)将被硬件清除,结束空闲工作方式,中断得到响应后,进入中断服务子程序,紧跟在RET1之后,下一条要执行的指令将是使单片机进入空闲方式那条指令的后面一条指令。

终止空闲方式的另一个方法是通过硬件复位。

要注意的是,当空闲方式是靠硬件复位来结束时,CPU通常都是从激活空闲方式那条指令的下一条指令开始继续执行。

但要完成内部复位操作,硬件复位信号要保持2个机器周期(24个振荡器周期)有效。

在此情况下,片内的硬件禁止CPU访问内部RAM,但不禁止其访问端口引脚。

当空闲方式是通过硬件复位来结束时,为了排除对端口引脚产生意外写入的可能性,激活空闲方式那条指令的下一条指令就不应该是一条对一个端口引脚或对外部存储器写入的指令。

2.掉电工作方式执行完一条把PD(PCON.1)置1的指令后.单片机就进入掉电方式。

激活掉电方式的那条指令是CPU执行的最后一条指令,这条指令执行完以后,CPU停止工作。

在掉电方式下,片内振荡器停止工作。

由于时钟被“冻结”,一切功能都停止。

片内RAM的内容和专用寄存器中的内容一直保持到掉电方式结束为止。

STM32L051测试 (四、Flash和EEPROM的读写)

STM32L051测试 (四、Flash和EEPROM的读写)

STM32L051 测试第 4 课,掉电数据保存的测试。

..修改文中以前的问题,增加后续问题说明(数据存储大小端模式)..增加后续问题2.4.3(STM32L071RBT6 EEPROM读写全字问题)..更新一下STM32L071 EEPROM读写全字问题最后解决说明•1、STM32L051内部存储模块地址范围•2、读写函数的设计▪ 2.1 读取函数▪ 2.2 EEPROM写函数▪ 2.3 Flash写函数▪ 2.4 读写EEPROM的后续问题•总结本文测试L051 flash的读写,用来处理以后应用中的掉电数据保存。

1、STM32L051内部存储模块地址范围开始找到F103的FLASH图复习了一遍,然后L051C8T6,64KB的flash,然后我惊奇的发现还有2KB的EEPROM。

发现L051系列的地址与F103完全不同,F103的flash每页的长度有1KB(小容量<=64KB)和2KB(大容量128KB起)查看各种资料,查了2个小时,还是不知道L051的flash 每页长度是128Byte 还是256Byte还是请教了一下大佬,发现直接在J-Flash中可以找到答案,先上个F103的图:然后来看个L051的图:图中64KB 的flash 和2KB的EEPROM都能都明显的看出地址,flash 512页,每页128bytes,EEPROM只有4页,每页512bytes.知道了基本的地址,就可以操作起来了。

最后还需要确定的一点事,最小擦除单元是128bytes,还是256bytes,按以前的认知,删除是按照一个Sector擦除的,也就是128bytes,但是我查看了一些网上的例子和资料,有的是说256bytes,所以后面需要自己确定一下其实在HAL库的stm32l0xx_hal_flash.h 文件中有过FLASH_PAGE_SIZE 的定义,就是128bytes :#define FLASH_SIZE (uint32_t)((*((uint32_t *)FLASHSIZE_BASE)&0xFFFF) * 1024U)#define FLASH_PAGE_SIZE ((uint32_t)128U) /*!< FLASH Page Size in bytes * /对于flash的操作,有一些基础知识补充一下:Read interface organized by word, half-word or byte in every area • Programming in the Flash memory performed by word or half-page • Programming in the Option bytes area performed by word • Programmi ng in the data EEPROM performed by word, half-word or byte • Erase operation performed by page (in Flash memory, data EEPROM and Option bytes)STM32L051写Flash必须字,读字节、半字、字都支持。

基于51单片机的空闲模式和掉电模式实验演示

基于51单片机的空闲模式和掉电模式实验演示

1、仿真电路2、源代码/****************************************************************** **************基于51单片机的空闲模式和掉电模式实验演示** File :main.c* Created by :********************************************************************* **********/#include <reg51.h>// --------------------------------------------------#define IDL_ON() PCON|=0x01 //打开空闲模式//#define IDL_OFF() PCON&=0xfe //关闭空闲模式#define PD_ON() PCON|=0x02//打开掉电模式//#define PD_OFF() PCON&=0xfd //关闭掉电模式sbit Led_PWD=P0^0; //掉电模式指示灯(红),进入掉电模式,指示灯亮sbit Led_Idle=P0^3; //空闲模式指示灯(黄),进入空闲模式,指示灯亮sbit WorkLedCtrl=P0^6; //正常模式指示灯(绿),正常模式150ms间隔闪烁sbit Led_Idle_Once=P2^0; //第一次INT1中断使退出空闲模式,此灯(蓝)闪烁// --------------------------------------------------1typedef unsigned char uchar; typedef unsigned int uint;typedef struct {uchar flag_150ms:1;// 150ms事件标志uchar flag_5s:1; // 5s事件标志uchar flag_10s:1;// 10s事件标志uchar flag_Idle:1; //进入空闲模式标志uchar flag_Idle_INT1:1; //空闲模式时,INT1中断标志} FLAG;//定义FLAG数据类型// --------------------------------------------------FLAG idata User; //用户标志,存储在内部RAM中uint idata count; //时间计数器,存储在内部RAM中// --------------------------------------------------void delay(uint z);//延时函数void init(void); //初始化函数void system_event_pro(void); //系统事件处理函数// --------------------------------------------------void delay(uint z) //延时{uint x,y;for(y=0;y<z;y++)for(x=0;x<120;x++);}void init(void) //初始化{User.flag_150ms=0; User.flag_5s=0;User.flag_10s=0;User.flag_Idle=0;User.flag_Idle_INT1=0; //用户标志初始化count=0; //时间计数器初始化Led_PWD=1;Led_Idle=1;WorkLedCtrl=1;Led_Idle_Once=1; //关闭所有指示灯IT0=1; // INT0下降沿触发EX0=1; //允许INT0xxIT1=1; // INT1下降沿触发EX1=1; //允许INT1xxTMOD |= 0x01; // Timer0,16位定时器TH0=0x3c;TL0=0xb0; // 12MHz,50msET0=1; //允许Timer0xxTR0=1; //打开Timer0PT0=1; // Timer0中断优先级最高EA=1; //允许总中断}void system_event_pro(void) //系统事件处理{if(User.flag_150ms){2User.flag_150ms=0;WorkLedCtrl = ~WorkLedCtrl;//正常模式指示灯闪烁}if(User.flag_10s) //掉电模式优先,避免进入空闲模式,复又进入掉电模式{User.flag_5s=0; //进入掉电模式,复位才能退出,可以不用下列语句,STARTUP.A51会对内部RAM清零User.flag_10s=0;//TR0=0; //关闭Timer0,定时器在掉电模式停止工作,复位,特殊功能寄存器的值将重新定义WorkLedCtrl=1; //关闭正常模式指示灯delay(10);Led_PWD=0; //打开掉电模式指示灯PD_ON(); //进入掉电模式}if(User.flag_5s){User.flag_5s=0; // 5s事件标志清零// Timer0不能打开,定时器在空闲模式仍在工作,避免定时中断退出空闲模式while(TR0) TR0=0; //关闭Timer0,等待外部中断INT0\INT1或者复位唤醒单片机WorkLedCtrl=1; //关闭正常模式指示灯delay(10);Led_Idle=0; //打开空闲模式指示灯User.flag_Idle=1; //设置进入空闲模式标志IDL_ON(); //进入空闲模式}while(User.flag_Idle) //第一次INT1中断使退出空闲模式,进入此循环;第二次INT1中断退出此循环{Led_Idle_Once =~Led_Idle_Once; //第一次INT1中断使退出空闲模式,此灯(蓝)闪烁delay(300);}}void main(void){init();//初始化while(1){system_event_pro(); //系统事件处理}}void INT0_ISR(void) interrupt 0//外部中断INT0服务子程序{//中断退出空闲模式if(User.flag_Idle){Led_Idle=1; //关闭空闲模式指示灯User.flag_Idle=0; //清除进入空闲模式标志User.flag_Idle_INT1=0; //清除INT1中断标志Led_Idle_Once=1; //关闭蓝灯TR0=1; //打开Timer0,返回正常模式}}void INT1_ISR(void) interrupt 2//外部中断INT1服务子程序{//中断退出空闲模式if(User.flag_Idle_INT1) //第一次INT1中断使退出空闲模式,第二次INT1中断{User.flag_Idle_INT1=0;User.flag_Idle=0; //清除进入空闲模式标志Led_Idle_Once=1; //关闭蓝灯TR0=1; //打开Timer0,返回正常模式}3if(User.flag_Idle){Led_Idle=1; //关闭空闲模式指示灯User.flag_Idle_INT1=1; //空闲模式,设置INT1中断标志}}void Timer0_ISR(void) interrupt 1 //定时器T0服务子程序{count++; if(count>=65535) // Keil C51中,unsigned int为双字节count=0; //计数器溢出清零if(!(count%3)) // 150msUser.flag_150ms=1;if(!(count%100)) // 5sUser.flag_5s=1;if(!(count%200)) // 10sUser.flag_10s=1;}4。

基于51单片机的EEPROM读写

基于51单片机的EEPROM读写

基于51单片机的EEPROM读写本讲内容:对存储器的基本知识进行介绍。

介绍EEPROM芯片AT24C02;通过例程展示EEPROM的读写。

存储器是应用于各种嵌入式场合的存储部件,按功能可分为只读存储器(ROM)和随机存取存储器(RAM)两大类,分别用作固定数据存储和临时数据缓存。

RAM(Random Access Memory),随机存取存储器:RAM的特点是:上电运行时,操作系统和应用程序的所有正在运行的数据和程序都会放置其中,并且随时可以对存放在里面的数据进行修改和存取。

它的工作需要由持续的电力提供,一旦系统断电,存放在里面的所有数据和程序都会自动清空掉,并且再也无法恢复。

使用得比较多的RAM种类有:DRAM(Dynamic RAM,动态随机存取存储器):这是最普通的RAM,一个电子管与一个电容器组成一个位存储单元,DRAM将每个内存位作为一个电荷保存在位存储单元中,用电容的充放电来做储存动作,但因电容本身有漏电问题,因此必须每几微秒就要刷新一次,否则数据会丢失。

存取时间和放电时间一致,约为2~4ms。

因为成本比较便宜,通常都用作计算机内的主存储器。

SRAM(Static RAM,静态随机存取存储器):静态,指的是内存里面的数据可以长驻其中而不需要随时进行存取。

每6颗电子管组成一个位存储单元,因为没有电容器,因此无须不断充电即可正常运作,因此它可以比一般的动态随机处理内存处理速度更快更稳定,往往用来做高速缓存。

SDRAM(Synchronous DRAM,同步动态随机存取存储器):这是一种与CPU实现外频Clock同步的内存模式,工作电压为3.3V。

所谓clock同步是指内存能够与CPU同步存取资料,这样可以取消等待周期,减少数据传输的延迟,因此可提升计算机的性能和效率。

DDR SDRAM(Double Data Rate二倍速率同步动态随机存取存储器):作为SDRAM的换代产品,它具有两大特点:其一,速度比SDRAM有一倍的提高;其二,采用了DLL(Delay Locked Loop:延时锁定回路)提供一个数据滤波信号。

STC51单片机EEPROM的使用方法

STC51单片机EEPROM的使用方法

STC51单片机EEPROM的使用方法STC51单片机有类似flash的功能EEPROM,可以掉电保存数据,不同型号的可以保存不同大小的数据,以12C5A60S2为例,EEPROM的大小为2K,分为两个扇区,掉电保存在很多地方需要。

首先寄存器的问题,不同系列的STC单片机的与EEPROM有关的寄存器不同,比如10/11/12系列的sfr ISP_DATA = 0xC2;sfr ISP_ADDRH = 0xC3;sfr ISP_ADDRL = 0xC4;sfr ISP_CMD = 0xC5;sfr ISP_TRIG = 0xC6;sfr ISP_CONTR = 0xC7;89/90系列的sfr ISP_DATA = 0xe2;sfr ISP_ADDRH = 0xe3;sfr ISP_ADDRL = 0xe4;sfr ISP_CMD = 0xe5;sfr ISP_TRIG = 0xe6;sfr ISP_CONTR = 0xe7;注意寄存器一定要按数据手册中的配置,ISP触发命令也不相同,详情请看下方代码其次是关于扇区问题,不同型号的MCU扇区个数不尽相同,详情请查询数据手册,在这里我以12C5A60S2为例,一共2扇区,每扇区512B,地址区间为0x0000~0x03FF,使用时请勿超出范围。

EEPROM使用时有三个功能,分别为读、写、和擦除,由ISP_CMD寄存器控制,分别对应1/2/3下面为此项内容的代码部分,分别为初始化、读、擦除和写,本程序为11.0592MHz晶振,STC12C5A60S2的MCU,以下程序测试可用EEPROM.cvoid DisableEEPROM(void){ISP_CONTR = 0;//禁止ISP/IAP操作ISP_CMD = 0;//去除ISP/IAP命令ISP_TRIG = 0;//防止ISP/IAP命令误触发ISP_ADDRH = 0xff;//指向非EEPROM区,防止误操作ISP_ADDRL = 0xff;//指向非EEPROM区,防止误操作。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

主函数:
#include<reg52.h>
#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<reg52.h>
#include<intrins.h>
//sfr定义特殊功能寄存器
sfr ISP_DATA =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 控制寄存器
/* 定义命令*/
#define uchar unsigned char /*8bit无符号整型*/
#define uint unsigned int /*16bit无符号整型*/
#define READ_AP_and_Data_Memory_Command 0x01 /*字节读数据存储区*/
#define PROGRAM_AP_and_Data_Memory_Command 0x02 /*字节编程数据存储区*/
#define SECTOR_ERASE_AP_and_Data_Memory_Command 0x03 /*扇区擦除数据存储*/
#define DEBUG_Data_Memory_Begin_Sector_addr 0x2000//扇区地址
#define DELAY_CONST 60000//延时
#define WAIT_TIME 0x01
uchar num;
/* 打开ISP,IAP 功能*/
void ISP_IAP_enable(void)
{
EA=0;/* 关中断*/
ISP_CONTR=ISP_CONTR & 0x18; /* 0001,1000 */
ISP_CONTR=ISP_CONTR|WAIT_TIME;
ISP_CONTR=ISP_CONTR|0x80; /* 1000,0000 */
}
/* 关闭ISP,IAP 功能*/
void ISP_IAP_disable(void)
{
ISP_CONTR=ISP_CONTR&0x7f;/* 0111,1111 */
ISP_TRIG=0x00;
EA=1;/* 开中断*/
}
/* 字节读*/
uchar byte_read(uint byte_addr)
{
ISP_ADDRH = (uchar)(byte_addr >> 8);
ISP_ADDRL = (uchar)(byte_addr & 0x00ff);
ISP_CMD = ISP_CMD&0xf8;/* 1111,1000 */
ISP_CMD = ISP_CMD|READ_AP_and_Data_Memory_Command;/* 0000,0001 */
ISP_IAP_enable();
ISP_TRIG = 0x46;
ISP_TRIG = 0xb9;
_nop_();
ISP_IAP_disable();
return (ISP_DATA);
}
/* 扇区擦除*/
void sector_erase(uint sector_addr)
{
uint get_sector_addr=0;
get_sector_addr=(sector_addr & 0xfe00); /* 1111,1110,0000,0000; 取扇区地址*/ ISP_ADDRH = (uchar)(get_sector_addr >> 8);
ISP_ADDRL = 0x00;
ISP_CMD = ISP_CMD&0xf8;/* 1111,1000 */
ISP_CMD =
ISP_CMD|SECTOR_ERASE_AP_and_Data_Memory_Command;/* 0000,0011 */ ISP_IAP_enable();
ISP_TRIG = 0x46;/* 触发ISP_IAP命令*/
ISP_TRIG = 0xb9;/* 触发ISP_IAP命令*/
_nop_();
ISP_IAP_disable();
}
/* 字节编程*/
void byte_program(uint byte_addr, uchar original_data)
{
ISP_ADDRH = (uchar)(byte_addr >> 8);
ISP_ADDRL = (uchar)(byte_addr & 0x00ff);
ISP_CMD = ISP_CMD & 0xf8; /* 1111,1000 */
ISP_CMD = ISP_CMD |
PROGRAM_AP_and_Data_Memory_Command; /* 0000,0010 */
ISP_DATA = original_data;
ISP_IAP_enable();
ISP_TRIG = 0x46; /* 触发ISP_IAP命令*/
ISP_TRIG = 0xb9; /* 触发ISP_IAP命令*/
_nop_();
ISP_IAP_disable();
}
void delay1(uint counter)
{
uint temp=0;
for(temp=counter;temp>0;temp--)
{
_nop_();
_nop_();
_nop_();
}
}
Smg.h:
/****************************************************************************** ****
* 标题: 试验数码管上显示数字( 单片机直接实现位选共阴极) *
* 用573锁存器控制和单片机脚直接位选控制(非译码器控制)数码管*
******************************************************************************* ****/
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar code smg_duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //段码0-9.
uchar code smg_wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdF,0xbF,0x7F}; //位选控制查表的方法控制
void delay(uint i)
{
uchar j;
for(i;i>0;i--)
for(j=200;j>0;j--);
}
void display(uint dat)//数码管显示函数
{
uint i;
uint LedOut[10];
LedOut[0]=smg_duan[dat%10000/1000];//(若要显示小数点,则|0x80)
LedOut[1]=smg_duan[dat%1000/100];
LedOut[2]=smg_duan[dat%100/10];
LedOut[3]=smg_duan[dat%10];
for( i=0; i<4; i++)
{
P0=LedOut[i];
P2=smg_wei[i];//使用查表法进行位选
delay(10);//扫描间隔时间,数码管每位显示的时间,太长会数码管会有闪烁感}
}。

相关文档
最新文档