关于STC单片机EEPROM断电问题

2019-11-22 15:46发布

<font face="微软雅黑"><font style="font-size:18px">EEPROM用的也比较多了,之前写代码也是可以使用的,但是这次发现有些问题,写进数据后断电再上电读取正常数值,不做任何操作再断电再上电,读取就是FF,再断再上又正常。可能个人对STC的EEPROM了解的不够深刻,没完全摸清它的脾气……</font></font><br> <font color="#333333"><font face="微软雅黑"><font style="font-size:18px">芯片采用STC12C5A60S2,供电采用7.4直流锂电经过7805后供电,硬件上有滤波器件。先附上改动后代码&nbsp;&nbsp;(在我其他的代码里亲测可用)。</font></font></font><br><p><br></p><pre style="max-width: 100%;"><code class="cpp hljs" codemark="1"><span class="hljs-comment">//EEPROM.h----------------------------------------------------------------------</span> <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span></span> sfr IAP_DATA = <span class="hljs-number">0xC2</span>; <span class="hljs-comment">//IAP数据寄存器</span> sfr IAP_ADDRH = <span class="hljs-number">0xC3</span>; <span class="hljs-comment">//IAP地址寄存器高字节</span> sfr IAP_ADDRL = <span class="hljs-number">0xC4</span>; <span class="hljs-comment">//IAP地址寄存器低字节</span> sfr IAP_CMD = <span class="hljs-number">0xC5</span>; <span class="hljs-comment">//IAP命令寄存器</span> sfr IAP_TRIG = <span class="hljs-number">0xC6</span>; <span class="hljs-comment">//IAP命令触发寄存器</span> sfr IAP_CONTR = <span class="hljs-number">0xC7</span>; <span class="hljs-comment">//IAP控制寄存器</span> <span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> ENABLE_IAP 0x82 <span class="hljs-comment">//IF SYSCLK&lt;12MHz</span></span> <span class="hljs-comment">/*---------------------------- 关闭IAP ----------------------------*/</span> <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">IapIdle</span><span class="hljs-params">()</span> </span>{ IAP_CONTR = <span class="hljs-number">0</span>; <span class="hljs-comment">//关闭IAP功能</span> IAP_CMD = <span class="hljs-number">0</span>; <span class="hljs-comment">//清除命令寄存器</span> IAP_TRIG = <span class="hljs-number">0</span>; <span class="hljs-comment">//清除触发寄存器</span> IAP_ADDRH = <span class="hljs-number">0x80</span>; <span class="hljs-comment">//将地址设置到非IAP区域</span> IAP_ADDRL = <span class="hljs-number">0</span>; } <span class="hljs-comment">/*---------------------------- 从ISP/IAP/EEPROM区域读取一字节 ----------------------------*/</span> <span class="hljs-function"><span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> <span class="hljs-title">IapReadByte</span><span class="hljs-params">(<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span> addr)</span> </span>{ <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> datt; <span class="hljs-comment">//数据缓冲区</span> IAP_CONTR = ENABLE_IAP; <span class="hljs-comment">//使能IAP</span> IAP_CMD = <span class="hljs-number">1</span>; <span class="hljs-comment">//设置IAP命令</span> IAP_ADDRL = addr; <span class="hljs-comment">//设置IAP低地址</span> IAP_ADDRH = addr &gt;&gt; <span class="hljs-number">8</span>; <span class="hljs-comment">//设置IAP高地址</span> IAP_TRIG = <span class="hljs-number">0x5a</span>; <span class="hljs-comment">//写触发命令(0x5a)</span> IAP_TRIG = <span class="hljs-number">0xa5</span>; <span class="hljs-comment">//写触发命令(0xa5)</span> _nop_(); <span class="hljs-comment">//等待ISP/IAP/EEPROM操作完成</span> datt = IAP_DATA; <span class="hljs-comment">//读ISP/IAP/EEPROM数据</span> IapIdle(); <span class="hljs-comment">//关闭IAP功能</span> <span class="hljs-keyword">return</span> datt; <span class="hljs-comment">//返回</span> } <span class="hljs-comment">/*---------------------------- 写一字节数据到ISP/IAP/EEPROM区域 ----------------------------*/</span> <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">IapProgramByte</span><span class="hljs-params">(<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span> addr, <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> dat1)</span> </span>{ IAP_CONTR = ENABLE_IAP; <span class="hljs-comment">//使能IAP</span> IAP_CMD = <span class="hljs-number">2</span>; <span class="hljs-comment">//设置IAP命令</span> IAP_ADDRL = addr; <span class="hljs-comment">//设置IAP低地址</span> IAP_ADDRH = addr &gt;&gt; <span class="hljs-number">8</span>; <span class="hljs-comment">//设置IAP高地址</span> IAP_DATA = dat1; <span class="hljs-comment">//写ISP/IAP/EEPROM数据</span> IAP_TRIG = <span class="hljs-number">0x5a</span>; <span class="hljs-comment">//写触发命令(0x5a)</span> IAP_TRIG = <span class="hljs-number">0xa5</span>; <span class="hljs-comment">//写触发命令(0xa5)</span> _nop_(); <span class="hljs-comment">//等待ISP/IAP/EEPROM操作完成</span> IapIdle(); } <span class="hljs-comment">/*---------------------------- 扇区擦除 ----------------------------*/</span> <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">IapEraseSector</span><span class="hljs-params">(<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span> addr)</span> </span>{ IAP_CONTR = ENABLE_IAP; <span class="hljs-comment">//使能IAP</span> IAP_CMD = <span class="hljs-number">3</span>; <span class="hljs-comment">//设置IAP命令</span> IAP_ADDRL = addr; <span class="hljs-comment">//设置IAP低地址</span> IAP_ADDRH = addr &gt;&gt; <span class="hljs-number">8</span>; <span class="hljs-comment">//设置IAP高地址</span> IAP_TRIG = <span class="hljs-number">0x5a</span>; <span class="hljs-comment">//写触发命令(0x5a)</span> IAP_TRIG = <span class="hljs-number">0xa5</span>; <span class="hljs-comment">//写触发命令(0xa5)</span> _nop_(); <span class="hljs-comment">//等待ISP/IAP/EEPROM操作完成</span> IapIdle(); } <span class="hljs-comment">//main.c-----------------------------------------------------------------------</span> <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">Uart_SendData</span><span class="hljs-params">(uchar dat)</span><span class="hljs-comment">//发送一个Byte数据</span> </span>{ <span class="hljs-keyword">while</span> (uart_busy); uart_busy = <span class="hljs-number">1</span>; SBUF = dat; } <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">SendString</span><span class="hljs-params">(uchar ub,uchar uc,uchar ud)</span><span class="hljs-comment">//发送字符串</span> </span>{ uart_n4=(ub+uc+ud)%<span class="hljs-number">256</span>; _nop_();_nop_();_nop_(); Uart_SendData(<span class="hljs-number">0xEF</span>); Uart_SendData(ub); Uart_SendData(uc); Uart_SendData(ud); Uart_SendData(uart_n4); Uart_SendData(<span class="hljs-number">0xFE</span>); } <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{ nb1 = IapReadByte(<span class="hljs-number">0x0000</span>); SendString(nb1,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>); <span class="hljs-keyword">while</span>(<span class="hljs-number">1</span>) { <span class="hljs-keyword">if</span>(uart_bit==<span class="hljs-number">1</span>) { IapEraseSector(<span class="hljs-number">0x0000</span>);_nop_();_nop_();_nop_(); IapProgramByte(<span class="hljs-number">0x0000</span>,number);_nop_();_nop_(); nb1 = IapReadByte(<span class="hljs-number">0x0000</span>); SendString(nb1,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>); uart_bit=<span class="hljs-number">0</span>; } } }</code></pre><font face="微软雅黑"> <font style="font-size:18px">PS:已省略部分函数,比如delay();uart_init();void uart() interrupt 4;</font><br> </font><br> <p><br></p>
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
3条回答
wulinwl
2019-11-22 16:20
由于程序不完整,不能整体分析,单看main函数是有问题的。在主循环中只要满足if(uart_bit==1)条件,就擦除EEPROM并重写、读取、串口发送。有可能这个操作很频繁(片内EEPROM是有约10万次擦写寿命的),断电时正好在擦除中。所谓擦除就是整个扇区全部写0xff。所以上电后读取的是0xff。正确的做法是把变量number保存在缓存中,不会影响串口及时发送。利用外部中断做断电检测,当电源下降到某值触发外部中断,把缓存中的数据写入EEPROM。再次上电读取EEPROM就不会出错。 最佳答案

一周热门 更多>