- /***********************************************************************************
- * 函数名 :FLASH_WRITE_FUN
- * 函数功能:按块或按页写入数据到FLASH,个数参数只能为16,32 ,地址必须为块的首地址 如十六进制下结尾00 20 40 60 80 A0 C0 E0
- * 如果地址不是页的首地址,必须确定后续块结果为0xFFFF,或前面操作过块首写,使后续块值被0xFFFF,否则写结果异常。
- * 入口参数:待写地址,待写地址的数据
- * 返回 :无
- * 写时间说明:除去代码,以整页FLASH为例,操作完第一块需要6ms,另外3块需要3ms。即第一块执行整页的擦除后写自身块,其他块直接写。
- **********************************************************************************/
- void FLASH_WRITE_FUN(unsigned int address,unsigned char length)
- {
- #if 1 // 1时效率比0小 1 使用传递参数 0 按编译器全嵌汇编实现,但编译提示参数未使用,可以忽略
- //; 参数的使用
- NVMADDRH=(unsigned char) (address>>8);
- NVMADDRL=address;
- __asm
- ;//备份中断使能寄存器
- BANKSEL _INTCTL
- MOV R1,_INTCTL
- ;//关闭中断,操作不可打断
- CLR _INTCTL,_PUIE
- CLR _INTCTL,_AIE
- JNB _INTCTL,_AIE
- JMP $-2
- ;//时钟频率备份及降频操作,建议降频到1M,此时中断已被关
- MOV R0,#0x30
- MOV R2,_OSCCTL
- MOV _OSCCTL,R0
- ;//读取结果的存放起始RAM地址,即数组缓存区 FLASH_BUFFER[x]
- MOV R3,#_FLASH_BUFFER
- __endasm;
- while(length--) // 仅使用R0,不改变R1
- {
- __asm
- ;//加载待写数据
- BANKSEL _FLASH_BUFFER
- LD R6,[R3]
- INC R3
- LD R7,[R3]
- INC R3
- BANKSEL _NVMDATAH
- MOV _NVMDATAH,R7
- MOV _NVMDATAL,R6
- ;//硬件写
- MOV R5 ,#0x84
- MOV _NVMCTL0,R5
- MOV R5,#0x69
- MOV _NVMCTL1,R5
- MOV R5,#0x96
- MOV _NVMCTL1,R5
- SET _NVMCTL0 , 1 ;// 写存在高压,高压还原添加空指令确保后续运行正常
- NOPZ
- NOPZ
- NOPZ
- NOPZ
- NOPZ
- NOPZ ;// 建议10条,至少2条
- NOPZ
- NOPZ
- NOPZ
- NOPZ
- MOV R5,#0X80
- MOV _NVMCTL0,R5
- ;//指向下一操作地址,这里不考虑高位,特性要求只能操作一页内的数据,不能跨页
- BANKSEL _NVMADDRL
- INC _NVMADDRL
- __endasm;
- }
- __asm
- ;//时钟与中断使能的还原
- BANKSEL _OSCCTL
- MOV _OSCCTL,R2
- AND R1,#0xC0 ;//中断使能仅关系高2位
- ORL _INTCTL,R1
- __endasm;
- #else
- // 参数1的传递使用 编译器自动变量 STK00 和 R0 ,其中R0为高位
- // 参数2的传递使用 编译器自动变量 STK01
- // 整体实现的嵌汇编会提示参数未被使用,可以忽略
- __asm
- ;//传递操作的地址(块首)
- BANKSEL _NVMADDRH
- MOV _NVMADDRH,R0
- BANKSEL STK00
- MOV R0,STK00
- BANKSEL _NVMADDRL
- MOV _NVMADDRL,R0
- ;//备份中断使能寄存器
- BANKSEL _INTCTL
- MOV R1,_INTCTL
- ;//关闭中断,操作不可打断
- CLR _INTCTL,_PUIE
- CLR _INTCTL,_AIE
- JNB _INTCTL,_AIE
- JMP $-2
- ;//时钟频率备份及降频操作,建议降频到1M,此时中断已被关
- MOV R0,#0x30
- MOV R2,_OSCCTL
- MOV _OSCCTL,R0
- ;//待写数据的存放起始RAM地址,即数组缓存区 FLASH_BUFFER[x]
- MOV R0,#_FLASH_BUFFER
- FALSH_WRITE_PAGE_LOOP:
- ;//加载待写数据
- BANKSEL _FLASH_BUFFER
- LD R6,[R0]
- INC R0
- LD R7,[R0]
- INC R0
- BANKSEL _NVMDATAH
- MOV _NVMDATAH,R7
- MOV _NVMDATAL,R6
- ;//硬件写
- MOV R5 ,#0x84
- MOV _NVMCTL0,R5
- MOV R5,#0x69
- MOV _NVMCTL1,R5
- MOV R5,#0x96
- MOV _NVMCTL1,R5
- SET _NVMCTL0 , 1 ;// 写存在高压,高压还原添加空指令确保后续运行正常
- NOPZ
- NOPZ
- NOPZ
- NOPZ
- NOPZ
- NOPZ ;// 建议10条,至少2条
- NOPZ
- NOPZ
- NOPZ
- NOPZ
- MOV R5,#0X80
- MOV _NVMCTL0,R5
- ;//指向下一操作地址,这里不考虑高位,特性要求只能操作一页内的数据,不能跨页
- BANKSEL _NVMADDRL
- INC _NVMADDRL
- BANKSEL STK01
- DECJZ STK01
- JMP FALSH_WRITE_PAGE_LOOP
- ;//时钟与中断使能的还原
- BANKSEL _OSCCTL
- MOV _OSCCTL,R2
- AND R1,#0xC0 ;//中断使能仅关系高2位
- ORL _INTCTL,R1
- __endasm;
- #endif
- }