发新帖我要提问
12
返回列表
打印
[PIC®/AVR®/dsPIC®产品]

【分享】PIC16F1503读写flash所有函数

[复制链接]
楼主: wangtao478552
手机看帖
扫描二维码
随时随地手机跟帖
21
yhy08090| | 2019-7-3 16:32 | 只看该作者 回帖奖励 |倒序浏览
本帖最后由 yhy08090 于 2019-7-4 11:32 编辑
lcczg 发表于 2019-7-3 15:54
程序空间一个word是14位。如果要存放16位的数据的话,写入前和读取后应该要做下处理。 ...

嗯,感觉有些奇怪

使用特权

评论回复
22
lcczg| | 2019-7-4 08:36 | 只看该作者
yhy08090 发表于 2019-7-3 16:32
嗯,感觉处理有些头大。奇怪

只是针对数据存储需要处理,对于程序是不需要的,因为指令都是14位的。这样设计方便指令存储,毕竟Flash基本都是放程序的。

使用特权

评论回复
评分
参与人数 1威望 +2 收起 理由
yhy08090 + 2 很给力!
23
yhy08090| | 2019-7-10 13:21 | 只看该作者
本帖最后由 yhy08090 于 2019-7-10 13:28 编辑

我在PIC16  18346 上按照楼主的行写,写一次结束后,重启MCU, 发现电流从200ma掉电至90MA, MCU不能正常工作了。

使用特权

评论回复
24
小卡| | 2019-7-12 14:03 | 只看该作者
感激分享~  

使用特权

评论回复
25
淘猫汤姆| | 2019-7-12 19:43 | 只看该作者
zbcaich 发表于 2018-1-7 20:53
如附图,在ROM range后面指定要空出来的空间,编译器就不会在这个空间内放置任何数据了
...

这个才是正解

使用特权

评论回复
26
xixi2017| | 2019-8-15 14:26 | 只看该作者
谢谢楼主分享

使用特权

评论回复
27
jiekou001| | 2019-8-20 19:29 | 只看该作者
感谢楼主分享,帮你顶一下

使用特权

评论回复
28
wkq123456789| | 2020-9-9 08:26 | 只看该作者
Antecer 发表于 2016-1-9 20:40
你好,我用PIC16F1455编写了读写flash的函数,然而读取没问题,擦除和写入都无法成功。

在这里看到了你的 ...

你好,可以和你交流一下1455嘛

使用特权

评论回复
29
自己造声卡| | 2020-9-9 08:36 | 只看该作者
感谢楼主分享,这种资料太真贵了。谢谢。

使用特权

评论回复
30
看别人照片| | 2020-9-9 08:43 | 只看该作者
感谢楼主的分享,感谢大家,感谢21ic

使用特权

评论回复
31
Antecer| | 2023-7-10 14:26 | 只看该作者
本帖最后由 Antecer 于 2023-7-10 14:28 编辑
wkq123456789 发表于 2020-9-9 08:26
你好,可以和你交流一下1455嘛

都在这里了:
<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>

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则