完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
EEPROM用的也比较多了,之前写代码也是可以使用的,但是这次发现有些问题,写进数据后断电再上电读取正常数值,不做任何操作再断电再上电,读取就是FF,再断再上又正常。可能个人对STC的EEPROM了解的不够深刻,没完全摸清它的脾气……
芯片采用STC12C5A60S2,供电采用7.4直流锂电经过7805后供电,硬件上有滤波器件。先附上改动后代码 (在我其他的代码里亲测可用)。 //EEPROM.h---------------------------------------------------------------------- #include sfr IAP_DATA = 0xC2; //IAP数据寄存器 sfr IAP_ADDRH = 0xC3; //IAP地址寄存器高字节 sfr IAP_ADDRL = 0xC4; //IAP地址寄存器低字节 sfr IAP_CMD = 0xC5; //IAP命令寄存器 sfr IAP_TRIG = 0xC6; //IAP命令触发寄存器 sfr IAP_CONTR = 0xC7; //IAP控制寄存器 #define ENABLE_IAP 0x82 //if SYSCLK<12MHz /*---------------------------- 关闭IAP ----------------------------*/ void IapIdle() { IAP_CONTR = 0; //关闭IAP功能 IAP_CMD = 0; //清除命令寄存器 IAP_TRIG = 0; //清除触发寄存器 IAP_ADDRH = 0x80; //将地址设置到非IAP区域 IAP_ADDRL = 0; } /*---------------------------- 从ISP/IAP/EEPROM区域读取一字节 ----------------------------*/ unsigned char IapReadByte(unsigned int addr) { unsigned char datt; //数据缓冲区 IAP_CONTR = ENABLE_IAP; //使能IAP IAP_CMD = 1; //设置IAP命令 IAP_ADDRL = addr; //设置IAP低地址 IAP_ADDRH = addr >> 8; //设置IAP高地址 IAP_TRIG = 0x5a; //写触发命令(0x5a) IAP_TRIG = 0xa5; //写触发命令(0xa5) _nop_(); //等待ISP/IAP/EEPROM操作完成 datt = IAP_DATA; //读ISP/IAP/EEPROM数据 IapIdle(); //关闭IAP功能 return datt; //返回 } /*---------------------------- 写一字节数据到ISP/IAP/EEPROM区域 ----------------------------*/ void IapProgramByte(unsigned int addr, unsigned char dat1) { IAP_CONTR = ENABLE_IAP; //使能IAP IAP_CMD = 2; //设置IAP命令 IAP_ADDRL = addr; //设置IAP低地址 IAP_ADDRH = addr >> 8; //设置IAP高地址 IAP_DATA = dat1; //写ISP/IAP/EEPROM数据 IAP_TRIG = 0x5a; //写触发命令(0x5a) IAP_TRIG = 0xa5; //写触发命令(0xa5) _nop_(); //等待ISP/IAP/EEPROM操作完成 IapIdle(); } /*---------------------------- 扇区擦除 ----------------------------*/ void IapEraseSector(unsigned int addr) { IAP_CONTR = ENABLE_IAP; //使能IAP IAP_CMD = 3; //设置IAP命令 IAP_ADDRL = addr; //设置IAP低地址 IAP_ADDRH = addr >> 8; //设置IAP高地址 IAP_TRIG = 0x5a; //写触发命令(0x5a) IAP_TRIG = 0xa5; //写触发命令(0xa5) _nop_(); //等待ISP/IAP/EEPROM操作完成 IapIdle(); } //main.c----------------------------------------------------------------------- void Uart_SendData(uchar dat)//发送一个Byte数据 { while (uart_busy); uart_busy = 1; SBUF = dat; } void SendString(uchar ub,uchar uc,uchar ud)//发送字符串 { uart_n4=(ub+uc+ud)%256; _nop_();_nop_();_nop_(); Uart_SendData(0xEF); Uart_SendData(ub); Uart_SendData(uc); Uart_SendData(ud); Uart_SendData(uart_n4); Uart_SendData(0xFE); } void main() { nb1 = IapReadByte(0x0000); SendString(nb1,0,0); while(1) { if(uart_bit==1) { IapEraseSector(0x0000);_nop_();_nop_();_nop_(); IapProgramByte(0x0000,number);_nop_();_nop_(); nb1 = IapReadByte(0x0000); SendString(nb1,0,0); uart_bit=0; } } } PS:已省略部分函数,比如delay();uart_init();void uart() interrupt 4; |
|
相关推荐
3个回答
|
|
由于程序不完整,不能整体分析,单看main函数是有问题的。在主循环中只要满足if(uart_bit==1)条件,就擦除EEPROM并重写、读取、串口发送。有可能这个操作很频繁(片内EEPROM是有约10万次擦写寿命的),断电时正好在擦除中。所谓擦除就是整个扇区全部写0xff。所以上电后读取的是0xff。正确的做法是把变量number保存在缓存中,不会影响串口及时发送。利用外部中断做断电检测,当电源下降到某值触发外部中断,把缓存中的数据写入EEPROM。再次上电读取EEPROM就不会出错。
最佳答案
|
|
1 条评论
|
|
坐等大神解答
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
《DNESP32S3使用指南-IDF版_V1.6》第三十五章 摄像头实验
632 浏览 0 评论
《DNESP32S3使用指南-IDF版_V1.6》第三十章 DHT11数字温湿度传感器
671 浏览 0 评论
772 浏览 0 评论
【敏矽微ME32G070开发板免费体验】之原厂2812测试例程解析
1340 浏览 0 评论
1166 浏览 2 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
12057 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-28 19:23 , Processed in 0.580396 second(s), Total 50, Slave 43 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号