#include"include.h"

unsigned char	DATA_EE_BUFFER[DATA_EE_BUFFER_MAX];


/****************************************************************************************
 * 函数名     ：DATA_EE_READ_ONE
 * 函数功能：读取EE中指定地址数据，并返回
 * 入口参数：待读地址
 * 返回          ：待读数据
****************************************************************************************/
uchar DATA_EE_READ_ONE(unsigned char address)
{
	NVMADDRL=(unsigned char)address;
	__asm;
	MOV R0,#0X01
	MOV NVMCTL0,R0
	NOPZ
	NOPZ
	NOPZ
	NOPZ
	NOPZ
	__endasm;
	return 	NVMDATAL;
}
/****************************************************************************************
 * 函数名     ：DATA_EE_WRITE_ONE
 * 函数功能：将值写入EE中指定地址，等待EE写入完成后退出
 * 入口参数：待写地址，待写数据
 * 返回          ：无
****************************************************************************************/
void DATA_EE_WRITE_ONE(unsigned char address,unsigned char value)
{
#if 1  	   //  1时效率比0小   1 使用传递参数   0 按编译器全嵌汇编实现，但编译提示参数未使用，可以忽略
	//; 参数的使用
	NVMADDRL=address;
	NVMDATAL=value;
#else
	//; 参数的使用 第一个参数位于R0中，第二个参数位于自动变量STK00 中
	__asm
	BANKSEL STK00
	MOV R1,STK00
	BANKSEL _NVMADDRL
	MOV _NVMADDRL,R0
	BANKSEL _NVMDATAL
	MOV _NVMDATAL,R1
	__endasm;
#endif

	__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
	;//硬件写
		MOV 	R5 ,#0x04
		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,#0X00
		MOV 	_NVMCTL0,R5
	;//等待写完成
		JB _EIF1,7
		JMP $-1
		CLR _EIF1,7
	;//时钟与中断使能的还原
		MOV		_OSCCTL,R2
		AND 	R1,#0xC0	;//中断使能仅关系高2位
		ORL 	_INTCTL,R1
	__endasm;
}

/****************************************************************************************
 * 函数名     ：DATA_EE_READ_FUN
 * 函数功能：以设定地址开始，读取一定个数的DATA_EE数据放置到数值DATA_EE_BUFFER[x]中
 * 入口参数：起始地址，操作个数，过程关闭中断；
 * 返回          ：读出数据位于DATA_EE_BUFFER[]中
****************************************************************************************/
void DATA_EE_READ_FUN(unsigned char address,unsigned char length)
{
#if 1  	   //  1时效率比0小   1 使用传递参数   0 按编译器全嵌汇编实现，但编译提示参数未使用，可以忽略
	//; 参数的使用
	NVMADDRL=address;

	__asm
	;//备份中断使能寄存器
		BANKSEL _INTCTL
		MOV		R1,_INTCTL
	;//关闭中断，操作不可打断
		CLR		_INTCTL,_AIE
		JNB		_INTCTL,_AIE
		JMP		$-2
	;//时钟频率备份及降频操作,建议降频到1M,此时中断已被关
		MOV		R0,#0x30
		MOV		R2,_OSCCTL
		MOV		_OSCCTL,R0
	;//读取结果的存放起始RAM地址，即数组缓存区  DATA_EE_BUFFER[x]
		MOV		R3,#_DATA_EE_BUFFER
	__endasm;

	while(length--)	// 仅使用R0，不改变R1
	{
		__asm
		;//硬件读
		BANKSEL _NVMCTL0
		MOV 	R5,#0x01
		MOV 	_NVMCTL0,R5
		NOPZ
		NOPZ
		NOPZ
		NOPZ
		;//读结果处理
		BANKSEL	_NVMDATAL
		MOV	R6,_NVMDATAL

		BANKSEL _DATA_EE_BUFFER
		ST		[R3],R6
		INC		R3
		;//指向下一操作地址
		BANKSEL _NVMADDRL
		INC		_NVMADDRL
		__endasm;
	}

	__asm
		;//时钟与中断使能的还原
		BANKSEL _OSCCTL
		MOV		_OSCCTL,R2
		AND 	R1,#0xC0	;//中断使能仅关系高2位
		ORL 	_INTCTL,R1
	__endasm;
#else
	// 参数1的传递使用  编译器自动变量 R0
	// 参数2的传递使用  编译器自动变量 STK00
	// 整体实现的嵌汇编会提示参数未被使用，可以忽略
__asm
	;//传递操作地址
	BANKSEL _NVMADDRL
	MOV		_NVMADDRL,R0
	;//备份中断使能寄存器
	BANKSEL _INTCTL
	MOV		R1,_INTCTL
	;//关闭中断，操作不可打断
	CLR		_INTCTL,_AIE
	JNB		_INTCTL,_AIE
	JMP		$-2
	;//时钟频率备份及降频操作,建议降频到1M,此时中断已被关
	MOV		R0,#0x30
	MOV		R2,_OSCCTL
	MOV		_OSCCTL,R0
	;//读取结果的存放起始RAM地址，即数组缓存区  DATA_EE_BUFFER[x]
	MOV		R0,#_DATA_EE_BUFFER

DATA_EE_READ_FUN_LOOP:
	;//硬件读
	BANKSEL _NVMCTL0
	MOV 	R5,#0x01
	MOV 	_NVMCTL0,R5
	NOPZ
	NOPZ
	NOPZ
	NOPZ
	;//读结果处理
	BANKSEL	_NVMDATAL
	MOV	R6,_NVMDATAL

	BANKSEL _DATA_EE_BUFFER
	ST		[R0],R6
	INC		R0

	;//指向下一操作地址，建议每次操作内容在一个块中，此时不需要处理_BADDRL进位的_BADDRH+1操作
	BANKSEL _NVMADDRL
	INC		_NVMADDRL
	;//读数量的判断
	BANKSEL STK00
	DECJZ	STK00
	JMP		DATA_EE_READ_FUN_LOOP

	;//时钟与中断使能的还原
	BANKSEL _OSCCTL
	MOV		_OSCCTL,R2
	AND 	R1,#0xC0	;//中断使能仅关系高2位
	ORL 	_INTCTL,R1
__endasm;
#endif
}
/****************************************************************************************
 * 函数名     ：DATA_EE_WRITE_FUN
 * 函数功能：将DATA_EE_BUFFER缓存区中的数据写入
 * 入口参数：待写地址，待写数据
 * 返回          ：无
****************************************************************************************/
void DATA_EE_WRITE_FUN(unsigned char address,unsigned char length)
{
#if 1  	   //  1时效率比0小   1 使用传递参数   0 按编译器全嵌汇编实现，但编译提示参数未使用，可以忽略
	//; 参数的使用
	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地址，即数组缓存区  DATA_EE_BUFFER[x]
		MOV		R3,#_DATA_EE_BUFFER
	__endasm;

	while(length--)		// 仅使用R0，不改变R1
	{
		__asm

		;//加载待写数据
		BANKSEL _DATA_EE_BUFFER
		LD		R6,[R3]
		INC		R3

		BANKSEL _NVMDATAL
		MOV _NVMDATAL,R6
		;//硬件写
		MOV 	R5 ,#0x04
		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,#0X00
		MOV 	_NVMCTL0,R5

		;//等待中断标志的写完成
		JB _EIF1,7
		JMP $-1
		CLR _EIF1,7
		;//指向下一操作地址，这里不考虑高位，特性要求只能操作一页内的数据，不能跨页
		BANKSEL _NVMADDRL
		INC		_NVMADDRL
		__endasm;
	}

	__asm
		;//时钟与中断使能的还原
		BANKSEL _OSCCTL
		MOV		_OSCCTL,R2
		AND 	R1,#0xC0	;//中断使能仅关系高2位
		ORL 	_INTCTL,R1
	__endasm;
#else
	// 参数1的传递使用  编译器自动变量 R0
	// 参数2的传递使用  编译器自动变量 STK00
	// 整体实现的嵌汇编会提示参数未被使用，可以忽略
__asm
	;//传递操作的地址
	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地址，即数组缓存区  DATA_EE_BUFFER[x]
	MOV		R0,#_DATA_EE_BUFFER

FALSH_WRITE_PAGE_LOOP:
	;//加载待写数据
	BANKSEL _DATA_EE_BUFFER
	LD		R6,[R0]
	INC		R0

	BANKSEL _NVMDATAL
	MOV _NVMDATAL,R6

	;//硬件写
	MOV 	R5 ,#0x04
	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条
	NOPZ
	NOPZ
	NOPZ
	NOPZ
	MOV 	R5,#0X00
	MOV 	_NVMCTL0,R5
	;//等待写完成的标志
	JB _EIF1,7
	JMP $-1
	CLR _EIF1,7

	;//指向下一操作地址，这里不考虑高位，特性要求只能操作一页内的数据，不能跨页
	BANKSEL _NVMADDRL
	INC		_NVMADDRL

	BANKSEL STK00
	DECJZ	STK00
	JMP		FALSH_WRITE_PAGE_LOOP

	;//时钟与中断使能的还原
	BANKSEL _OSCCTL
	MOV		_OSCCTL,R2
	AND 	R1,#0xC0	;//中断使能仅关系高2位
	ORL 	_INTCTL,R1
__endasm;
#endif
}
