关于断电延时和EEPROM数据保存(申酷!!)
EEPROM, 申酷, 数据, 延时, 断电
原来想用AD检测断电的,做出来测试几遍不行,听了各位的意见。
就花了一个下午完成用一个I/O断电检测电路。把法拉电容改小了,节约开支,一个2200uf的普通电容就足够了。经测试能正常保存数据到EEPROM。
电路见下面的图片链接。
该解决方案的程序:
#include #include #define uchar unsigned char #define uint unsigned int sbit p12 = P1^2; uchar i; void delay(uint z) //延时ms { uint x,y; for(x=112;x>0;x--) for(y=z;y>0;y--); } void init_232(void) //串口初始化 { SCON = 0x50; TMOD |= 0x20; TH1 = 0xfa; //波特率 9600 TL1 = 0xfa; PCON |= 0x80; EA = 1; ES = 1; TR1 = 1; } void send_char(uchar w) //串口发送一个字符 { SBUF = w; while(TI == 0); TI = 0; } void send_string(uchar *s,uint string_length) //串口发送一个字符串 { uint i = 0; do { send_char(*(s + i)); i++; } while(i < string_length); } /*EEPROM字符读取*/ uchar eeprom_read(uchar x,y) { ISP_ADDRH = x; ISP_ADDRL = y; ISP_CONTR = 0x9b; ISP_CMD = 0x01; ISP_TRIG = 0x46; ISP_TRIG = 0xb9; _nop_(); ISP_CONTR=0; ISP_CMD=0; ISP_TRIG=0; return(ISP_DATA); } /*EEPROM字符写入*/ void eeprom_write(uchar x,y,z) { ISP_DATA = z; ISP_ADDRH = x; ISP_ADDRL = y; ISP_CONTR = 0x9b; ISP_CMD = 0x02; ISP_TRIG = 0x46; ISP_TRIG = 0xb9; _nop_(); ISP_CONTR=0; ISP_CMD=0; ISP_TRIG=0; } /*EEPROM扇区擦除*/ void eeprom_erase(uchar x,y) { ISP_ADDRH = x; ISP_ADDRL = y; ISP_CONTR = 0x9b; ISP_CMD = 0x03; ISP_TRIG = 0x46; ISP_TRIG = 0xb9; _nop_(); ISP_CONTR=0; ISP_CMD=0; ISP_TRIG=0; } void main() { init_232(); i = 0; delay(10); while(1) { if((p12 == 0) && (i == 0)) { eeprom_erase(0x10,0x00); //擦除第一扇区 delay(1); eeprom_write(0x10,0x00,0x88); //在第一扇区写入88 delay(1); i = 1; } } } /*串口接收中断函数*/ void RS232() interrupt 4 { uchar ch = 0; if(RI) { ch = SBUF; RI = 0; send_char(ch); } switch(ch) { case 1: send_char(eeprom_read(0x10,0x00)); //串口助手输入16进制1,读EEPROM第一扇区 break; case 2: send_char(eeprom_read(0x12,0x00)); //串口助手输入16进制2,读EEPROM第2扇区 break; case 3: eeprom_write(0x10,0x00,0x55); //串口助手输入16进制3,写EEPROM第一扇区55 break; case 4: eeprom_write(0x12,0x00,0x66); //串口助手输入16进制4,写EEPROM第2扇区66 break; case 5: eeprom_erase(0x10,0x00); //串口助手输入16进制5,擦除EEPROM第一扇区 break; case 6: eeprom_erase(0x12,0x00); //串口助手输入16进制6,擦除EEPROM第2扇区 break; default: break; } } 这是一段stc单片机EEPROM掉电存储程序,麻烦大家帮我看看哈,怎么调用时输出有问题啊,希望给个调用的例子 悬赏分:0 - 提问时间2010-8-21 19:32 #include < reg52.h > #include < absacc.h > #include < intrins.h > #include \" ..\\h_files\\eeprom.h \" /**************************************************************************************************/ void isp_iap_enable ( void ) { EA = 0 ; /*关中断*/ ISP_CONTR = ISP_CONTR & 0x18 ; ISP_CONTR = ISP_CONTR | WAIT_TIME ; ISP_CONTR = ISP_CONTR | 0x80 ; /*ISPEN = 1*/ } /**************************************************************************************************/ void isp_iap_disable ( void ) { ISP_CONTR = ISP_CONTR & 0x7f ; /*ISPEN = 0*/ ISP_TRIG = 0x00 ; EA = 1 ; /*开中断*/ } /**************************************************************************************************/ void isp_iap_goon ( void ) { isp_iap_enable ( ) ; /*打开ISP,IAP功能*/ ISP_TRIG = 0x46 ; /*触发ISP,IAP命令字节1*/ ISP_TRIG = 0xb9 ; /*触发ISP,IAP命令字节2*/ _nop_ ( ) ; } /**************************************************************************************************/ UINT8 byte_read ( UINT16 byte_addr ) { ISP_ADDRH = ( UINT8 ) ( byte_addr >> 8 ) ; /*地址赋值*/ ISP_ADDRL = ( UINT8 ) ( byte_addr & 0x00ff ) ; ISP_COMD = ISP_COMD & 0xf8 ; /*清除低3位*/ ISP_COMD = ISP_COMD | RE_COMMAND ; /*写入读命令*/ isp_iap_goon ( ) ; /*触发执行*/ isp_iap_disable ( ) ; /*关闭ISP,IAP功能*/ return ( ISP_DATA ) ; /*返回读到的数据*/ } /**************************************************************************************************/ void sector_erase ( UINT16 sector_addr ) { UINT16 i_sector_addr ; i_sector_addr = ( sector_addr & 0xfe00 ) ; /*取扇区地址*/ ISP_ADDRH = ( UINT8 ) ( i_sector_addr >> 8 ) ; ISP_ADDRL = 0x00 ; ISP_COMD = ISP_COMD & 0xf8 ; /*清空低3位*/ ISP_COMD = ISP_COMD | ER_COMMAND ; /*擦除命令3*/ isp_iap_goon ( ) ; /*触发执行*/ isp_iap_disable ( ) ; /*关闭ISP,IAP功能*/ } /**************************************************************************************************/ void byte_write ( UINT16 byte_addr , UINT8 original_data ) { ISP_ADDRH = ( UINT8 ) ( byte_addr >> 8 ) ; /*取地址*/ ISP_ADDRL = ( UINT8 ) ( byte_addr & 0x00ff ) ; ISP_COMD = ISP_COMD & 0xf8 ; /*清空低3位*/ ISP_COMD = ISP_COMD | PR_COMMAND ; /*写命令2*/ ISP_DATA = original_data ; /*写入数据准备*/ isp_iap_goon ( ) ; /*触发执行*/ isp_iap_disable ( ) ; /*关闭ISP,IAP功能*/ } 提问者: smu_east - 一级 网友推荐答案 /************************************************************************************************************************************/ #include #include #include #include /******************************************************************************** ****************************************************/ #define Uchar unsigned char #define Uint unsigned int #define Ulong unsigned long //定义Flash 操作等待时间及允许IAP/ISP/EEPROM 操作的常数 #define ENABLE_ISP 0x83 //系统工作时钟<12MHz 时,对IAP_CONTR 寄存器设置此值 /************************************************************************************************************************************/ sfr IAP_DATA = 0xE2; sfr IAP_ADDRH = 0xE3; sfr IAP_ADDRL = 0xE4; sfr IAP_CMD = 0xE5; sfr IAP_TRIG = 0xE6; sfr IAP_CONTR = 0xE7; /************************************************************************************************************************************/ //全局变量及共用体变量 /************************************************************************************************************************************/ Uchar buff[8]; Uchar buff1[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; union union_temp16{ Uint un_temp16;Uchar un_temp8[2];}my_unTemp16;//定义共用体,给存储eeprom使用 /************************************************************************************************************************************/ //函数声明区 /************************************************************************************************************************************/ void Read_8byte(Uchar *buf,Uint add,Uchar bitt); //读多个字节,调用前需打开 IAP 功能 void Program_8byte(Uchar *buf,Uint add,Uchar bitt);//写多个字节,调用前需打开IAP 功能 void Sector_Erase(Uint add); //擦除扇区 void IAP_Disable(); //关闭IAP 功能 void Delay(); //延时函数 void mcu_ini(void);//mcu初始化函数 /************************************************************************************************************************************/ //主函数区 /************************************************************************************************************************************/ void main (void) { Uchar i; P1 = 0xF0; //演示程序开始,让 P1[3:0] 控制的灯亮 Delay(); //延时 P1 = 0x0F; //演示程序开始,让 P1[7:4] 控制的灯亮 Delay() ; //延时 Sector_Erase(0x4000); //擦除整个扇区 Program_8byte(buff1,0x4000,8); P2 = 0x55;//P2.7亮 Read_8byte(buff,0x4000,8); while (1)//CPU 在此无限循环执行此句 { P0 = ~buff[i]; Delay(); //延时 i++; if(i==8){i=0;P2 ^= 0xff;Delay();} //延时 } } /********************************************************************************************************************************/ //读一字节,调用前需打开IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节 /********************************************************************************************************************************/ Uchar Byte_Read(Uint add) { IAP_DATA = 0x00; IAP_CONTR = ENABLE_ISP; //打开IAP 功能, 设置Flash 操作等待时间 IAP_CMD = 0x01; //IAP/ISP/EEPROM 字节读命令 my_unTemp16.un_temp16 = add; IAP_ADDRH = my_unTemp16.un_temp8[0]; //设置目标单元地址的高8 位地址 IAP_ADDRL = my_unTemp16.un_temp8[1]; //设置目标单元地址的低8 位地址 //EA = 0; IAP_TRIG = 0x46; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此 IAP_TRIG = 0xB9; //送完A5h 后,ISP/IAP 命令立即被触发起动 _nop_(); //EA = 1; return (IAP_DATA); } /********************************************************************************************************************************/ //读多个字节,调用前需打开IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节 /********************************************************************************************************************************/ void Read_8byte(Uchar *buf,Uint add,Uchar bitt) { Uchar i; for (i=0;i buf[i]= Byte_Read(add+i); } IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态, //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关 } /******************************************************************************** ************************************************/ //字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据 /********************************************************************************************************************************/ void Byte_Program(Uint add, Uchar ch) { IAP_CONTR = ENABLE_ISP; //打开 IAP 功能, 设置Flash 操作等待时间 IAP_CMD = 0x02; //IAP/ISP/EEPROM 字节编程命令 my_unTemp16.un_temp16 = add; IAP_ADDRH = my_unTemp16.un_temp8[0]; //设置目标单元地址的高8 位地址 IAP_ADDRL = my_unTemp16.un_temp8[1]; //设置目标单元地址的低8 位地址 IAP_DATA = ch; //要编程的数据先送进IAP_DATA 寄存器 //EA = 0; IAP_TRIG = 0x46; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此 IAP_TRIG = 0xB9; //送完A5h 后,ISP/IAP 命令立即被触发起动 _nop_(); //EA = 1; } /********************************************************************************************************************************/ //多字节写入函数 /********************************************************************************************************************************/ void Program_8byte(Uchar *buf,Uint add,Uchar bitt) { Uchar i; for (i=0;i Byte_Program(add+i, buf[i]); } IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态, //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关 } /***************************************************************************************************************************************/ //扇区擦除, 入口:DPTR = 扇区地址 /***************************************************************************************************************************************/ void Sector_Erase(Uint add) { IAP_CONTR = ENABLE_ISP; //打开IAP 功能, 设置Flash 操作等待时间 IAP_CMD = 0x03; //IAP/ISP/EEPROM 扇区擦除命令 my_unTemp16.un_temp16 = add; IAP_ADDRH = my_unTemp16.un_temp8[0]; //设置目标单元地址的高8 位地址 IAP_ADDRL = my_unTemp16.un_temp8[1]; //设置目标单元地址的低8 位地址 //EA = 0; IAP_TRIG = 0x46; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此 IAP_TRIG = 0xB9; //送完A5h 后,ISP/IAP 命令立即被触发起动 _nop_(); //EA = 1; IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态, //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关 } /***************************************************************************************************************************************/ //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态, //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关 /***************************************************************************************************************************************/ void IAP_Disable() { IAP_CONTR = 0; //关闭IAP 功能 IAP_CMD = 0; //清命令寄存器,使命令寄存器无命令,此句可不用 IAP_TRIG = 0; //清命令触发寄存器,使命令触发寄存器无触发,此句可不用 IAP_ADDRH = 0; IAP_ADDRL = 0; } /***************************************************************************************************************************************/ //延时函数 /***************************************************************************************************************************************/ void Delay() { Uchar i; Uint d=100; while (d--) { i=255; while (i--); } } 你这个是STC系列的EPROM代码 要是STC12C系列就不一样了 回答者: yoya0303 - 八级 2010-8-24 20:06 这个是连续读写8个字节的程序 我调试过了,直接ctrl+c,ctrl+v,主程序调用就可以了 #define IAP_BYTE_READ 1 #define IAP_BYTE_WRITE 2 #define IAP_BYTE_ERASE 3 #define ENABLE_IAP 0x84 #define EEPROM_DATA_ADDR 0x00 UCHAR EEPROM_data[8]; UCHAR EEPROM_num; UCHAR EEPROM_addr; void read_EEPROM_DATA() { EEPROM_addr=25; for(EEPROM_num=0;EEPROM_num<8;EEPROM_num++) { IAP_ADDRH=0x00; IAP_ADDRL=EEPROM_addr; IAP_CONTR=ENABLE_IAP; IAP_CMD=IAP_BYTE_READ; IAP_TRIG=0x5a; IAP_TRIG=0xa5; nop(); EEPROM_data[EEPROM_num]=IAP_DATA; IAP_CONTR=0x00; IAP_CMD=0x00; EEPROM_addr++; } IAP_TRIG=0xff; IAP_ADDRH=0xff; IAP_ADDRL=0xff; } void write_EEPROM_DATA() { EEPROM_addr=25; for(EEPROM_num=0;EEPROM_num<8;EEPROM_num++) { IAP_DATA=EEPROM_data[EEPROM_num]; IAP_ADDRH=0x00; IAP_ADDRL=EEPROM_addr; IAP_CONTR=ENABLE_IAP; IAP_CMD=IAP_BYTE_WRITE; IAP_TRIG=0x5a; IAP_TRIG=0xa5; nop(); nop(); nop(); nop(); IAP_CONTR=0x00; IAP_CMD=0x00; EEPROM_addr++; Delay_10ms(); } IAP_TRIG=0x00; IAP_ADDRH=0xff; IAP_ADDRL=0xff; } 因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- yrrf.cn 版权所有 赣ICP备2024042794号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务