原创 PIC18F系列读写FLASH的函数

2008-7-9 23:35 9197 12 16 分类: MCU/ 嵌入式

网上搜了一下,关于PIC18F系列读写FLASH的函数,有很多都是有错误的或者有BUG的,集中在表指针的操作上.


 


因此走了些弯路,现在发一个我自己写的读写FLASH的函数分享给大家,已测试过,支持绝大部分PIC18F系列的芯片.


 


还有一个是写"1字节"的函数,写几个字节的时候很有用.有人一定会反驳说写操作不是按64个字节块来执行的吗?确实是,下边已经给出注释了.


 


以下是写函数的部分代码:


#define addr 0x400   //定义要写入的起始地址


//写周期
void Write_Cycle(void)
{
 EEPGD = 1;    //EEPGD:闪存程序存储器或数据EEPROM 选择位
                         //1 = 访问闪速程序存储器
                         //0 = 访问数据EEPROM
 CFGS = 0;      //CFGS:闪存程序存储器/ 数据EEPROM 或配置寄存器选择位
                         //1 = 访问配置寄存器
                         //0 = 访问闪存程序存储器或数据EEPROM
 WREN = 1;    //WREN:闪存程序/ 数据EEPROM 写使能位
                         //1 = 允许闪存程序/ 数据EEPROM 的写周期
                         //0 = 禁止闪存程序/ 数据EEPROM 的写周期
 CARRY = 0;
 if(GIE)
    CARRY = 1;
 GIE = 0;         //关全局中断
 EECON2 = 0X55;
 EECON2 = 0XAA;
 WR = 1;        //1 启动读/写周期;0 写周期完成
 NOP();
 NOP();
 while(WR) ;  //等待写周期完成
 WREN = 0;    //0 禁止向程序存储器或EEPROM写操作


 if(CARRY)
      GIE = 1;     //IPEN=1,开中断
}


//器件复位时和写操作后保持寄存器的默认
//值为FFh。向保持寄存器写入FFh 并不会
//修改寄存器中存储的字节。这意味着,假如
//不想将某个位从0 改为1,而仅修改程序存
//储器中的个别字节也是可以的。当修改个
//别字节时,在执行写操作前不必装入所有
//的64 个保持寄存器。


 


//写函数,每次写入FLASH是1个字节
void Write_One_Byte(unsigned long address,unsigned char data)
{
     TBLPTRL = ((address) & 0xFF);
     TBLPTRH = (((address) >> 8) & 0xFF);
     TBLPTRU = (((address) >> 8) >> 8);


    TABLAT = data;
    asm("\tTBLWT*");


    FREE = 0;          //只执行写操作
    Write_Cycle();
}


//写函数,每次写入FLASH只能是64字节,故要写入大量数据的话,就需要多次写入
void Flash_Write(unsigned long address,unsigned char *Pdata)
{
 unsigned char count;
 unsigned char length; 


 Flash_Erase(address);     //擦除64个字节


 for(count=0; count<8; count++)    //写8次,8*8=64
 {
      TBLPTRL = ((address+count*8) & 0xFF);  //地址载入TBLPTR
      TBLPTRH = (((address+count*8) >> 8) & 0xFF);
      TBLPTRU = (((address+count*8) >> 8) >> 8);


  for(length=0; length<8; length++)    //写8字节到RAM
  {
     TABLAT = *(Pdata+length+count*8); //数据载入TABLAT
     if(length != 0)     
    {
        asm("\tTBLWT+*");  //TBLPTR需要预先增加   
     }
     else
     {
       asm("\tTBLWT*");  //地址已经载入TBLPTR,不需要预先增加   
      }
   }


    FREE = 0;       //只执行写操作
    Write_Cycle();
 }
}


void main(void)
{   
 Write_One_Byte(addr-1, 0xaa);
 Flash_Write(addr, &data[0]);
 while(1)
 {
  temp = Flash_Read(addr-1);
 }
}


 


MPLAB SIM仿真结果,其中地址0x3ff中的数据:0xaa就是用"写1字节"函数写上去的.


7e47fa03-d45d-4198-aa50-c20de069ae05.jpg


 


附件内含两个工程,一个是用PICC18编译器的,一个是MCC18编译器的.


 


再送大家一个CleanUp.bat,可以用来清除编译器产生的一些链接文件之类的,很好用.


附件下载地址:点击下载

文章评论4条评论)

登录后参与讨论

用户377235 2014-3-21 12:05

谢谢分享!

用户377235 2013-6-14 22:30

如果在写FLASH的时候出现掉电,会发生什么?哈哈,PIC的自写FLASH实用性不是很强。

用户377235 2011-12-13 10:31

谢谢,很好的

用户249995 2009-10-26 11:33

你好,我目前使用PIC18F66J65单片机,需要使用网络在应用更新固件程序,其中网络部分已经实现,但是还有很多东西不知道该怎么做,您能指导一下我吗?我的QQ是 119630974
相关推荐阅读
用户1177633 2008-06-12 14:29
如何把两个*.hex合并成一个*.hex?在写IAP/Bootloader很有用哦
        前几天,一网友在某论坛上问我关于PIC Bootloader的问题,他问如何创建两个工程分别编写引导程序和用户程序,分别将两个工程编译成两个.hex文件,然后手工合为一个.hex文件,...
用户1177633 2008-06-04 23:39
Protel技巧之二:巧为元器件进行标注
        今天发现自己的博客中11篇博文,居然有5篇博客精华,质量很高啊,非常感谢EDNCHINA,非常开心,想起自己好久没有更新过BLOG了,想起以前设计原理图时候使用过的一个技巧,现发出来分...
用户1177633 2008-04-08 22:05
如何使用PIC C30中的外设库函数?
        刚开始学dsPIC33,发现MicroChip做的C30编译器还不错,里边有常用的外设库(Peripheral Libraries),写程序也不用查datasheet就可以很快配置好寄...
用户1177633 2008-04-02 21:47
Protel技巧之一:设计原理图模块化
         设计大系统的原理图的时候,通常元器件很多,而且连线错综复杂,很容易搞错,看起来也不舒服,如果大家设计的时候,把各个模块系统化,对不同功能的部分进行分类,然后用不同颜色的虚线框围起来,...
用户1177633 2007-09-14 17:50
真正的变形金刚
http://www.56.com/n_v165_/c17_/23_/18_/yuan8088_/zhajm_1184957140_349_/39000_/0_/15707484.swf简直是精品艺术...
我要评论
4
12
关闭 站长推荐上一条 /2 下一条