|
- .C
- #include "eeprom.h"
- #include "STC15Fxxxx.H"
- //========================================================================
- // 函数: void ISP_Disable(void)
- // 描述: 禁止访问ISP/IAP.
- // 参数: non.
- // 返回: non.
- // 版本: V1.0, 2022-05-28
- //========================================================================
- void DisableEEPROM(void)
- {
- ISP_CONTR = 0; //禁止ISP/IAP操作
- ISP_CMD = 0; //去除ISP/IAP命令
- ISP_TRIG = 0; //防止ISP/IAP命令误触发
-
- ISP_ADDRH = 0xff; //清0地址高字节
- ISP_ADDRL = 0xff; //清0地址低字节,指向非EEPROM区,防止误操作
- }
- //========================================================================
- // 函数: void EEPROM_read_n(u16 EE_address,u8 *DataAddress,u16 number)
- // 描述: 从指定EEPROM首地址读出n个字节放指定的缓冲.
- // 参数: EE_address: 读出EEPROM的首地址.
- // DataAddress: 读出数据放缓冲的首地址.
- // number: 读出的字节长度.
- // 返回: non.
- // 版本: V1.0, 2022-05-28
- //========================================================================
- void EEPROM_read_n(u16 EE_address,u8 *DataAddress,u16 number)
- {
- ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //设置等待时间,允许ISP/IAP操作,送一次就够
- ISP_READ(); //送字节读命令,命令不需改变时,不需重新送命令
-
- do
- {
- ISP_ADDRH = EE_address / 256; //送地址高字节(地址需要改变时才需重新送地址)
- ISP_ADDRL = EE_address % 256; //送地址低字节
- _ISP_TRIG(); //先送5AH,再送A5H到ISP/IAP触发寄存器,每次都需要如此
- //送完A5H后,ISP/IAP命令立即被触发启动
- //CPU等待IAP完成后,才会继续执行程序。
- _nop_();
-
- *DataAddress = ISP_DATA; //读出的数据送往
-
- EE_address++;
- DataAddress++;
- }while(--number);
-
-
- DisableEEPROM();
- }
- /******************** 扇区擦除函数 *****************/
- //========================================================================
- // 函数: void EEPROM_SectorErase(u16 EE_address)
- // 描述: 把指定地址的EEPROM扇区擦除.
- // 参数: EE_address: 要擦除的扇区EEPROM的地址.
- // 返回: non.
- // 版本: V1.0, 2022-05-28
- //========================================================================
- void EEPROM_SectorErase(u16 EE_address)
- {
- //只有扇区擦除,没有字节擦除,512字节/扇区。
- //扇区中任意一个字节地址都是扇区地址。
- ISP_ADDRH = EE_address / 256; //送扇区地址高字节(地址需要改变时才需重新送地址)
- ISP_ADDRL = EE_address % 256; //送扇区地址低字节
-
- ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //设置等待时间,允许ISP/IAP操作,送一次就够
-
- ISP_ERASE(); //送扇区擦除命令,命令不需改变时,不需重新送命令
-
- _ISP_TRIG(); //先送5AH,再送A5H到ISP/IAP触发寄存器,每次都需要如此
- //送完A5H后,ISP/IAP命令立即被触发启动
-
- _nop_();
-
- DisableEEPROM();
- }
- //========================================================================
- // 函数: void EEPROM_write_n(u16 EE_address,u8 *DataAddress,u16 number)
- // 描述: 把缓冲的n个字节写入指定首地址的EEPROM.
- // 参数: EE_address: 写入EEPROM的首地址.
- // DataAddress: 写入源数据的缓冲的首地址.
- // number: 写入的字节长度.
- // 返回: non.
- // 版本: V1.0, 2022-05-28
- //========================================================================
- void EEPROM_write_n(u16 EE_address,u8 *DataAddress,u16 number)
- {
- ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //设置等待时间,允许ISP/IAP操作,送一次就够
-
- ISP_WRITE(); //送字节写命令,命令不需改变时,不需重新送命令
-
- do
- {
- ISP_ADDRH = EE_address / 256; //送地址高字节(地址需要改变时才需重新送地址)
- ISP_ADDRL = EE_address % 256; //送地址低字节
-
- ISP_DATA = *DataAddress; //送数据到ISP_DATA,只有数据改变时才需重新送
-
- _ISP_TRIG(); //先送5AH,再送A5H到ISP/IAP触发寄存器,每次都需要如此
- //送完A5H后,ISP/IAP命令立即被触发启动
-
- _nop_();
-
- EE_address++;
- DataAddress++;
- }while(--number);
- DisableEEPROM();
- }
复制代码
STC芯片的IAP版本:IAP15F2K61S2
使用官方IAP示例代码测试,如代码所示:
IAP15F2K61S2据说整片Flash都可以模拟EEPROM,地址:0x0000-0xF3FF(测试时需要避开程序空间,测试读写地址:0xF200)使用官方IAP示例代码测试
测试:部分代码
unsigned char EPR1[20]={0x20,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
写:
EEPROM_SectorErase(0xF200); //擦除一个扇区
EEPROM_write_n(0xF200,EPR1,sizeof(EPR1)); //写
读:
EEPROM_read_n(0xF200,EPR1,sizeof(EPR1)); //读出n字节,存放在EPR1数组内
uartWrite(EPR1,sizeof(EPR1));//串口发送
测试结果如图:
问题:
1,代码是使用IAP读写官方Demo修改,有没有问题?
2,正常读出来的数据为0x20,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,但是芯片运行一段时间后,Flash好像无法通过IAP程序再次读写了,即读出来都是0x00,目测坏了,更换新的同型号芯片又没有问题了(代码均一致,只是换了新的芯片),但是或者有什么办法修复一下?还是代码哪里可以优化一下?又感觉没坏,因为程序还在正常运行,只是没办法通过IAP读写Flash,来模拟EEPROM了
PS:正常与非正常的芯片,代码运行均正常(因为串口发送0x15是用来测试IC的,由此得出芯片其实除了IAP,其他正常),读写次数最多也没超过100次,地址均为0xF200,且没有与程序区冲突,就坏了
没有遇到过类似无法IAP读写的问题,分享一下!
|
|