#include "..\include\main.h"
/**********************************************************************************************************/
//;-------NVMCON:FLASH:闪存存储器控制寄存器-------------------------------------------------------------------------------
//NVMCONbits.WR; //15,写控制位;1=启动闪存存储器编程或擦除操作,该操作是自定时的,一旦操作完成该位即由硬件清零;0=编程或擦除操作完成,并处于停止状态;
//NVMCONbits.WREN ; //14, 写使能位; 1=使能闪存编程/擦除操作; 0=禁止闪存编程/ 擦除操作
//NVMCONbits.WRERR; //13, 写序列错误标志位; 1=试图执行不合法的编程或擦除序列,或者发生终止(试图将WR位置1时自动置1该位); 0=编程或擦除操作正常完成;
//bit 12-7 未实现:读为0
//NVMCONbits.ERASE; //6, 擦除/编程使能位; 1=在下一条WR命令时执行NVMOP<3:0>指定的擦除操作; 0=在下一条WR命令时执行NVMOP<3:0>指定的编程操作;
//bit 5-4 未实现:读为0
//NVMCONbits.NVMOP<3:0>;//14, NVM 操作选择位(2);
//如果ERASE = 1: //1111 = 存储器批量擦除操作;//1110 = 保留;//1101 = 擦除通用段;//1100 = 擦除安全段;//1011 = 保留;
//0011 = 无操作;//0010 = 存储器页擦除操作;//0001 = 无操作;//0000 = 擦除单个配置寄存器字节;
//如果ERASE = 0: //1111 = 无操作;//1110 = 保留;//1101 = 无操作;//1100 = 无操作;//1011 = 保留;
//0011 = 存储器字编程操作;//0010 = 无操作;//0001 = 存储器行编程操作;//0000 = 编程单个配置寄存器字节;
/**********************************************************************************************************/
//1.RTSP 允许用户一次擦除由8 行数据(512 条指令)组成的程序存储器页,一次编程一行或一个字.
//2.用户可以一次对闪存存储器的一行进行编程。要实现该操作,首先需要擦除包含该行在内的一个8 行大小的页.
//3.dsPIC33F 闪存程序存储器被分段为页(512 个指令字)和行(64 个指令字)。
//4.注意:dsPIC33F 闪存程序存储器阵列是由64 条指令或192 字节的行组成的。RTSP 允许用户应用程序
// 一次擦除8 行(512 条指令)的块,一次编程64 条指令。8 行擦除块和单行写入块都是边沿对
// 齐的,从程序存储器起始地址开始,分别以1536=0x0600字节和192=0x00C0字节为边界。
/**********************************************************************************************************/
void PIC33_Flash_Erase(unsigned long add)//0.Flash擦除操作,一次擦除192*8=1536个字节的块或页。
{
feed_dog();
//WREN=1(使能闪存编程/擦除操作) & ERASE=1(在下一条WR命令时执行NVMOP<3:0>指定的擦除操作) & NVMOP=0b0010(存储器页擦除操作)
while(NVMCONbits.WR)//判断上个写周期是否完成?由写操作完成后硬件清零。写控制位。
continue;
NVMCON = 0x4042;
//注:高[23:16]位页地址:
TBLPAG = ((add>>16)&0xff);//将(页面边界)高8位地址写入程序存储地址的高8位TBLPAG(0x0032),初始化时页面边界寄存器
__builtin_tblwtl((add&0xffff),0xFF);//设置擦除程序存储单元页的基地址的<15:0>:低16位地址。
asm("DISI #0x3FFF"); //在k(最大2^14-1) 个指令周期内禁止中断
__builtin_write_NVM(); //解锁FLASH,并启动对闪存的写操作。相当于以下汇编指令:
while(NVMCONbits.WR); //判断写周期是否完成?
NVMCONbits.WREN=0; //写完后禁止闪存编程/ 擦除操作
asm("DISI #0X0000"); //重新使能中断
feed_dog();
}
//1.写入Flash,1个半字16位数据的数据。
void PIC33_Flash_WriteHalfWord(unsigned long add, unsigned int dat)
{
unsigned char i=0;
PIC33_Flash_Erase(add);//先擦除FLASH,全部置1
//装载写缓冲器
NVMCON = 0x4001; //WREN=1(使能闪存编程/擦除操作) & ERASE=0(在下一条WR命令时执行NVMOP<3:0>指定的编程操作) & NVMOP=0b0001(存储器行编程操作)
TBLPAG = ((add>>16)&0xff);//初始化页面边界
__builtin_tblwtl(((add&0xffff)+2*i), dat); // 写低字进缓冲区[15:0]
__builtin_tblwth(((add&0xffff)+2*i+1), 0x00);// 写高字(8位)[23:16]进缓冲区,强制为设置为0xFF 或0x00,为一条NOP 指令
asm("DISI #0x3FFF"); //在k(最大2^14-1) 个指令周期内禁止中断
__builtin_write_NVM(); //使能对闪存的写操作。
asm("DISI #0X0000"); //确保写FLASH期间禁止中断
}
//2.读取Flash,读取半个字16位数据。
unsigned int PIC33_Flash_ReadHalfWord(unsigned long add)
{
unsigned int rtemp=0;
TBLPAG = ((add>>16)&0xff);//初始化页面边界
rtemp=(__builtin_tblrdl(add&0xffff));
return rtemp;
}
//3.写Flash N(半字),一行64指令字,一个指令字24位宽=192Byte。
void PIC33_Flash_WriteHalfWordN(unsigned long add, unsigned int *fnt, unsigned char len)
{
unsigned char i;
PIC33_Flash_Erase(add);//先擦除FLASH,全部置1
//1.装载写缓冲器,注意存储地址是偶地址。
NVMCON = 0x4001; //WREN=1(使能闪存编程/擦除操作) & ERASE=0(在下一条WR命令时执行NVMOP<3:0>指定的编程操作) & NVMOP=0b0001(存储器行编程操作)
TBLPAG = (add>>16)&0xff;//初始化时页面边界寄存器
for(i=0; i
__builtin_tblwtl(((add&0xffff)+2*i), fnt[i]); //写低字进缓冲区[15:0]
__builtin_tblwth(((add&0xffff)+2*i+1), 0x00); //写高字(8位)[23:16]进缓冲区,强制为设置为0xFF 或0x00,为一条NOP 指令
}
asm("DISI #0x3FFF"); //在k(最大2^14-1) 个指令周期内禁止中断
__builtin_write_NVM(); //使能对闪存的写操作。
asm("DISI #0X0000"); //确保写FLASH期间禁止中断
}