/* extern void SectorErase(uint sector_addr); // 扇区擦除 extern uchar byte_read(uint byte_addr); // byte读 extern void byte_write(uint byte_addr, uchar original_data); // byte写 extern uchar byte_write_verify(uint byte_addr, uchar original_data);// byte写并校验 extern uchar ArrayWrite(uint begin_addr, uint len, uchar code *array); // byte数组写并校验 extern void ArrayRead(uint begin_addr, uchar len); // 读出, 保存在Ttotal[]中 */ #define RdCommand 0x01 #define PrgCommand 0x02 #define EraseCommand 0x03 #define Error 1 #define Ok 0 #define WaitTime 0x01 #define PerSector 512 unsigned char Ttotal[]; /* ================ 打开 ISP,IAP 功能 ================= */ void ISP_IAP_enable(void) { EA = 0; /* 关中断 */ ISP_CONTR = ISP_CONTR & 0x18; /* 0001,1000 */ ISP_CONTR = ISP_CONTR | WaitTime; /* 写入硬件延时 */ ISP_CONTR = ISP_CONTR | 0x80; /* ISPEN=1 */ } /* =============== 关闭 ISP,IAP 功能 ================== */ void ISP_IAP_disable(void) { ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */ ISP_TRIG = 0x00; EA = 1; /* 开中断 */ } /* ================ 公用的触发代码 ==================== */ void ISPgoon(void) { ISP_IAP_enable(); /* 打开 ISP,IAP 功能 */ ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */ ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */ _nop_(); } /* ==================== 字节读 ======================== */ unsigned char byte_read(unsigned int byte_addr) { ISP_ADDRH = (unsigned char)(byte_addr >> 8); /* 地址赋值 */ ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff); ISP_CMD = ISP_CMD & 0xf8; /* 清除低3位 */ ISP_CMD = ISP_CMD | RdCommand; /* 写入读命令 */ ISPgoon(); /* 触发执行 */ ISP_IAP_disable(); /* 关闭ISP,IAP功能 */ return (ISP_DATA); /* 返回读到的数据 */ } /* ================== 扇区擦除 ======================== */ void sectorerase(unsigned int sector_addr) { unsigned int iSectorAddr; iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */ ISP_ADDRH = (unsigned char)(iSectorAddr >> 8); ISP_ADDRL = 0x00; ISP_CMD = ISP_CMD & 0xf8; /* 清空低3位 */ ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3 */ ISPgoon(); /* 触发执行 */ ISP_IAP_disable(); /* 关闭ISP,IAP功能 */ } /* ==================== 字节写 ======================== */ void byte_write(unsigned int byte_addr, unsigned char original_data) { ISP_ADDRH = (unsigned char)(byte_addr >> 8); /* 取地址 */ ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff); ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */ ISP_CMD = ISP_CMD | PrgCommand; /* 写命令2 */ ISP_DATA = original_data; /* 写入数据准备 */ ISPgoon(); /* 触发执行 */ ISP_IAP_disable(); /* 关闭IAP功能 */ } /* =================== 字节写并校验 =================== */ unsigned char byte_write_verify(unsigned int byte_addr, unsigned char original_data) { ISP_ADDRH = (unsigned char)(byte_addr >> 8); /* 取地址 */ ISP_ADDRL = (unsigned char)(byte_addr & 0xff); ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */ ISP_CMD = ISP_CMD | PrgCommand; /* 写命令2 */ ISP_DATA = original_data; ISPgoon(); /* 触发执行 */ /* 开始读,没有在此重复给地址,地址不会被自动改变 */ ISP_DATA = 0x00; /* 清数据传递寄存器 */ ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */ ISP_CMD = ISP_CMD | RdCommand; /* 读命令1 */ ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */ ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */ _nop_(); /* 延时 */ ISP_IAP_disable(); /* 关闭IAP功能 */ if(ISP_DATA == original_data) /* 读写数据校验 */ return Ok; /* 返回校验结果 */ else return Error; } /* ===================== 数组写入 ===================== */ unsigned char arraywrite(unsigned int begin_addr, unsigned int len, unsigned char *array) { unsigned int i; unsigned int in_addr; /* 判是否是有效范围,此函数不允许跨扇区操作 */ if(len > PerSector) return Error; in_addr = begin_addr & 0x01ff; /* 扇区内偏移量 */ if((in_addr + len) > PerSector) return Error; in_addr = begin_addr; /* 逐个写入并校对 */ ISP_IAP_enable(); /* 打开IAP功能 */ for(i = 0; i< len; i++) { /* 写一个字节 */ ISP_ADDRH = (unsigned char)(in_addr >> 8); ISP_ADDRL = (unsigned char)(in_addr & 0x00ff); ISP_DATA = array[i]; /* 取数据 */ ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */ ISP_CMD = ISP_CMD | PrgCommand; /* 写命令2 */ ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */ ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */ _nop_(); /* 读回来 */ ISP_DATA = 0x00; ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */ ISP_CMD = ISP_CMD | RdCommand; /* 读命令1 */ ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */ ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */ _nop_(); /* 比较对错 */ if(ISP_DATA != array[i]) { ISP_IAP_disable(); return Error; } in_addr++; /* 指向下一个字节 */ } ISP_IAP_disable(); return Ok; } /* ========================= 扇区读出 ========================= */ /* 程序对地址没有作有效性判断,请调用方事先保证他在规定范围内 */ void arrayread(unsigned int begin_addr, unsigned char len) { // unsigned char xdata data_buffer[]; /* 整个扇区读取缓存区 */ unsigned int iSectorAddr; unsigned int i; iSectorAddr = begin_addr; // & 0xfe00; /* 取扇区地址 */ ISP_IAP_enable(); for(i = 0; i < len; i++) { ISP_ADDRH = (unsigned char)(iSectorAddr >> 8); ISP_ADDRL = (unsigned char)(iSectorAddr & 0x00ff); ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */ ISP_CMD = ISP_CMD | RdCommand; /* 读命令1 */ ISP_DATA = 0; ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */ ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */ _nop_(); Ttotal[i] = ISP_DATA; iSectorAddr++; } ISP_IAP_disable(); /* 关闭IAP功能 */ }