请教各位,小生最近做个DD,需要考虑系统复位后对RAM的处理,就是说要区分是上电复位还是其它的复位,如果是上电可能要清变量从EEPROM里面抓数据,如果不是上电复位就保持RAM的数据不变化 //有些方法 1)现在的很多单片机提供复位类别标志,程序一开始查这些标志位即可知道是上电复位还是其它复位,如看门狗复位、低电压复位、非法指令复位和非法寻址复位等; 2)如果你用的单片机很不幸地没有提供这些标志,那就只有一个传统办法了:找两个不用的RAM,程序一上来就检查其数据内容是否为0xaa55,若不是,则为上电复位,同时对其赋值为0xaa55;若已经是0xaa55,则为其它复位。但要注意RAM内容在电压很低(0点几伏)时也能维持,所以要能可靠判断上电复位,单片机必须彻底放电。 // 感谢教主指点 我用的是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这个寄存器,可能代码中还有些问题,我再看看,谢谢教主!! // 我想了想在RAM付值的这种办法判断是否是上电复位,可能要注意以下几个地方吧 1:如果是汇编好处理,直接判断,如果是C语言,如果是FSL的MCU是不是要改PRM文件,在里面化个_in_init的区域来声明个变量 2:如果是PIC16的要把RAN_INIT_CODE声明成persistent吧,而且只在这个地方做了一下付值,后面就没有用了,编译器会不会把它给优化了? 3:如果是C18,C18不会预处理变量,直接付值比较就可以了 4:刚才判断"上电复位"寄存器RAM值不对的原因是MCU没有彻底掉电,一个I/O检测电池电压,挂了大电容,通过I/O的保护二极管到电源,所以没有彻底复位 //差不多啦 注意变量类型 volatile unsigned char RAN_INIT_CODE 是不行地。要int才可以 C的话确实要注意静态变量被Startup模块自动清零的问题,你的考虑是正确的。有很多种做法,按芯片和编译器不一而论。 // 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一个特殊值的办法就可以搞定了,不用这么复杂 不知道小生的理解对不对 // 说是这么说,可什么样的值才是“特殊值”这可是大讲究。AA55就是最特殊的一个!“祖传秘方,包用包好” // 效果很好,值得推荐,我把这种设定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也可以吧
本文目录
本文目录