hsztc 发表于 2010-3-19 23:04:13

将ATmega48的FLASH当EEPROM用,成功了哈

ATmega48没有Boot Loader,所以只要编程SELFPRGEN熔丝,SPM指令就可以在整个FLASH空间执行。

也就是说可以修改整个FLASH空间。


#include<iom48v.h>

const char data1[];
char data;   //M48的FLASH一页的大小为64B

void SDELFLASH(unsigned char page,unsigned char x);//选译性删除FLASH页
void WFLASH2B(unsigned int add,unsigned char data1,unsigned char data0); //写一字到缓冲区
void WFLASH(unsigned char page);   //写一页
void RFLASH(unsigned char page);   //读入一页
void Pdata(void);                  //改data[]中的内容

void IO_Init(void) //IO口初始化
{//I/O口
DDRB|=(1<<PB2)|(1<<PB1)|(0<<PB0);
//PB2=蓝色LED(OC1B)PB1=红色LED(OC1A) PB0=按键'左'   
PORTB|=(0<<PB2)|(0<<PB1)|(1<<PB0);
//PC0-PC5   ADC       
DDRC|=(1<<PC5)|(1<<PC4)|(1<<PC3)|(1<<PC2)|(1<<PC1)|(1<<PC0);                               
PORTC|=(0<<PC5)|(0<<PC4)|(0<<PC3)|(0<<PC2)|(0<<PC1)|(0<<PC0);
//PD6=RESET RS232 PD7=按键'右'
DDRD|=(1<<PD6)|(0<<PD7);                               
PORTD|=(1<<PD6)|(1<<PD7);
}


void main(void)
{
IO_Init();
PORTC|=(1<<5);

RFLASH(60);      //读这页FLASH内容,读到data[]
Pdata();         //修改data[]的内容
WFLASH(60);      //写这页FLASH内容,data[]写到FLASH

while(1);
}


///////////////////////////////////////////////////////////////
void Pdata(void)   //改data[]中的内容
{ unsigned char n;
for(n=0;n<64;n++)
data=data+1;//全加1
}

///////////////////FLASH操作////////////////////////////////////
void RFLASH(unsigned char page)   //读入一页data[]
{ unsigned char Dzh,Dzl,n,da; unsigned int add;
    add=page*64;       
       for(n=0;n<64;n++)
             { Dzh=add>>8; Dzl=add;
           asm("MOV R31,%Dzh");//ZHFlash地址   
       asm("MOV R30,%Dzl");//ZL
           asm("LPM %da,Z");
           data=da;
           add++;
      }
}
////////////////////////////////////////////////////////////////
void SDELFLASH(unsigned char page,unsigned char x)   //选译性删除FLASH程序   
{ //page为要删除的页码,x为要删除的页数
unsigned char n,dpageh; unsigned int dpage;
dpage=page*64;   
   for(n=0;n<x;n++)   
   {dpageh=dpage>>8;
      asm("MOV R31,%dpageh");//ZHFlash地址   
      asm("MOV R30,%dpage");//ZL   
      SPMCSR=(1<<1)|(1<<0);   
      asm("SPM");
          dpage+=64;}   
}   
////////////////////////////////////////////////////////
void WFLASH(unsigned char page)   //写入一页
{unsigned char n; unsigned int add;
    add=page*64;

   for(n=0;n<32;n++)   //将数据写入这页缓冲区
   {
    WFLASH2B(add,data,data);
    add+=2;
   }
   
   SDELFLASH(page,1);//擦除这页FLASH
   
   SPMCSR=0b00000101;//写这页FLASH
   asm("SPM");
}
//////////////////////////////////////////////////////////////////////////
//将一个字写入缓冲区
void WFLASH2B(unsigned int add,unsigned char data1,unsigned char data0)   
{unsigned char Dzh,Dzl;
      Dzh=add>>8; Dzl=add;
          asm("MOV R0,%data1");
          asm("MOV R1,%data0");
             asm("MOV R31,%Dzh");//ZHFlash地址   
      asm("MOV R30,%Dzl");//ZL   
      SPMCSR=(1<<0);   
      asm("SPM");}
////////////////////////////////////////////////////////////////////////
/////0xF00=38403840/64=60 第60页
#pragma abs_address:0xF00
const char data1[]="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
#pragma end_abs_address

http://cache.amobbs.com/bbs_upload782111/files_27/ourdev_539588.PNG
(原文件名:写入的数据)

http://cache.amobbs.com/bbs_upload782111/files_27/ourdev_539589.PNG
(原文件名:将数字读出后,+1处理,再写回去)

1181zjf 发表于 2010-3-19 23:10:20

mark

flywater 发表于 2010-3-19 23:14:59

马克...

daicp 发表于 2010-3-19 23:27:10

又见高手

Xearo 发表于 2010-3-19 23:33:31

您是说flash可以在应用程序中修改?我只测试可以自宫,但是没想到这么用,哈哈

C语言看不太懂,最终您测试写入的程序是这个引号中的部分么?
const char data1[]="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";

那把您的思维拓展一下,我们可以用指针指向运算后的RAM区,把各种加密后的运算结果保存到Flash中,比如开始写一段自宫程序用来加密运算某密值,保存到Ram中再以一段表格的形式写回Flash;最后加密段自宫,程序投入使用。

不定期用算法校验Flash表,如果表有误则随机跳转乱执行./emotion/em035.gif,不要执行SPM,SPM命令太容易通过反汇编屏蔽掉了。

我以前的作法是把密表放在EP中。放在ep中有缺点,就是数据的安全性有点玄……而且可以通过不断修改ep内容测试加密方式和内联的运算关系。
随口乱说,请勿拍砖……

zjr0411 发表于 2010-3-19 23:45:11

记号

hsztc 发表于 2010-3-19 23:46:43

我将这些字符串放在首地址为0xF00 也就是FLASH空间的第60页
const char data1[]="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
这个完全可以不需要的
你也可以这么用,定义个数组data
然后送值给它,然后就可以直接写到FLASH了。

数据写入data[]后,执行 WFLASH(60); 就行了,这里的参数60表示FLASH空间的第60页,一页大小为64字节。


我上面写着
RFLASH(60);      //读这页FLASH内容,读到data[]
Pdata();         //修改data[]的内容
WFLASH(60);      //写这页FLASH内容,data[]写到FLASH

主要是为了只改其中的一部分,如一个字节,但FLASH要修改就要先擦除后才行,而擦除是以页为单位的。

因此要先读出来,防止无关数据丢失。

yangyi 发表于 2010-3-20 07:36:59

谢谢共享!

lifufeng 发表于 2010-3-20 07:55:14

mark,
但是FLASH的擦写次数很有限啊

n0831 发表于 2010-3-20 08:14:17

mark

xgl_1982 发表于 2010-3-20 08:45:30

学习

zou158 发表于 2010-3-20 08:53:50

高手!学习了!

sz_ehome 发表于 2010-3-20 09:02:41

马克

shabby 发表于 2010-3-20 09:04:43

先收藏,以后肯定会有用,十分感谢!

highnose 发表于 2010-3-20 10:05:33

顶,强顶哇

zj_t 发表于 2010-3-20 10:06:27

mark

hecb999 发表于 2010-3-20 10:19:49

mark

abcd200844 发表于 2010-3-20 10:33:11

顶,有用的东东,不知道有没有弊端

bluefeel 发表于 2010-3-20 11:30:10

mark

benladn911 发表于 2010-3-20 12:41:37

B向北走,NB,哈哈。

blueagle 发表于 2010-3-20 12:50:07

要是硬件支持分页写保护就好了,这样完全没保护的话用起来比较危险

liumaojun_cn 发表于 2010-3-20 12:53:34

mark

pish 发表于 2010-3-20 13:48:24

MARK,,DING...

gxy508 发表于 2010-3-20 14:11:28

mark

uc-can-m3 发表于 2010-3-20 20:16:00

程序里有写FLASH操作时,记得开BOD。要不然AVR可能会自宫。

frogrider 发表于 2010-3-20 20:39:31

mark

yangyb 发表于 2010-3-20 20:42:20

mark

yaya001 发表于 2010-3-20 23:07:05

mark

XA144F 发表于 2010-3-20 23:34:13

啊……这让我想到了STC……

wwwdege 发表于 2010-3-27 21:21:39

牛人

vincent101 发表于 2010-3-28 13:42:05

强人,进来膜拜一下。

noproblem 发表于 2010-3-28 14:10:54

很有用的功能,但同时也是灰常灰常灰常危险滴。
不到万不得已,还是慎用。

XQGG 发表于 2010-3-28 14:22:21

牛A 和 牛C中间那个就是你

camtime 发表于 2010-3-28 14:34:47

马克.m48..............

xml2028 发表于 2010-3-28 15:03:34

Nb

sonna 发表于 2010-3-28 23:27:10

留个记号

aaron96031 发表于 2010-3-29 13:04:41

mark

skyxjh 发表于 2010-4-1 14:50:08

MARK

kbdcj2000 发表于 2010-4-3 17:57:37

先收藏,以后肯定会有用,十分感谢!

221008 发表于 2010-4-22 17:38:40

楼主我怎么编译通不过啊?用的是ICC6.31A
提示:
!W D:\avr_flash\flash.c(45): local variable 'da' has no initial value
!E D:\avr_flash\flash.c(86): Register not allocated to variable data0? referenced in inline asm. Please simplify function or delete reference in inline asm.D:\icc\bin\imakew.exe: Error code 1
Done: there are error(s). Exit code: 1


不知为什么.请解答.谢谢!

hsztc 发表于 2010-4-22 18:09:49

我没这种问题啊,有可能是 da,data0 这两个变量定交到RAM区了,所以不行。

dzh,dzl,da,data0等有被汇编代码用到的变量都在是放在寄存器上,如果在RAM上汇编代码就不能这么写了。

所以在dzh,dzl,da,data0等变量前加入register试下看

如:register unsigned char Dzh,Dzl,da;

221008 发表于 2010-4-22 21:34:48

请问楼主QQ是多少?按你说的我还是没调好,依然提示有错误。请一定告知。谢谢!

smartzou 发表于 2010-4-22 21:51:36

mark~

elecboy 发表于 2010-4-22 23:03:22

总感觉这玩意很危险,抗干扰不过关的话,不定哪天就自裁了,研究研究很有意思,产品里要用,还要多加考虑。

zhenke 发表于 2010-4-22 23:08:25

mark!
演示版本该自宫的时候就自宫啊。

hsztc 发表于 2010-4-22 23:13:55

【41楼】 221008
你确定都改好了?这个试下看,

#include<iom48v.h>

const char data1[];
unsigned char data;   //M48的FLASH一页的大小为64B

void SDELFLASH(unsigned char page,unsigned char x);//选译性删除FLASH页
void WFLASH2B(unsigned int add,register unsigned char data1,register unsigned char data0); //写一字到缓冲区
void WFLASH(unsigned char page);   //写一页
void RFLASH(unsigned char page);   //读入一页
void Pdata(void);                  //改data[]中的内容


void main(void)
{

RFLASH(60);      //读这页FLASH内容,读到data[]
Pdata();         //修改data[]的内容
WFLASH(60);      //写这页FLASH内容,data[]写到FLASH

while(1);
}


///////////////////////////////////////////////////////////////
void Pdata(void)   //改data[]中的内容
{ unsigned char n;
for(n=0;n<64;n++)
data=data+1;//全加1
}

///////////////////FLASH操作////////////////////////////////////
void RFLASH(unsigned char page)   //读入一页data[]
{ unsigned char n; unsigned int add;
register unsigned char Dzh,Dzl,da;
    add=page*64;
for(n=0;n<64;n++)
      { Dzh=add>>8; Dzl=add;
   asm("MOV R31,%Dzh");//ZHFlash地址   
       asm("MOV R30,%Dzl");//ZL   
   asm("LPM %da,Z");
   data=da;
   add++;
      }
}
////////////////////////////////////////////////////////////////
void SDELFLASH(unsigned char page,unsigned char x)   //选译性删除FLASH程序   
{ //page为要删除的页码,x为要删除的页数
register unsigned char n,dpageh; register unsigned int dpage;
dpage=page*64;   
   for(n=0;n<x;n++)   
   {dpageh=dpage>>8;   
      asm("MOV R31,%dpageh");//ZHFlash地址   
      asm("MOV R30,%dpage");//ZL   
      SPMCSR=(1<<1)|(1<<0);   
      asm("SPM");
dpage+=64;}   
}   
////////////////////////////////////////////////////////
void WFLASH(unsigned char page)   //写入一页
{unsigned char n; unsigned int add;
    add=page*64;

   for(n=0;n<32;n++)   //将数据写入这页缓冲区
   {
    WFLASH2B(add,data,data);
    add+=2;
   }
   
   SDELFLASH(page,1);//擦除这页FLASH
   
   SPMCSR=0b00000101;//写这页FLASH
   asm("SPM");
}   
//////////////////////////////////////////////////////////////////////////
//将一个字写入缓冲区
void WFLASH2B(unsigned int add,register unsigned char data1,register unsigned char data0)   
{register unsigned char Dzh,Dzl;
      Dzh=add>>8; Dzl=add;
asm("MOV R0,%data1");
asm("MOV R1,%data0");
      asm("MOV R31,%Dzh");//ZHFlash地址   
      asm("MOV R30,%Dzl");//ZL   
      SPMCSR=(1<<0);   
      asm("SPM");}
////////////////////////////////////////////////////////////////////////
/////0xF00=38403840/64=60 第60页
#pragma abs_address:0xF00
const char data1[]="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
#pragma end_abs_address

380121850 发表于 2010-4-22 23:22:32

嗯,要是有一天写坏了,芯片也就跟着坏了,得不偿失

hsztc 发表于 2010-4-22 23:28:21

【43楼】 elecboy

其实不需要当心的,程序跑飞的可能性很小,在执行SPM指令之前加入分支指令,如果程序跑飞到这随近也不怕。(除非刚好跑飞到SPM指令上)

而且只要带有自动更新的产品,都有擦写FLASH的程序。他们都不当心,我们当心什么?

hsztc 发表于 2010-4-22 23:34:03

擦写不要太频繁,FLASH的寿命只有EEPROM的十分之一。

FLASH坏也不可能都坏掉的,只是坏掉几个字节而以,写程序的时候绕开这些坏的字节就行了,就是麻烦。

不过芯片照样用。

smartzou 发表于 2010-4-23 00:11:20

Mark!

yinglively 发表于 2010-4-23 07:47:33

mark

tanguoyong 发表于 2010-4-23 08:08:03

回家试一下

wangwenjia 发表于 2010-4-23 08:10:02

牛 !!!收藏了 !!!

221008 发表于 2010-4-23 08:10:43

楼主,我将以面程序中的:asm("MOV R1,%data0"); 改为:asm("MOV R1,%data1"); 就可以编译通过了.
末改的原程序为:
void WFLASH2B(unsigned int add,register unsigned char data1,register unsigned char data0)   
{register unsigned char Dzh,Dzl;
      Dzh=add>>8; Dzl=add;
asm("MOV R0,%data1");
asm("MOV R1,%data0");
      asm("MOV R31,%Dzh");//ZHFlash地址   
      asm("MOV R30,%Dzl");//ZL      
      SPMCSR=(1<<0);   
      asm("SPM");}

这是为什么呢?

liumaojun_cn 发表于 2010-4-23 08:41:46

mark

hsztc 发表于 2010-4-23 19:18:24

【53楼】 221008

怪...试下用其它变量代下看,改三句如:

void WFLASH2B(unsigned int add,unsigned char data1,unsigned char abc); //写一字到缓冲区
....

void WFLASH2B(unsigned int add,register unsigned char data1,register unsigned char abc)
.....

asm("MOV R1,%abc");

.....

xuejianhua1986 发表于 2010-4-23 22:06:14

mark

lv998127 发表于 2010-4-24 17:31:06

我顶!

mushk 发表于 2010-4-25 14:32:42

mark

221008 发表于 2010-4-27 16:21:31

请问在iar avr里面以下代码应该怎么写:
      Dzh=add>>8; Dzl=add;   
      asm("MOV R0,%data1");   
      asm("MOV R1,%data0");   
      asm("MOV R31,%Dzh");//ZHFlash地址      
      asm("MOV R30,%Dzl");//ZL

才能让上面的程序编译通过.
注:以上为ICCAVR可以编译的程序.

XA144F 发表于 2010-6-15 20:54:50

Atmega8515是否可以这样操作?

hsztc 发表于 2010-6-15 21:10:01

可以的,只是要把程序放在BOOT区,程序应该也有点差别,没试过,看数据手册吧。

XA144F 发表于 2010-6-15 21:14:01

看过资料,SPM指令在应用程序区是无效的,将这“应用”程序定位到BOOT区是否可行?

hsztc 发表于 2010-6-15 21:27:06

应该是可以的,不知道软件支不技持,ICCAVR可以选译放在哪里。



#pragma abs_address:0xF00//地址

//程序

#pragma end_abs_address

lv998127 发表于 2010-6-16 20:46:07

ball648500361 发表于 2010-6-17 11:45:28

mark

gliet_su 发表于 2010-6-17 13:00:00

记录

joing2000 发表于 2010-6-17 16:53:46

mark

twlkzxy 发表于 2010-7-16 10:35:47

mark

dgdjfw 发表于 2010-7-16 13:38:00

mark

wzyllgx 发表于 2010-7-16 13:56:32

mark

lkwslk1 发表于 2010-8-13 11:31:51

...

swustlx86 发表于 2010-8-13 11:54:34

mark

guxingganyue 发表于 2010-10-1 20:12:56

mark

rafd 发表于 2010-10-25 08:31:22

为什么我把上面的例子程序改程mega32的,软件模拟可以,但是实际写入芯片jtag调试和运行,却不行,反映的情况是擦除不掉和不能写入,软件模拟时SPMCR 置数后,指令 asm("SPM") 可以清零SPMCR ,jtag调试看到的却是SPMCR 置数后,指令 asm("SPM")不能清零SPMCR,SPMCR 还是原来的数,I_Automate_Out寄存器是外部输出指示灯,第一个数据没改时,是原来的00时第一个等亮,更改成功不是00时第二个灯亮,用来指示实际运行时的状态,原来我以为,是jtag调试时,是不能更改flash,实际运行也是一样是第一个灯亮就是还是00没有更改成功
#include <iom32.h>
#define N_Isp_PageStart 60                  //开始页
#define N_Isp_PageSize 128                  //一页字节数
static uint8 I_Isp_Buffer;         //M48的FLASH一页的大小为64B
__regvar __no_init uint8 Reg_12 @ 12;
__regvar __no_init uint8 Reg_13 @ 13;
__regvar __no_init uint8 Reg_14 @ 14;
__regvar __no_init uint8 Reg_15 @ 15;

////////////////////////////////////////////////////////////////////////   
__root__flash uint8 I_Isp_Rom@(N_Isp_PageStart*N_Isp_PageSize) ={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};


uint8 fff = 0;


void SDELFLASH(uint8 page,uint8 x);//选译性删除FLASH页
void WFLASH2B(uint16 add,uint8 data1,uint8 data0); //写一字到缓冲区
void WFLASH(uint8 page);   //写一页
void RFLASH(uint8 page);   //读入一页
void Pdata(void);                  //改data[]中的内容
void main(void)      
{
    while(1)
    {
      if(fff==0x0)
      {
            RFLASH(N_Isp_PageStart);      //读这页FLASH内容,读到data[]
            if(I_Isp_Rom == 0)
            {
                I_Automate_Out = ~0x2;
                Pdata();         //修改data[]的内容
                WFLASH(N_Isp_PageStart);      //写这页FLASH内容,data[]写到FLASH
                RFLASH(N_Isp_PageStart);      //读这页FLASH内容,读到data[]
                if(I_Isp_Rom == 1)
                {
                  I_Automate_Out = ~0x8;
                }
                else
                {
                  I_Automate_Out = ~0x2;
                }
            }
            else
            {
                I_Automate_Out = ~0x8;
            }
            //fff++;
      }
      else
      {
            fff = 0xff;
      }
            

      OSTimeDly(N_Isp_rwxmys);   //任务休眠时间
    }
}


///////////////////////////////////////////////////////////////
void Pdata(void)   //改data[]中的内容
{ uint8 n;
for(n=0;n<N_Isp_PageSize;n++)
I_Isp_Buffer=I_Isp_Buffer+1;//全加1
}

///////////////////FLASH操作////////////////////////////////////
void RFLASH(uint8 page)   //读入一页data[]
{
    uint8 n; uint16 add;   
    add=page*N_Isp_PageSize;
    for(n=0;n<N_Isp_PageSize;n++)
    {
      asm ("cli");
      Reg_13=add>>8;
      Reg_14=add;
      asm("MOV R31,R13");//ZHFlash地址   
      asm("MOV R30,R14");//ZL   
      asm("LPM R15,Z");
      I_Isp_Buffer=Reg_15;
      asm ("sei");
      add++;
    }
}
////////////////////////////////////////////////////////////////
void SDELFLASH(uint8 page,uint8 x)   //选译性删除FLASH程序   
{ //page为要删除的页码,x为要删除的页数
    uint8 n,dpageh;
    uint16 dpage;
    dpage=page*N_Isp_PageSize;   
    for(n=0;n<x;n++)   
    {
      dpageh=dpage>>8;
      asm ("cli");
      Reg_14 = dpageh;
      Reg_15 = dpage;
      asm("MOV R31,R14");//ZHFlash地址   
      asm("MOV R30,R15");//ZL   
      SPMCR=(1<<1)|(1<<0);   
      asm("SPM");
      asm ("sei");
      dpage+=N_Isp_PageSize;
    }   
}   
////////////////////////////////////////////////////////
void WFLASH(uint8 page)   //写入一页
{
    uint8 n;
    uint16 add;
    uint8 zjs;
    while(SPMCR & 0x01 != 0 );//未处理好死循环
    {
      add = page*N_Isp_PageSize;
      zjs = N_Isp_PageSize/2;
      for(n=0;n<zjs;n++)   //将数据写入这页缓冲区
      {
            WFLASH2B(add,I_Isp_Buffer,I_Isp_Buffer[(n*2)+1]);
            add += 2;
      }
      
      SDELFLASH(page,1);//擦除这页FLASH
      asm ("cli");
      SPMCR = (1<<2)|(1<<0);//写这页FLASH
      asm("SPM");
      asm ("sei");
    }
}   
//////////////////////////////////////////////////////////////////////////   
//将一个字写入缓冲区
void WFLASH2B(uint16 add,uint8 data1,uint8 data0)   
{
    asm ("cli");
    Reg_12 = add>>8;
    Reg_13 = add;
    Reg_14 = data1;
    Reg_15 = data0;
    asm("MOV R0,R14");
    asm("MOV R1,R15");
    asm("MOV R31,R12");//ZHFlash地址   
    asm("MOV R30,R13");//ZL      
    SPMCR=(1<<0);   
    asm("SPM");
    asm ("sei");
}

rafd 发表于 2010-10-25 08:32:22

忘了说了,上面的程序是已经改成在IAR上运行了

rafd 发表于 2010-10-25 08:45:29

改成单独的工程文件,上面那个程序是整个程序里拷出来的


#include <iom32.h>
#define N_Isp_PageStart 60                  //开始页
#define N_Isp_PageSize 128                  //一页字节数
__regvar __no_init unsigned char Reg_12 @ 12;
__regvar __no_init unsigned char Reg_13 @ 13;
__regvar __no_init unsigned char Reg_14 @ 14;
__regvar __no_init unsigned char Reg_15 @ 15;

unsigned char I_Isp_Buffer;         //M48的FLASH一页的大小为64B
////////////////////////////////////////////////////////////////////////   
__root__flash unsigned char I_Isp_Rom@(N_Isp_PageStart*N_Isp_PageSize) ={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};


unsigned char fff = 0;
   

void SDELFLASH(unsigned char page,unsigned char x);//选译性删除FLASH页   
void WFLASH2B(unsigned int add,unsigned char data1,unsigned char data0); //写一字到缓冲区   
void WFLASH(unsigned char page);   //写一页   
void RFLASH(unsigned char page);   //读入一页   
void Pdata(void);                  //改data[]中的内容   
int main(void)      
{
    while(1)
    {
      if(fff==0x0)
      {
            RFLASH(N_Isp_PageStart);      //读这页FLASH内容,读到data[]   
            if(I_Isp_Rom == 0)
            {
                //I_Automate_Out = ~0x2;
                Pdata();         //修改data[]的内容   
                WFLASH(N_Isp_PageStart);      //写这页FLASH内容,data[]写到FLASH   
                RFLASH(N_Isp_PageStart);      //读这页FLASH内容,读到data[]
                if(I_Isp_Rom == 1)
                {
                  //I_Automate_Out = ~0x8;
                }
                else
                {
                  //I_Automate_Out = ~0x2;
                }
            }
            else
            {
                //I_Automate_Out = ~0x8;
            }
            //fff++;
      }
      else
      {
            fff = 0xff;
      }
            
    }
}
///////////////////////////////////////////////////////////////   
void Pdata(void)   //改data[]中的内容   
{ unsigned char n;   
for(n=0;n<N_Isp_PageSize;n++)   
I_Isp_Buffer=I_Isp_Buffer+1;//全加1   
}   

///////////////////FLASH操作////////////////////////////////////   
void RFLASH(unsigned char page)   //读入一页data[]   
{
    unsigned char n; unsigned int add;   
    add=page*N_Isp_PageSize;   
    for(n=0;n<N_Isp_PageSize;n++)   
    {
      asm ("cli");
      Reg_13=add>>8;
      Reg_14=add;   
      asm("MOV R31,R13");//ZHFlash地址      
      asm("MOV R30,R14");//ZL   
      asm("LPM R15,Z");   
      I_Isp_Buffer=Reg_15;
      asm ("sei");
      add++;
    }   
}   
////////////////////////////////////////////////////////////////   
void SDELFLASH(unsigned char page,unsigned char x)   //选译性删除FLASH程序      
{ //page为要删除的页码,x为要删除的页数   
    unsigned char n,dpageh;
    unsigned int dpage;   
    dpage=page*N_Isp_PageSize;      
    for(n=0;n<x;n++)      
    {
      dpageh=dpage>>8;   
      asm ("cli");
      Reg_14 = dpageh;
      Reg_15 = dpage;
      asm("MOV R31,R14");//ZHFlash地址      
      asm("MOV R30,R15");//ZL      
      SPMCR=(1<<1)|(1<<0);      
      asm("SPM");
      asm ("sei");
      dpage+=N_Isp_PageSize;
    }      
}      
////////////////////////////////////////////////////////   
void WFLASH(unsigned char page)   //写入一页   
{
    unsigned char n;
    unsigned int add;
    unsigned char zjs;
    while(SPMCR & 0x01 != 0 );//未处理好死循环
    {
      add = page*N_Isp_PageSize;   
      zjs = N_Isp_PageSize/2;
      for(n=0;n<zjs;n++)   //将数据写入这页缓冲区   
      {   
            WFLASH2B(add,I_Isp_Buffer,I_Isp_Buffer[(n*2)+1]);   
            add += 2;   
      }   
         
      SDELFLASH(page,1);//擦除这页FLASH   
      asm ("cli");
      SPMCR = (1<<2)|(1<<0);//写这页FLASH   
      asm("SPM");
      asm ("sei");
    }
}   
//////////////////////////////////////////////////////////////////////////   
//将一个字写入缓冲区   
void WFLASH2B(unsigned int add,unsigned char data1,unsigned char data0)      
{
    asm ("cli");
    Reg_12 = add>>8;
    Reg_13 = add;
    Reg_14 = data1;
    Reg_15 = data0;
    asm("MOV R0,R14");   
    asm("MOV R1,R15");   
    asm("MOV R31,R12");//ZHFlash地址      
    asm("MOV R30,R13");//ZL      
    SPMCR=(1<<0);      
    asm("SPM");
    asm ("sei");
}

zhaoghsea 发表于 2010-10-25 09:07:39

mark

qiu452555846 发表于 2010-10-26 06:59:55

mark

jiaweijing 发表于 2010-10-26 08:07:37

mark

rafd 发表于 2010-10-26 20:57:26

再顶

rafd 发表于 2010-10-27 21:14:30

还是不行,是不是控制字熔丝还要设置

hsztc 发表于 2010-10-27 22:26:01

【81楼】 rafd

好久没玩这个了,都忘差不多了,M32应该把程序定义在boot loader空间,否则SPM无法执行。

还有注意M32的FLASH的页大小可能跟M48不一样大,具体看数据手册。

熔丝默认是可以读写FLASH的。

ankjin 发表于 2010-10-27 23:28:24

牛X,mark

wzxavr 发表于 2010-10-28 08:39:07

mark

ufo2007 发表于 2010-11-25 00:16:59

留意一下

lxw2087290 发表于 2010-11-25 00:38:52

这个有意思,哈哈

zhaoghsea 发表于 2010-11-25 08:50:57

牛,mark

ning321613 发表于 2011-3-6 15:56:21

楼主,【81楼】 rafd 你们好,我现在也是只能读出不能写入,在IAR下编译的,发现读出的数据是对的。但是自己修改数据写入后再重新读出发现读出的数据还是原来的

czz777 发表于 2011-4-4 23:47:13

mark

jiang47 发表于 2011-5-8 12:06:35

mark

xinshou63 发表于 2011-5-9 11:08:33

mark

dong7758 发表于 2014-9-26 07:12:35

mark                   .

chinazhaoyl 发表于 2014-9-26 09:26:56

谢谢分享!
页: [1]
查看完整版本: 将ATmega48的FLASH当EEPROM用,成功了哈