打印

如何往flash里面写入int型数据,张老师

[复制链接]
5365|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dianqi123|  楼主 | 2007-5-26 11:11 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

/*-------------DoEraseFlash:擦除指定flash区------------*/ 
void DoEarseFlash(void)
  {
    unsigned int c;
    FLBPR=0xff;                    //设置flash保护区
    FLCR_ERASE=1;     //1->ERASE,0->MASS(页擦除)
    FLCR_MASS=0;
    c=FLBPR;              //读FLBPR 
    *((volatile unsigned char *)(0xde00))=0x99;//向被擦写的单元写任意字符
    for(c=0;c<100;c++);   //延时10us
    FLCR_HVEN=1;     //1->HVEN (加高压)
    for(c=0;c<1000;c++);  //延时时间必须>1.6ms
    FLCR_ERASE=0;     //0->Erase
    for(c=0;c<100;c++);   //10us
    FLCR_HVEN=0;     //0->HVEN(取消高压)
    for(c=0;c<100;c++);   //延时10us
  }

/*-------------------------------------------------------*/
/*-----------DoWriteFlash:实际执行的写入函数-----------*/
void DoWriteFlash()
  {  
    unsigned int c;
    FLBPR=0xff;    
    FLCR_PGM=1;      //1->PGM,编程状态        
    c=FLBPR;               //读FLBPR 
    *((volatile unsigned char *)(0xde00))=0x88;//0x88->C000,选中flash行 
    for(c=0;c<200;c++);    //10us
    FLCR_HVEN=1;           //1->HVEN
    for(c=0;c<100;c++);    //10us  
  *((volatile unsigned char *)(0xde00))=12;//将数据写入相应的flash地址
    for(c=0;c<350;c++);
    FLCR_PGM=0;            //0->PGM  
    for(c=0;c<100;c++);    //10us
    FLCR_HVEN=0;           //0->HVEN 
    for(c=0;c<100;c++);    //10us
       
  }
现在在地址0xde00里写char类型的数据没有问题,但是如何写超过255的数呢
譬如我想写3456,我将DoWriteFlash改为
*((volatile unsigned char *)(0xde00))=34;//将数据写入相应的flash地址
    for(c=0;c<350;c++);
*((volatile unsigned char *)(0xde01))=56;//将数据写入相应的flash地址
    for(c=0;c<350;c++);

可是为什么不对呢?

相关帖子

沙发
mcuall| | 2007-5-26 14:19 | 只看该作者

一次只能写一个吧

使用特权

评论回复
板凳
dianqi123|  楼主 | 2007-5-26 15:38 | 只看该作者

如果一次写一个那写一个int型数据怎么写呢?譬如3456

如果一次写一个那写一个int型数据怎么写呢?譬如3456

使用特权

评论回复
地板
computer00| | 2007-5-26 15:50 | 只看该作者

3456是十进制的吧? 要转换为十六进制才能写入

3456转换为十六进制就是0xD80, 还要看你系统是大端结构还是小端结构。

如果是大端结构,则将0x0D写在前面的地址,而0x80写在后面的地址.
如果是小端结构,则刚好相反.


自己转换比较麻烦,可以直接在程序里写,使用移位操作,


*((volatile unsigned char *)(0xde00))=(3456>>8);//将数据写入相应的flash地址
    for(c=0;c<350;c++);
*((volatile unsigned char *)(0xde01))=(3456&0xFF);//将数据写入相应的flash地址
    for(c=0;c<350;c++);

使用特权

评论回复
5
张明峰| | 2007-5-27 06:49 | 只看该作者

楼主应该了解一下数据表达方式

8位单片机中一个8位宽的字节是最基本的数据描述单位,其他所有数据类型,如int、long、float等都是由多个字节构成。你现在可以将1个字节写入Flash,那就重复写入该过程将其他字节顺叙写入即可。

使用特权

评论回复
6
free_tech| | 2007-5-28 08:57 | 只看该作者

支持页写功能

你可以一次写入16个字节,准备好要写入的数据,可以一次写入8个INT型

使用特权

评论回复
7
dianqi123|  楼主 | 2007-5-29 17:37 | 只看该作者

既然可以

使用特权

评论回复
8
dianqi123|  楼主 | 2007-5-29 17:41 | 只看该作者

既然可以一次写入8个int数据,为什么按照我的写法写3456不对

既然可以一次写入8个int数据,为什么按照我的写法写3456不对呢

使用特权

评论回复
9
dianqi123|  楼主 | 2007-5-29 17:49 | 只看该作者

一定要先转换成16进制才能写马?

一定要先转换成16进制才能写马?为什么我写char类型小于255都可以

使用特权

评论回复
10
computer00| | 2007-5-30 02:17 | 只看该作者

晕晕晕....楼主还没弄明白....

一个16位的整型分成2个字节,字节1和字节2.

你往字节1写入了34,往字节2写入了56,那么读回来的结果是多少?

就是34*256+56,而不是3456. 3456是我们十进制的写法,可是MCU里面的高字节
和低字节里面可不是分别保存着3456,而是对应的十六进制的高字节和低字节。
如果照你所想,那一个16位的int岂不是最大是255255了??? 可实际上16位的
最大值是65535,即255*256+255. 而不是直接将两个十进制的连起来,而应该将
两个十六进制的连起来,既0xFFFF.

使用特权

评论回复
11
HotPower| | 2007-5-30 03:30 | 只看该作者

不喜欢这种写法,确实有些晕~~~

使用特权

评论回复
12
free_tech| | 2007-5-30 08:35 | 只看该作者

对dianqi123:010101010101。。。

计算机只认0和1,所谓的int 就是16位最大1111 1111 1111 1111,8位 机一次
只处理8个位,它的数据线是8位.一次只能写byte,   3456,=0b0000 1101 1000 0000,超出处理能力,所以必须分成2个8位来处理,多看一些汇编例子

使用特权

评论回复
13
dianqi123|  楼主 | 2007-5-30 17:03 | 只看该作者

多谢老师的解答

参照了各位老师的建议,现在int型数据可以写入了,是转化成16进制写的,但又出现了一个问题,具体程序如下:
 *((volatile unsigned char *)(0xde00))=(3456>>8);//将数据写入相应的flash地址
    for(c=0;c<350;c++);
    *((volatile unsigned char *)(0xde01))=(3456&0xFF);//将数据写入相应的flash地址
    for(c=0;c<350;c++);
    *((volatile unsigned char *)(0xde02))=(1278>>8);//将数据写入相应的flash地址
    for(c=0;c<350;c++);
    *((volatile unsigned char *)(0xde03))=(1278&0xFF);//将数据写入相应的flash地址 
我现在想存两个数据,3456,1278,我如果单独存其中一个都没有问题,但是为什么存两个就老是复位,不知道什么原因 
    

使用特权

评论回复
14
dianqi123|  楼主 | 2007-5-30 17:29 | 只看该作者

为什么不能连续写数据

使用特权

评论回复
15
dianqi123|  楼主 | 2007-5-30 18:37 | 只看该作者

如何往flash里写入多个int型数据

使用特权

评论回复
16
dianqi123|  楼主 | 2007-5-31 10:18 | 只看该作者

如何写呢

写flash的时候遇到一个问题,我想保存的数据存的起始地址是0xde00,
譬如存入3456,
 *((volatile unsigned char *)(0xde00))=(3456>>8);//将数据写入相应的flash地址
    for(c=0;c<350;c++);
  *((volatile unsigned char *)(0xde01))=(3456&0xFF);//将数据写入相应的flash地址

    for(c=0;c<350;c++);
读的时候
 m=*((volatile unsigned char *)(0xde00)); //00,01地址写入KWH
   n=*((volatile unsigned char *)(0xde01));
  m=m<<8;
  kwh=m+n;  读出的数据没有问题
现在我想存两个int型数据,如3456,1278,仍采用上述方法,将1278存在0xde02,0xde0
3地址,程序如下:
 *((volatile unsigned char *)(0xde00))=(3456>>8);//将数据写入相应的flash地址
    for(c=0;c<350;c++);
  *((volatile unsigned char *)(0xde01))=(3456&0xFF);//将数据写入相应的flash地址

    for(c=0;c<350;c++);
  *((volatile unsigned char *)(0xde02))=(1278>>8);//将数据写入相应的flash地址

    for(c=0;c<350;c++);
*((volatile unsigned char *)(0xde03))=(1278&0xFF);//将数据写入相应的flash地址 
 
    for(c=0;c<350;c++);
读的时候m=*((volatile unsigned char *)(0xde00)); //00,01地址写入KWH
   n=*((volatile unsigned char *)(0xde01));//将数据写入相应的flash地址
   p=*((volatile unsigned char *)(0xde02));//02,03地址写入WH
   q=*((volatile unsigned char *)(0xde03));//将数据写入相应的flash地址
   m=m<<8;
   p=p<<8;
   kwh=m+n;
   dwh=p+q; 
这时候却老出现复位的现象,不知程序哪里有问题

使用特权

评论回复
17
dianqi123|  楼主 | 2007-5-31 14:29 | 只看该作者

老师,很多初学者flash的编程都存在问题

包括如何写道RAM中去执行

使用特权

评论回复
18
dianqi123|  楼主 | 2007-6-1 10:09 | 只看该作者

老师帮下忙

使用特权

评论回复
19
张明峰| | 2007-6-1 12:22 | 只看该作者

读数据太夸张了点

kwh = *((unsigned int *)0xde00);
dwh = *((unsigned int *)0xde02);

使用特权

评论回复
20
张明峰| | 2007-6-1 12:48 | 只看该作者

基于9S08AW32的参考代码

#pragma DATA_SEG DEFALUT        //default data segment
volatile byte ramCode[64]; //开辟64字节RAM区为Flash编程专用

//==============================================================
// Read a string of byte from EEPROM (Flash emulated)
//==============================================================
void ReadEE(byte* eeAddr, byte* datBuff, byte byteCount)
{
   while(byteCount) {
      *datBuff++ = *eeAddr++;
      byteCount--;
   }
}

//==============================================================
// Code to enable and poll for Flash programming
// Must copy into RAM area before actual calling
//==============================================================
byte ExecEePrgCmd(byte cmd)
{
      FCMD = cmd;              //set command
      FSTAT_FCBEF = 1;         //command launched and FCBEF cleared
      NOP();                   //wait at least 4 nop
      NOP();
      NOP();
      NOP();
      if (FSTAT_FPVIOL || FSTAT_FACCERR) { //exit if encounter any error
         return(0);
      }
      while(!FSTAT_FCCF)                   //wait for FCCF=1
         __RESET_WATCHDOG();               
      return(1);
}

//==============================================================
// Write a string of byte to EEPROM (Flash emulated)
//==============================================================
void WriteEE(byte* eeAddr, byte* datBuff, byte byteCount)
{
   byte i;
   byte *srcPtr, *dstPtr;
   byte (*FuncInRam)(byte);
   
   //Copy ExecEePrgCmd code into RAM
   srcPtr = (byte*)ExecEePrgCmd;     //function entry in Flash
   dstPtr = ramCode;                //function entry in RAM
   for (i=0;i<64;i++) {             //do byte copy
      dstPtr = srcPtr;
   }
   FuncInRam = (byte (*)(byte))ramCode;
   
   FSTAT_FACCERR = 1; //clear any pending Flash error flag
   
   while (byteCount) {
      *eeAddr++ = *datBuff++;               //latch data byte and memory address
      DisableInterrupts;
      FuncInRam(0x20);                      //byte program, single byte mode
      EnableInterrupts;
      byteCount--;
   }
}

//==============================================================
// Erase a page of EEPROM (Flash emulated)
//==============================================================
void EraseEE(byte* eeAddr)
{
   byte i;
   byte *srcPtr, *dstPtr;
   byte (*FuncInRam)(byte);
   
   //Copy ExecEePrgCmd code into RAM
   srcPtr = (byte*)ExecEePrgCmd;     //function entry in Flash
   dstPtr = ramCode;                //function entry in RAM
   for (i=0;i<64;i++) {             //do byte copy
      dstPtr = srcPtr;
   }
   FuncInRam = (byte (*)(byte))ramCode;
   
   FSTAT_FACCERR = 1; //clear any pending Flash error flag
   
   *eeAddr = 0;       //latch memory address
   DisableInterrupts;
   FuncInRam(0x40);   //do page erase
   EnableInterrupts;
}

上述代码摘自本人编写的一个DIY设计(完成我老爸交给的一个控制任务),运行于9S08AW32/60芯片。基本上适用于其他9S08系列,但不能用于908系列。
由于RAM的大量富裕,所以单独开辟64字节RAM(ramCode)为Flash编程关键代码的运行区。实际代码长度(ExecEePrgCmd模块)可能随C编译器优化级别的设置稍有变化,但不会超过64字节。你可以将ramCode定义在调用函数的堆栈区(和FuncInRam类似的局部变量),但要确保整个项目所定义的堆栈区有足够的空间。

最后对dianqi123提一些建议:1)多看看芯片数据手册,Flash编程的流程写得很详细,照着做就可以,我就是照着做的,没有其它窍门;2)仔细领会C语言编程的基本技术。看了你的代码,就算Flash能编程了,你的设计最后能否可靠运行还是个大问号;3)必须理解最最基本的数据在单片机内存储和表达方式;4)成功要靠自己的努力钻研,而不是守株待兔。

使用特权

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

本版积分规则

3

主题

19

帖子

0

粉丝