jackliuwenli 发表于 2021-5-26 08:38 嗯 今天再倒腾倒腾,不行明天就换STC15F2K32S2了,我们以前的芯片是STM,现在太贵了。换芯从来了! |
![]() 建议先把例程跑通,多看官方操作 |
paladina 发表于 2021-5-25 21:26 我昨天折腾了一下午还是没整明白,地址从F000H开始也不成,不过仿真整出来了。一会儿发出来! |
IAP15没有EEPROM专用区,但可以把用户程序区的多余FLASH当做EEPROM用。下载程序前根据代码长度的下一个扇区,确定用作EEPROM的地址,以下图为例,EEPROM的首地址选0x0800,就不会发生擦除用户程序。![]() ![]() |
本帖最后由 bj1024 于 2021-5-25 16:50 编辑 #include "pbdata.h" #define CMD_IDLE 0 //空闲模式 #define CMD_READ 1 //IAP字节读命令 #define CMD_PROGRAM 2 //IAP字节编程命令 #define CMD_ERASE 3 //IAP扇区擦除命令 //extern uchar ADDR; //uint addr_s; //sfr IAP_ADDRH = 0xC3; //IAP地址寄存器高字节 sTC15f内有定义 //sfr IAP_ADDRL = 0xC4; //IAP地址寄存器低字节 //sfr IAP_CMD = 0xC5; //IAP命令寄存器 //sfr IAP_TRIG = 0xC6; //IAP命令触发寄存器 //sfr IAP_CONTR = 0xC7; //IAP控制寄存器 //根据不同的频率选择不同的等待时间 //#define ENABLE_IAP 0x80 //if SYSCLK<30MHz //#define ENABLE_IAP 0x81 //if SYSCLK<24MHz //#define ENABLE_IAP 0x82 //if SYSCLK<20MHz #define ENABLE_IAP 0x83 //if SYSCLK<12MHz //#define ENABLE_IAP 0x84 //if SYSCLK<6MHz //#define ENABLE_IAP 0x85 //if SYSCLK<3MHz //#define ENABLE_IAP 0x86 //if SYSCLK<2MHz //#define ENABLE_IAP 0x87 //if SYSCLK<1MHz /*---------------------------- IAP扇区擦除命令 ----------------------------*/ void eeprom_init(uint addr) //IAP扇区擦除命令 { IAP_CONTR= ENABLE_IAP; //使能IAP IAP_CMD= CMD_ERASE; //使能IAP命令 IAP_ADDRL= addr; //设置IAP低地址 IAP_ADDRH= addr >> 8; //设置IAP高地址 IAP_TRIG= 0x5a; //写触发命令0x5a IAP_TRIG= 0xa5; //写触发命令0xa5 _nop_(); //等待写ISP/IAP/EEPROM数据完成 eeprom_offiap(); //关闭IAP功能 } /*---------------------------- 关闭IAP ----------------------------*/ void eeprom_offiap(void) { IAP_CONTR = 0; //关闭IAP功能 IAP_CMD = 0; //清除命令寄存器 IAP_TRIG = 0; //清除触发寄存器 IAP_ADDRH = 0x80; //将地址设置到非IAP区域 IAP_ADDRL = 0; } /*---------------------------- 从ISP/IAP/EEPROM区域读取一字节 ----------------------------*/ uchar eeprom_read(uint addr) { uchar dat; //数据缓冲区 IAP_CONTR = ENABLE_IAP; //使能IAP IAP_CMD = CMD_READ; //设置IAP命令 IAP_ADDRL = addr; //设置IAP低地址 IAP_ADDRH = addr >> 8; //设置IAP高地址 IAP_TRIG = 0x5a; //写触发命令(0x5a) IAP_TRIG = 0xa5; //写触发命令(0xa5) _nop_(); //等待ISP/IAP/EEPROM操作完成 dat = IAP_DATA; //读ISP/IAP/EEPROM数据 eeprom_offiap(); //关闭IAP功能 return dat; //返回 } /*---------------------------- 从ISP/IAP/EEPROM区域写一字节 ----------------------------*/ void eeprom_writ(uchar addr,uchar dat) { IAP_CONTR= ENABLE_IAP; //使能IAP IAP_CMD= CMD_PROGRAM; //设置IAP命令 IAP_ADDRL= addr; //设置IAP低地址 IAP_ADDRH= addr >> 8; //设置IPA高地址 IAP_DATA= dat; //写ISP/IAP/EEPROM数据 IAP_TRIG= 0x5a; //写触发命令0x5a IAP_TRIG= 0xa5; //写触发命令0xa5 _nop_(); //等待写ISP/IAP/EEPROM数据完成 eeprom_offiap(); //关闭IAP功能 } |