本帖最后由 Antecer 于 2023-7-10 14:28 编辑
都在这里了:
<font size="2">/*PIC16F1455 Program Flash Memory 读写库函数*/
#include <pic.h>
#include "Flash.h"
#define FLASHSPACE 0x2000 //单片机的FlashROM大小
#define ROWLENGTH 32 //Flash的擦写块大小
/*************************************************
* 功能:单字读取函数
* 说明: 按字读取闪存(读取1个16位数据)
* 参数: FlashAddr 需要读取的字的地址
* 返回: PMDAT 读取到的数据
*************************************************/
UINT16 FlashReadWord(UINT16 FlashAddr)
{
if(FlashAddr >= FLASHSPACE) return 0;
PMCON1bits.CFGS=0;
PMADR = FlashAddr;
PMCON1bits.RD=1;
NOP();
NOP();
return PMDAT;
}
/**************************************************
* 功能:多字读取函数
* 说明: 从FLASH中读取多个字到指定数组
* 参数: FlashAddr 要读取的起始地址
* *DataStr 指向存储数组的指针
* Length 需要读取的内容长度
* 返回: 无
**************************************************/
void FlashReadWords(UINT16 FlashAddr , UINT16 *DataStr,UINT8 Length)
{
for(UINT8 i=0;i<Length;i++)
{
DataStr[i]=FlashReadWord(FlashAddr);
FlashAddr++;
}
}
/**************************************************
* 功能:Bytes读取函数(取程序存储器低8位)
* 说明: 从FLASH中读取多个UINT8数据到指定数组
* 参数: FlashAddr 要读取的起始地址
* *DataStr 指向存储数组的指针
* Length 需要读取的内容长度
* 返回: 无
**************************************************/
void FlashReadBytes(UINT16 FlashAddr , UINT8 *DataStr,UINT8 Length)
{
for(UINT8 i=0;i<Length;i++)
{
DataStr[i] = 0xff & FlashReadWord(FlashAddr);
FlashAddr++;
}
}
/***************************************************
* 功能:FLASH解锁函数
* 说明: FLASH只有在解锁后才能执块擦除和写入操作
* 参数: 无
* 返回: 无
***************************************************/
void FlashUnlock(void)
{
PMCON2=0x55;
PMCON2=0xAA;
PMCON1bits.WR=1;
NOP();
NOP();
}
/***************************************************
* 功能:FLASH按块擦除函数(只能整块擦除ROWLENGTHByte)
* 说明: Flash块擦除(0x0000~0x001F/0x0010~0x002F/..)
* 参数: FlashAddr 被擦除块的首地址
* 返回: 无
***************************************************/
void FlashErase(UINT16 FlashAddr)
{
INTCONbits.GIE=0;
PMCON1bits.CFGS=0;
PMADR = FlashAddr & 0x7fff;
PMCON1bits.FREE=1;
PMCON1bits.WREN=1;
FlashUnlock();
PMCON1bits.WREN=0;
INTCONbits.GIE=1;
}
/***************************************************
* 功能:FLASH按块写数据函数
* 说明:FLASH块写入(块长度为32)
* 参数:FlashAddr 块首地址
* *DataStr 数组指针(单个数据不得大于0x3fff)
* Length 要写的数据长度(不能超过 ROWLENGTH 个)
* 返回:无
* 重要:按块写入数据不能跨越某些边界(0x0100/0x0200/..)
***************************************************/
void FlashWriteRow(UINT16 FlashAddr,UINT16 *DataStr,UINT8 Length)//必须块地址
{
UINT8 i=0;
INTCONbits.GIE=0;
PMADR = FlashAddr & 0x7fff;
PMCON1bits.FREE=0;
PMCON1bits.CFGS=0;
PMCON1bits.WREN=1;
PMCON1bits.LWLO=1;
while(1)
{
PMDAT = 0x3fff & DataStr[i];
i++;
if(i>=Length) break;
FlashUnlock();
PMADRL++;//锁存器地址+1
}
PMCON1bits.LWLO=0;
FlashUnlock();
PMCON1bits.WREN=0;
INTCONbits.GIE=1;
}
/***************************************************
* 功能:FLASH按字写函数(写入一个UINT16数据)
* 说明: 任意地址任意字,只写该字,自动原数据重写
* 参数: FlashAddr 写入地址
* data 写入的内容
* 返回: 无
***************************************************/
void FlashWriteWord(UINT16 FlashAddr,UINT16 data)
{
UINT16 tmpdata[ROWLENGTH];
UINT16 rowFlashAddr = FlashAddr & 0xfff0;
UINT8 wordFlashAddr=FlashAddr & 0x000f;
if((rowFlashAddr%0x20) > 0) //写入地址块对齐
{
rowFlashAddr = rowFlashAddr - 0x10;
wordFlashAddr = wordFlashAddr + 0x10;
}
FlashReadWords(rowFlashAddr,tmpdata,ROWLENGTH); //整块读出数据
tmpdata[wordFlashAddr] = data; //要写入的数据
FlashErase(rowFlashAddr); //擦除整块
FlashWriteRow(rowFlashAddr,tmpdata,ROWLENGTH); //整块写入数据
}
/***************************************************
* 功能:FLASH按Byte写函数(写入程序存储器低8位)
* 说明: 任意地址任意Byte,只写该Byte,自动原数据重写
* 参数: FlashAddr 写入地址
* data 写入的内容
* 返回: 无
***************************************************/
void FlashWriteByte(UINT16 FlashAddr,UINT8 data)
{
UINT16 tmpdata[ROWLENGTH];
UINT16 rowFlashAddr = FlashAddr & 0xfff0;
UINT8 wordFlashAddr=FlashAddr & 0x000f;
if((rowFlashAddr%0x20) > 0) //写入地址块对齐
{
rowFlashAddr = rowFlashAddr - 0x10;
wordFlashAddr = wordFlashAddr + 0x10;
}
FlashReadWords(rowFlashAddr,tmpdata,ROWLENGTH); //整块读出数据
tmpdata[wordFlashAddr] = tmpdata[wordFlashAddr]&0xff00|data;//要写入的数据
FlashErase(rowFlashAddr); //擦除整块
FlashWriteRow(rowFlashAddr,tmpdata,ROWLENGTH); //整块写入数据
}
/***************************************************
* 功能:FLASH写任意长度UINT16函数
* 说明:在任意地址写入任意长度的数据
* 参数:FlashAddr 要写入内容的首地址
* *DataStr 要写入的数组指针
* Length 要写入的数组长度
* 返回:无
***************************************************/
void FlashWriteWords(UINT16 FlashAddr , UINT16 *DataStr,UINT8 Length)
{
UINT16 tmpdata[ROWLENGTH];
UINT8 tmpLength = 0;
UINT16 rowFlashAddr = FlashAddr & 0xfff0;
UINT8 wordFlashAddr=FlashAddr & 0x000f;
if((rowFlashAddr%0x20) > 0) //写入地址块对齐
{
rowFlashAddr = rowFlashAddr - 0x10;
wordFlashAddr = wordFlashAddr + 0x10;
}
while(1)
{
FlashReadWords(rowFlashAddr,tmpdata,ROWLENGTH); //整块读出数据
for(unsigned i=0;i<ROWLENGTH;i++)
{
if(i>=wordFlashAddr)
{
tmpdata[i] = DataStr[tmpLength]; //要写入的数据
tmpLength++;
}
if(tmpLength>=Length) break;
}
FlashErase(rowFlashAddr); //擦除整块
FlashWriteRow(rowFlashAddr,tmpdata,ROWLENGTH); //整块写入数据
rowFlashAddr = rowFlashAddr + 0x20; //块地址+1
wordFlashAddr= 0;
if(tmpLength>=Length) break;
}
}
/***************************************************
* 功能:FLASH写任意长度UINT8函数(写入程序存储器低8位)
* 说明:在任意地址写入任意长度的数据
* 参数:FlashAddr 要写入内容的首地址
* *DataStr 要写入的数组指针
* Length 要写入的数组长度
* 返回:无
***************************************************/
void FlashWriteBytes(UINT16 FlashAddr , UINT8 *DataStr,UINT8 Length)
{
UINT16 tmpdata[ROWLENGTH];
UINT8 tmpLength = 0;
UINT16 rowFlashAddr = FlashAddr & 0xfff0;
UINT8 wordFlashAddr=FlashAddr & 0x000f;
if((rowFlashAddr%0x20) > 0) //写入地址块对齐
{
rowFlashAddr = rowFlashAddr - 0x10;
wordFlashAddr = wordFlashAddr + 0x10;
}
while(1)
{
FlashReadWords(rowFlashAddr,tmpdata,ROWLENGTH); //整块读出数据
for(unsigned i=0;i<ROWLENGTH;i++)
{
if(i>=wordFlashAddr)
{
tmpdata[i] = tmpdata[i]&0xff00|DataStr[tmpLength]; //要写入的数据
tmpLength++;
}
if(tmpLength>=Length) break;
}
FlashErase(rowFlashAddr); //擦除整块
FlashWriteRow(rowFlashAddr,tmpdata,ROWLENGTH); //整块写入数据
rowFlashAddr = rowFlashAddr + 0x20; //块地址+1
wordFlashAddr= 0;
if(tmpLength>=Length) break;
}
}</font>
|