搜索
bottom↓
回复: 93

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

[复制链接]

出0入0汤圆

发表于 2010-3-19 23:04:13 | 显示全部楼层 |阅读模式
ATmega48没有Boot Loader,所以只要编程SELFPRGEN熔丝,SPM指令就可以在整个FLASH空间执行。

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


#include<iom48v.h>

const char data1[];
char data[64];   //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[n]=data[n]+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");  //ZH  Flash地址   
       asm("MOV R30,%Dzl");  //ZL  
           asm("LPM %da,Z");
           data[n]=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");  //ZH  Flash地址   
      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[n*2],data[n*2+1]);
    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");  //ZH  Flash地址   
      asm("MOV R30,%Dzl");  //ZL   
      SPMCSR=(1<<0);   
      asm("SPM");}
////////////////////////////////////////////////////////////////////////
/////0xF00=3840  3840/64=60 第60页
#pragma abs_address:0xF00
const char data1[]="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
#pragma end_abs_address


(原文件名:写入的数据)


(原文件名:将数字读出后,+1处理,再写回去)

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2010-3-19 23:10:20 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-19 23:14:59 | 显示全部楼层
马克...

出0入0汤圆

发表于 2010-3-19 23:27:10 | 显示全部楼层
又见高手

出300入0汤圆

发表于 2010-3-19 23:33:31 | 显示全部楼层
您是说flash可以在应用程序中修改?我只测试可以自宫,但是没想到这么用,哈哈

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

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

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

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

出200入0汤圆

发表于 2010-3-19 23:45:11 | 显示全部楼层
记号

出0入0汤圆

 楼主| 发表于 2010-3-19 23:46:43 | 显示全部楼层
我将这些字符串放在首地址为0xF00 也就是FLASH空间的第60页
const char data1[]="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
这个完全可以不需要的
你也可以这么用,定义个数组data[64]
然后送值给它,然后就可以直接写到FLASH了。

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


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

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

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

出10入10汤圆

发表于 2010-3-20 07:36:59 | 显示全部楼层
谢谢共享!

出0入0汤圆

发表于 2010-3-20 07:55:14 | 显示全部楼层
mark,
但是FLASH的擦写次数很有限啊

出0入42汤圆

发表于 2010-3-20 08:14:17 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-20 08:45:30 | 显示全部楼层
学习

出0入0汤圆

发表于 2010-3-20 08:53:50 | 显示全部楼层
高手!学习了!

出0入0汤圆

发表于 2010-3-20 09:02:41 | 显示全部楼层
马克

出0入0汤圆

发表于 2010-3-20 09:04:43 | 显示全部楼层
先收藏,以后肯定会有用,十分感谢!

出0入0汤圆

发表于 2010-3-20 10:05:33 | 显示全部楼层
顶,强顶哇

出0入0汤圆

发表于 2010-3-20 10:06:27 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-20 10:19:49 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-20 10:33:11 | 显示全部楼层
顶,有用的东东,不知道有没有弊端

出0入85汤圆

发表于 2010-3-20 11:30:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-20 12:41:37 | 显示全部楼层
B向北走,NB,哈哈。

出0入0汤圆

发表于 2010-3-20 12:50:07 | 显示全部楼层
要是硬件支持分页写保护就好了,这样完全没保护的话用起来比较危险

出0入0汤圆

发表于 2010-3-20 12:53:34 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-20 13:48:24 | 显示全部楼层
MARK,,DING...

出0入0汤圆

发表于 2010-3-20 14:11:28 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-20 20:16:00 | 显示全部楼层
程序里有写FLASH操作时,记得开BOD。要不然AVR可能会自宫。

出0入0汤圆

发表于 2010-3-20 20:39:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-20 20:42:20 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-20 23:07:05 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-20 23:34:13 | 显示全部楼层
啊……这让我想到了STC……

出0入0汤圆

发表于 2010-3-27 21:21:39 | 显示全部楼层
牛人

出0入0汤圆

发表于 2010-3-28 13:42:05 | 显示全部楼层
强人,进来膜拜一下。

出0入0汤圆

发表于 2010-3-28 14:10:54 | 显示全部楼层
很有用的功能,但同时也是灰常灰常灰常危险滴。
不到万不得已,还是慎用。

出0入0汤圆

发表于 2010-3-28 14:22:21 | 显示全部楼层
牛A 和 牛C中间那个就是你

出0入0汤圆

发表于 2010-3-28 14:34:47 | 显示全部楼层
马克.m48..............

出675入8汤圆

发表于 2010-3-28 15:03:34 | 显示全部楼层
Nb

出0入59汤圆

发表于 2010-3-28 23:27:10 | 显示全部楼层
留个记号

出0入0汤圆

发表于 2010-3-29 13:04:41 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-1 14:50:08 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-4-3 17:57:37 | 显示全部楼层
先收藏,以后肯定会有用,十分感谢!

出0入0汤圆

发表于 2010-4-22 17:38:40 | 显示全部楼层
楼主我怎么编译通不过啊?用的是ICC6.31A
提示:
!W D:\avr_flash\flash.c(45):[warning] 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


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

出0入0汤圆

 楼主| 发表于 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;

出0入0汤圆

发表于 2010-4-22 21:34:48 | 显示全部楼层
请问楼主QQ是多少?按你说的我还是没调好,依然提示有错误。请一定告知。谢谢!

出0入0汤圆

发表于 2010-4-22 21:51:36 | 显示全部楼层
mark~

出0入0汤圆

发表于 2010-4-22 23:03:22 | 显示全部楼层
总感觉这玩意很危险,抗干扰不过关的话,不定哪天就自裁了,研究研究很有意思,产品里要用,还要多加考虑。

出0入0汤圆

发表于 2010-4-22 23:08:25 | 显示全部楼层
mark!
演示版本该自宫的时候就自宫啊。

出0入0汤圆

 楼主| 发表于 2010-4-22 23:13:55 | 显示全部楼层
【41楼】 221008
你确定都改好了?这个试下看,

#include<iom48v.h>

const char data1[];
unsigned char data[64];   //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[n]=data[n]+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");  //ZH  Flash地址   
       asm("MOV R30,%Dzl");  //ZL   
   asm("LPM %da,Z");
   data[n]=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");  //ZH  Flash地址   
      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[n*2],data[n*2+1]);
    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");  //ZH  Flash地址   
      asm("MOV R30,%Dzl");  //ZL     
      SPMCSR=(1<<0);   
      asm("SPM");}  
////////////////////////////////////////////////////////////////////////
/////0xF00=3840  3840/64=60 第60页
#pragma abs_address:0xF00
const char data1[]="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
#pragma end_abs_address

出0入0汤圆

发表于 2010-4-22 23:22:32 | 显示全部楼层
嗯,要是有一天写坏了,芯片也就跟着坏了,得不偿失

出0入0汤圆

 楼主| 发表于 2010-4-22 23:28:21 | 显示全部楼层
【43楼】 elecboy

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

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

出0入0汤圆

 楼主| 发表于 2010-4-22 23:34:03 | 显示全部楼层
擦写不要太频繁,FLASH的寿命只有EEPROM的十分之一。

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

不过芯片照样用。

出0入0汤圆

发表于 2010-4-23 00:11:20 | 显示全部楼层
Mark!

出0入0汤圆

发表于 2010-4-23 07:47:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-23 08:08:03 | 显示全部楼层
回家试一下

出0入0汤圆

发表于 2010-4-23 08:10:02 | 显示全部楼层
牛 !!!  收藏了 !!!

出0入0汤圆

发表于 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");  //ZH  Flash地址     
      asm("MOV R30,%Dzl");  //ZL      
      SPMCSR=(1<<0);     
      asm("SPM");}

这是为什么呢?

出0入0汤圆

发表于 2010-4-23 08:41:46 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 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");

.....

出0入0汤圆

发表于 2010-4-23 22:06:14 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-24 17:31:06 | 显示全部楼层
我顶!

出0入0汤圆

发表于 2010-4-25 14:32:42 | 显示全部楼层
mark

出0入0汤圆

发表于 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");  //ZH  Flash地址      
      asm("MOV R30,%Dzl");  //ZL

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

出0入0汤圆

发表于 2010-6-15 20:54:50 | 显示全部楼层
Atmega8515是否可以这样操作?

出0入0汤圆

 楼主| 发表于 2010-6-15 21:10:01 | 显示全部楼层
可以的,只是要把程序放在BOOT区,程序应该也有点差别,没试过,看数据手册吧。

出0入0汤圆

发表于 2010-6-15 21:14:01 | 显示全部楼层
看过资料,SPM指令在应用程序区是无效的,将这“应用”程序定位到BOOT区是否可行?

出0入0汤圆

 楼主| 发表于 2010-6-15 21:27:06 | 显示全部楼层
应该是可以的,不知道软件支不技持,ICCAVR可以选译放在哪里。



#pragma abs_address:0xF00  //地址

//程序

#pragma end_abs_address

出0入0汤圆

发表于 2010-6-16 20:46:07 | 显示全部楼层

出0入0汤圆

发表于 2010-6-17 11:45:28 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-6-17 13:00:00 | 显示全部楼层
记录

出0入0汤圆

发表于 2010-6-17 16:53:46 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-16 10:35:47 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-16 13:38:00 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-16 13:56:32 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-13 11:31:51 | 显示全部楼层
...

出0入0汤圆

发表于 2010-8-13 11:54:34 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-1 20:12:56 | 显示全部楼层
mark

出0入0汤圆

发表于 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[N_Isp_PageSize];           //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_PageSize]@(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] == 0)
            {
                I_Automate_Out = ~0x2;
                Pdata();         //修改data[]的内容  
                WFLASH(N_Isp_PageStart);      //写这页FLASH内容,data[]写到FLASH  
                RFLASH(N_Isp_PageStart);      //读这页FLASH内容,读到data[]
                if(I_Isp_Rom[0] == 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[n]=I_Isp_Buffer[n]+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");  //ZH  Flash地址     
        asm("MOV R30,R14");  //ZL   
        asm("LPM R15,Z");  
        I_Isp_Buffer[n]=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");  //ZH  Flash地址     
        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[n*2],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");  //ZH  Flash地址     
    asm("MOV R30,R13");  //ZL      
    SPMCR=(1<<0);     
    asm("SPM");
    asm ("sei");
}

出0入0汤圆

发表于 2010-10-25 08:32:22 | 显示全部楼层
忘了说了,上面的程序是已经改成在IAR上运行了

出0入0汤圆

发表于 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[N_Isp_PageSize];           //M48的FLASH一页的大小为64B
////////////////////////////////////////////////////////////////////////   
__root  __flash unsigned char I_Isp_Rom[N_Isp_PageSize]@(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] == 0)
            {  
                //I_Automate_Out = ~0x2;
                Pdata();         //修改data[]的内容   
                WFLASH(N_Isp_PageStart);      //写这页FLASH内容,data[]写到FLASH   
                RFLASH(N_Isp_PageStart);      //读这页FLASH内容,读到data[]
                if(I_Isp_Rom[0] == 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[n]=I_Isp_Buffer[n]+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");  //ZH  Flash地址      
        asm("MOV R30,R14");  //ZL     
        asm("LPM R15,Z");   
        I_Isp_Buffer[n]=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");  //ZH  Flash地址      
        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[n*2],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");  //ZH  Flash地址      
    asm("MOV R30,R13");  //ZL      
    SPMCR=(1<<0);      
    asm("SPM");
    asm ("sei");
}

出0入0汤圆

发表于 2010-10-25 09:07:39 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-26 06:59:55 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-26 08:07:37 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-26 20:57:26 | 显示全部楼层
再顶

出0入0汤圆

发表于 2010-10-27 21:14:30 | 显示全部楼层
还是不行,是不是控制字熔丝还要设置

出0入0汤圆

 楼主| 发表于 2010-10-27 22:26:01 | 显示全部楼层
【81楼】 rafd

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

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

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

出0入0汤圆

发表于 2010-10-27 23:28:24 | 显示全部楼层
牛X,mark

出0入0汤圆

发表于 2010-10-28 08:39:07 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-25 00:16:59 | 显示全部楼层
留意一下

出0入0汤圆

发表于 2010-11-25 00:38:52 | 显示全部楼层
这个有意思,哈哈

出0入0汤圆

发表于 2010-11-25 08:50:57 | 显示全部楼层
牛,mark

出0入0汤圆

发表于 2011-3-6 15:56:21 | 显示全部楼层
楼主,【81楼】 rafd 你们好,我现在也是只能读出不能写入,在IAR下编译的,发现读出的数据是对的。但是自己修改数据写入后再重新读出发现读出的数据还是原来的

出0入0汤圆

发表于 2011-4-4 23:47:13 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-8 12:06:35 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-9 11:08:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2014-9-26 07:12:35 | 显示全部楼层
mark                   .

出0入0汤圆

发表于 2014-9-26 09:26:56 来自手机 | 显示全部楼层
谢谢分享!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 07:17

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表