目录

1、理论

2、实践


1、理论

众所周知,单片机复位后变量数值会自动初始化,以华大半导体HC32L136为例,具有 7 个复位信号来源,每个复位信号都可以让 CPU 重新运行,绝大多数寄存器会被复位到复位值,程序会从复位向量处开始执行。

  • 数字区域上电掉电复位 POR
  • 外部 Reset PAD,低电平为复位信号
  • WDT 复位
  • PCA 复位
  • LVD 低电压复位
  • Cortex-M0+ SYSRESETREQ 软件复位
  • Cortex-M0+ LOCKUP 硬件复位

每个复位源由相应的复位标志进行指示,复位标志均由硬件置位,需要用户软件清零。

华大半导体各区域的复位来源如下图所示:

本篇博客主要讲授华大半导(STM32、C51等单片机均可适用)复位(以看门狗复位为例)后变量数据保存的方法。

这里将用到__not_init属性,其用于变量声明,可禁止系统启动时变量的初始化,有了__not_init属性,编译器只给指定变量分配空间,不会再初始化。

__not_init的两种定义方式如下所示:

    方式1:不指定存储位置,由编译器分配__no_init 类型 变量名;        ///< 例如:__no_init uint8_t cou_num;方式2:指定存储位置__no_init 类型 变量名 @地址;  ///< 例如:__no_init uint8_t cou_num @0x20000000;

2、实践

实践描述:使用__no_init属性创建一个变量cou_num,其将数据存储在SRAM中,每隔300毫秒自加1并通过串口打印输出数值,当检测到上电复位和按键复位后,变量cou_num数值置为0,在看门狗复位下变量cou_num数值不变。

第1步:配置串口引脚、串口使能和串口中断,代码如下所示:

///< 串口引脚配置
static void App_PortInit(void)
{stc_gpio_cfg_t stcGpioCfg;DDL_ZERO_STRUCT(stcGpioCfg);///< 使能GPIO模块时钟Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE); ///< 配置PA02端口为URART1_TXstcGpioCfg.enDir = GpioDirOut;Gpio_Init(GpioPortA, GpioPin2, &stcGpioCfg);Gpio_SetAfMode(GpioPortA, GpioPin2, GpioAf1);
}///< 串口配置
static void App_UartCfg(void)
{stc_uart_cfg_t    stcCfg;DDL_ZERO_STRUCT(stcCfg);///< 开启UART1外设时钟Sysctrl_SetPeripheralGate(SysctrlPeripheralUart1,TRUE);///< UART1初始化stcCfg.enRunMode        = UartMskMode3;           ///< 模式3stcCfg.enStopBit        = UartMsk1bit;            ///< 1bit停止位stcCfg.enMmdorCk        = UartMskEven;            ///< 偶检验stcCfg.stcBaud.u32Baud  = 9600;                   ///< 波特率9600  注意误差stcCfg.stcBaud.enClkDiv = UartMsk8Or16Div;        ///< 通道采样分频配置stcCfg.stcBaud.u32Pclk  = Sysctrl_GetPClkFreq();  ///< 获得外设时钟(PCLK)频率值Uart_Init(M0P_UART1, &stcCfg);                    ///< 串口初始化///< UART1中断使能Uart_ClrStatus(M0P_UART1,UartTC);                 ///< 清发送请求Uart_EnableIrq(M0P_UART1,UartTxIrq);              ///< 使能串口发送中断EnableNvic(UART1_IRQn, IrqLevel3, TRUE);          ///< 系统中断使能
}///< UART1中断函数
void Uart1_IRQHandler(void)
{///< UART1数据发送if(Uart_GetStatus(M0P_UART1, UartTC))         {///< 清中断状态位Uart_ClrStatus(M0P_UART1, UartTC);  }
}

第2步:配置看门狗复位,每隔820毫秒若没有喂狗,则复位,代码如下所示:

///< WDT初始化配置
static void App_WdtInit(void)
{///< 开启WDT外设时钟Sysctrl_SetPeripheralGate(SysctrlPeripheralWdt,TRUE);///< WDT 初始化,喂狗时间:820msWdt_Init(WdtResetEn, WdtT820ms);
}

第3步:使用__no_init属性定义cou_num变量,将数组存储在SRAM寄存器0x20001000中,代码如下所示:

__no_init uint8_t cou_num @ 0x20001000;

第4步:添加上电复位源和RESET脚复位源检测,当检测到其中之一个复位的时候,cou_num置为0,代码如下所示:

int32_t main(void)
{char * data_buf = (char *)malloc(sizeof(char) * 19);///< 串口引脚配置App_PortInit();///< 串口配置App_UartCfg();///< WDT初始化App_WdtInit();///< 启动 WDTWdt_Start();///< 当上电复位或者RESET脚复位后cou_num为0,看门狗复位数值不变if((Reset_GetFlag(ResetFlagMskPor5V) == 1) || (Reset_GetFlag(ResetFlagMskRstb) == 1)){cou_num = 0;Reset_ClearFlag(ResetFlagMskPor5V);Reset_ClearFlag(ResetFlagMskRstb);}while (1){cou_num = cou_num + 1;delay1ms(300);///< 开启喂狗后,将不会产生复位//Wdt_Feed(); sprintf(data_buf,"numerical value:%d\n",cou_num);for(int8_t i = 0;i < 19;i++){Uart_SendDataIt(M0P_UART1,data_buf[i]); delay1ms(5);}}
}

运行效果如下所示:

可见虽然看门狗每隔820毫秒复位一次,但是cou_num数值不收影响,但是也可以看出cou_num数值中间存在丢失,例如没有打印输出数值3,主要原因是运行到此数时,恰巧看门狗复位,所以串口未来得及打印,但是不影响cou_num计数。

单片机异常复位后如何保存变量数据相关推荐

  1. STM32单片机VCAP电容太小引起内核电压波动导致单片机异常复位

    问题:现象1:上位机记录的角度从-90.3°变为0,现象2:有时甚至不回复数据 在线调试发现单片机死机,使用软件RST复位之后查看RCC_CSR寄存器发现并不是程序里的看门狗复位排除是软件看门狗复位引 ...

  2. 7.2 一次产品异常复位引发的质量提升经历

    借助在跨国公司的研发经历,我得以带着大家漫游一次产品质量之旅.然而,知道并非做到,看似触手可及,但又好似隔着万水千山.明明知道采用那些策略可以有效的提升产品质量,然而现实世界中的自己却长时间无动于衷. ...

  3. 51单片机串口SBUF是特殊寄存器,只要不写入新的数据就不会消失,写入新的数据就会覆盖之前的,单片机复位后初始值为不确定值

    如题,请问51单片机接收数据的SBUF能存活多久呢? 比如下面这个串口中断复函函数(片段),我将接收中断标志RI清0之后,SBUF的值多久会消失呢? unsigned char data = 0; v ...

  4. 单片机复位后为什么要对sp重新赋值_单片机系统抗干扰,软件 VS 硬件哪个重要?...

    在提高硬件系统抗干扰能力的同时,软件抗干扰以其设计灵活.节省硬件资源.可靠性好越来越受到重视.下面以MCS-51单片机系统为例,对微机系统软件抗干扰方法进行研究. 1.软件抗干扰方法的研究在工程实践中 ...

  5. 单片机学习之IIC协议用24C02连续保存读取数据

    刚学单片机C语言,记录学习IIC协议用24C02连续保存读取数据成功: 1.根据24C02的数据手册先画流程图,如下: 2.在.H头文件中进行 GPIO脚位定义与初始化: sbit IO_SDA =P ...

  6. 如何在软件复位后保留指定RAM区域的数据

    文章目录 配置介绍 启动文件 链接文件 主程序 例程测试 环境搭建 功能描述 测试现象 注意事项 1. 另一种实现RAM retention功能的方式 2. 自定义RAM区域的地址问题 3. bool ...

  7. 单片机复位后为什么要对sp重新赋值_常见的单片机复位方式及其原理分析

    为确保设计出的电路系统稳定可靠的工作,必须在电路中加入复位电路--将电路恢复到初始状态.类似于我们使用的电脑,一旦我们电脑死机或发生其他问题,我们会利用重启按钮重启我们的电脑.复位电路亦是如此,一旦我 ...

  8. 单片机断电后不保存程序_为什么单片机语音芯片既有flash又有EEPROM

    为什么单片机语音芯片既有flash又有EEPROM 单片机语音芯片运行时的数据存在于RAM (随机存储器)中,停电后无法保留RAM的数据时,如何在停电后不丢失数据呢?这需要使用EEPROM和FLASH ...

  9. quartus管脚分配后需要保存吗_掉电保存数据到EEPROM

    我想在掉电时保存数据(3 个字节)到 EEPROM 中,用 BOD掉电检测,不知怎样使用.望高手指点: 1. 在 BOOT 区设置好 BODEN,BODLEVEL,后软件还要怎样设置? 2. 掉电中断 ...

最新文章

  1. 从团购网的漏洞看网站安全性问题 -- 安全 -- IT技术博客大学习 -- 共学习 共进步!...
  2. 大型ERP等数据库系统常见几种设计
  3. flink 三种时间机制_Flink1.10入门:时间机制简介
  4. HarmonyOS之AI能力·分词
  5. MapReduce V1:Job提交流程之JobTracker端分析
  6. oracle低权限下获取shell
  7. 【IP分析】合并信号concat,拆分总线slice
  8. Graham 三参数表示法 详解
  9. android 自定义View【2】对话框取色色盘取色的实现
  10. ​我国首个5G消息平台标准发布;华为拿下支付牌照;工业富联、酷派发布2020年业绩报告...
  11. Zemax仿真中像质评价及方法
  12. sai钢笔图层怎么移动某条线?
  13. DOS专题之基本命令
  14. Python高级编程第2版_张亮 阿信(译)_人民邮电出版社_2017-10_v2_完整版
  15. 四大基本反应类型的关系_中学化学中的四种基本反应类型,氧化还原反应和物质的变化!...
  16. 抖音壁纸小程序,星光壁纸小程序2.0版本,升级版
  17. 图片显示方向不对怎么办
  18. TIDB-分布式关系型数据库讲解
  19. C++和opencv实现图像分割(二)
  20. 手把手教你通过solidworks模拟摩擦运动

热门文章

  1. C++ while 循环与 do...while 循环
  2. Android 点击空白出隐藏软键盘
  3. Kotlin的几个面试题
  4. CircularFloatingActionMenu
  5. Java内存溢出详解之Tomcat配置
  6. Go 学习笔记(54)— Go 第三方库之 uber-go/zap/lumberjack(记录日志到文件、支持自动分割日志、支持日志级别、打印调用文件、函数和行号)
  7. 关于 hashcode 和 equals
  8. 用C#钩子写一个改键外挂
  9. WEBSHELL跳板REDUH使用说明
  10. POJ 1189 记忆化搜索