由于单片机没有用到看门狗,所以这两种看门狗复位用不到,SWIM复位是烧写程序或者仿真时用的。那就只剩下一个EMC复位、非法操作码复位可以判断。但是更希望看到的是单片机是电源不稳引起的掉电复位还是单片机复位引脚被干扰引起的NRST复位。但是寄存器中没有可以判断这两种复位源的标志位。那么能不能自己想办法来判断这两种复位源呢?
首先分析一下掉电复位和NRST复位的区别,掉电复位也就是单片机完全断电,复位后内存中所有的东西会丢失。NRST复位时内存数据没有丢失,内存中的东西还是复位前存储的数据。那么根据这个特性是不是可以在内存中某个地址存数一个标志。复位后去读取这个标志,如果这个标志和存放的一样,说明单片机没有掉电,属于NRST复位。如果读取到的值不是存储的值那么说明单片机断电了,内存中存储的内容丢失了,属于掉电复位。那么这样就能区分开是掉电复位还是NRST复位了。
写个程序测试了一下,测试结果符合预期。
测试代码如下:
#include "iostm8s103F3.h" #include "main.h" #include "uart.h" #include "stdio.h" void SysClkInit( void ) { CLK_SWR = 0xe1; //HSI为主时钟源 16MHz CPU时钟频率 CLK_CKDIVR = 0x00; //CPU时钟0分频,系统时钟0分频 } void main( void ) { __asm( "sim" ); //禁止中断 SysClkInit(); Uart1_Init( 9600 ); __asm( "rim" ); //开启中断 //复位源判断 if( ( * ( u16* )( 0x000102 ) ) == 0x55 ) //判断0x000100这个地址中存储的值是不是0x55 { printf( " key reset!\r\n" ); //值等于0x55说明是程序写进去的,属于按键复位 } else //如果这个地址的值不等于0x55 说明单片机是刚上电 { printf( " power reset!\r\n" ); //属于上电复位 然后将指定的值写入指定的地址,若单片机不断电,这个值就会一直保持不变 * ( u16* )( 0x000102 ) = 0x55; } if( RST_SR_WWDGF ) { printf( "wwdg reset!\r\n" ); } if( RST_SR_IWDGF ) { printf( "iwdg reset!\r\n" ); } if( RST_SR_ILLOPF ) { printf( "illop reset!\r\n" ); } if( RST_SR_SWIMF ) { printf( "swim reset!\r\n" ); } if( RST_SR_EMCF ) { printf( "emcf reset!\r\n" ); } //WWDG_CR = 0x80; //启动独立看门狗 // IWDG_KR = 0xCC; //启动窗口看门狗 while( 1 ) { } }