/***********************************************************************************
* 函数名 :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
}