打印

关于复位后RAM处理的问题

[复制链接]
4088|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
soso|  楼主 | 2008-9-17 11:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
张明峰| | 2008-9-17 12:50 | 只看该作者

有些方法

1)现在的很多单片机提供复位类别标志,程序一开始查这些标志位即可知道是上电复位还是其它复位,如看门狗复位、低电压复位、非法指令复位和非法寻址复位等;
2)如果你用的单片机很不幸地没有提供这些标志,那就只有一个传统办法了:找两个不用的RAM,程序一上来就检查其数据内容是否为0xaa55,若不是,则为上电复位,同时对其赋值为0xaa55;若已经是0xaa55,则为其它复位。但要注意RAM内容在电压很低(0点几伏)时也能维持,所以要能可靠判断上电复位,单片机必须彻底放电。

使用特权

评论回复
板凳
soso|  楼主 | 2008-9-17 13:26 | 只看该作者

感谢教主指点

我用的是PIC18F6520
RCON &= 0x1f;//Note: Close IPEN
   if ( RCONbits.RI && RCONbits.TO && RCONbits.PD && (!RCONbits.POR) && (!RCONbits.BOR))
    {//是初次上电    
        RCONbits.POR = 1;
        RCONbits.BOR = 1;
        ASensorSingleDoNum = 0;//A传感器单只工作次数
           BSensorSingleDoNum = 0;;//B传感器单只工作次数
           PulseAvailTemp = 0;    //脉冲有效寄存器
           Key.allbits = 0;
           RunFlag.allbits = 0;
           ScanFlag.allbits = 0;
           BJFLAG.allbits = 0;
        ChooseFLag.allbits = 0;    
        EETORam();
        ReturnRunFlag();
    }
   else //if ( RAN_INIT_CODE == 0x3c)
    {//不是初次上电
       if( !RCONbits.RI )
        RCONbits.RI = 1;//Do  RESET
        CheckRAM();
       if( BJFLAG.Bits.RamCrcErr)
        {
           ReturnRunFlag();
           BJFLAG.Bits.RamCrcErr = 0;
           GasValueToEE();
           OtherDataToEE();
           MonthUseToEE();
        }
    }
这个上电复位的程序在使用的时候,就是有个标志的RAM会乱掉,我知道教主另外一个意思,应该是
volatile unsigned char RAN_INIT_CODE;
void main(void)
{
 if( RAN_INIT_CODE != 0xaa55)
  {//是初次上电    
        RAN_INIT_CODE  = 0xaa55;
               ASensorSingleDoNum = 0;//A传感器单只工作次数
           BSensorSingleDoNum = 0;;//B传感器单只工作次数
           PulseAvailTemp = 0;    //脉冲有效寄存器
           Key.allbits = 0;
           RunFlag.allbits = 0;
           ScanFlag.allbits = 0;
           BJFLAG.allbits = 0;
        ChooseFLag.allbits = 0;    
        EETORam();
        ReturnRunFlag();
    }
   else 
    {//不是初次上电
        CheckRAM();
       if( BJFLAG.Bits.RamCrcErr)
        {
           ReturnRunFlag();
           BJFLAG.Bits.RamCrcErr = 0;
           GasValueToEE();
           OtherDataToEE();
           MonthUseToEE();
        }
    }

}
我之前用的是一个字节,而且用的不是0xaa55,用的是随意写的一个好象效果不是很好,就用判断RCON这个寄存器,可能代码中还有些问题,我再看看,谢谢教主!!

使用特权

评论回复
地板
soso|  楼主 | 2008-9-17 14:21 | 只看该作者

我想了想在RAM付值的这种办法判断是否是上电

我想了想在RAM付值的这种办法判断是否是上电复位,可能要注意以下几个地方吧
 1:如果是汇编好处理,直接判断,如果是C语言,如果是FSL的MCU是不是要改PRM文件,在里面化个_in_init的区域来声明个变量
 2:如果是PIC16的要把RAN_INIT_CODE声明成persistent吧,而且只在这个地方做了一下付值,后面就没有用了,编译器会不会把它给优化了?
 3:如果是C18,C18不会预处理变量,直接付值比较就可以了
 4:刚才判断"上电复位"寄存器RAM值不对的原因是MCU没有彻底掉电,一个I/O检测电池电压,挂了大电容,通过I/O的保护二极管到电源,所以没有彻底复位

使用特权

评论回复
5
张明峰| | 2008-9-17 14:50 | 只看该作者

差不多啦

注意变量类型
volatile unsigned char RAN_INIT_CODE
是不行地。要int才可以

C的话确实要注意静态变量被Startup模块自动清零的问题,你的考虑是正确的。有很多种做法,按芯片和编译器不一而论。

使用特权

评论回复
6
soso|  楼主 | 2008-9-17 15:36 | 只看该作者

判断上电复位RAM不对的真正原因可能是我的烧些器

1:我用的REALICE,它的特点是烧完程序后自动运行,但这个时候它的RCON的值不会是手册上给的状态,所以不会走我预想的真正上电的那个程序分支,但恐怖的是,在我认为的另外一个非上电复位的分支有保存数据到EEPROM,所以就把一些混乱的数据保存了,等我再次重新彻底上电,MCU从真正的上电复位程序开始运行,从EEPROM抓出数据,就是刚才的混乱数据,我想这个问题只有那些烧完程序后,彻底断电复位才能运行的仿真烧写器才能解决.
2:那么我选择的上电复位程序的办法就是把教主的两种方法一起用:-),比如
volatile unsigned int RAN_INIT_CODE;
void main(void)
{
   unsigned char Buff;
   RCON &= 0x1f;//Note: Close IPEN
   if ( RCONbits.RI && RCONbits.TO && RCONbits.PD && (!RCONbits.POR) && (!RCONbits.BOR))
   //
    {//是初次上电    
      if ( RAN_INIT_CODE != 0xaa55 )
       {
        RAN_INIT_CODE = 0xaa55;
        RCONbits.POR = 1;
        RCONbits.BOR = 1;
        ASensorSingleDoNum = 0;//A传感器单只工作次数
           BSensorSingleDoNum = 0;;//B传感器单只工作次数
           PulseAvailTemp = 0;    //脉冲有效寄存器
           Key.allbits = 0;
           RunFlag.allbits = 0;
           ScanFlag.allbits = 0;
           BJFLAG.allbits = 0;
        ChooseFLag.allbits = 0;    
        EETORam();
        ReturnRunFlag();
      }
    }
   else 
    {//不是初次上电
      if( RAN_INIT_CODE == 0xaa55)
       {
               if( !RCONbits.RI )
             RCONbits.RI = 1;//Do  RESET
             CheckRAM();
            if( BJFLAG.Bits.RamCrcErr)
             {
               ReturnRunFlag();
               BJFLAG.Bits.RamCrcErr = 0;
               GasValueToEE();
               OtherDataToEE();
               MonthUseToEE();
             }
       }else{
                RAN_INIT_CODE = 0xaa55;
                RCONbits.POR = 1;
                RCONbits.BOR = 1;
                ASensorSingleDoNum = 0;//A传感器单只工作次数
                   BSensorSingleDoNum = 0;;//B传感器单只工作次数
                   PulseAvailTemp = 0;    //脉冲有效寄存器
                   Key.allbits = 0;
                   RunFlag.allbits = 0;
                   ScanFlag.allbits = 0;
                   BJFLAG.allbits = 0;
                ChooseFLag.allbits = 0;    
                EETORam();
                ReturnRunFlag();
          }
    }
}
3:其实我觉得说不定只要用判断RAM一个特殊值的办法就可以搞定了,不用这么复杂
 不知道小生的理解对不对

使用特权

评论回复
7
张明峰| | 2008-9-18 09:14 | 只看该作者

只要用判断RAM一个特殊值的办法就可以搞定了?

说是这么说,可什么样的值才是“特殊值”这可是大讲究。AA55就是最特殊的一个!“祖传秘方,包用包好”

使用特权

评论回复
8
王培1| | 2008-9-18 13:43 | 只看该作者

效果很好,值得推荐

效果很好,值得推荐,我把这种设定0xaa55的方法也用到RAM的效验和计算上面,比原来效果好多了,哈哈,谢谢教主
RamCrc = ((unsigned int)(RemainValueA.Bytes.RemainValueB[0] ^ RemainValueA.Bytes.RemainValueB[1] 
                ^ RemainValueA.Bytes.RemainValueB[2] ^ RemainValueA.Bytes.RemainValueB[3]
                ^ TotalUseValueA.Bytes.TotalUseValueB[0] ^ TotalUseValueA.Bytes.TotalUseValueB[1]
                ^ TotalUseValueA.Bytes.TotalUseValueB[2] ^ TotalUseValueA.Bytes.TotalUseValueB[3]
                ^ ParaInfo.UserID[0] ^ ParaInfo.UserID[1] ^ ParaInfo.UserID[2] ^ ParaInfo.UserID[3]) | 0x5500)我想这个0x5500换成0xaa00也可以吧

使用特权

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

本版积分规则

0

主题

0

帖子

1

粉丝