poweroff_save_app.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #include "poweroff_save_app.h"
  2. #include "variable.h"
  3. #include "board.h"
  4. #include <string.h>
  5. #include "MathHelper.h"
  6. #define DATA_MAIN_AREA_ADDR 0x1000 //主参数存储区域地址
  7. #define DATA_BACKUP_AREA_ADDR 0x2000 //从参数存储区域地址
  8. //掉电保存数据大小,由于取的是区域的大小,因此需要保证区域大小
  9. #define POWEROFF_SAVE_BLOCK_SIZE (1* 1024)
  10. //上电标志
  11. static unsigned char power_on_flag = 0;
  12. //定时器
  13. static sw_timer_t timer;
  14. static int power_off_sample = 0;
  15. //记录对象实体
  16. //static tiny_log_t tinylog;
  17. //unsigned char log_data[256];
  18. /**
  19. * 掉电工作初始化
  20. * 每次上电时先调用这个函数检查下第一块是否有空的位置让参数去保存,没有就先擦除第二块,然后将第一块的有效参数保存进去
  21. * 然后擦除第一块
  22. *
  23. * @author lxz (2019/5/31/鍛ㄤ簲)
  24. *
  25. * @param void
  26. */
  27. void poweroff_app_init(void) {
  28. int data_valid = 0;
  29. int i = 0;
  30. int retry = 0;
  31. //while (hw_dma_uart_write_finish(2) == 0);
  32. //等待一断时间,检测下看电源是否稳定再操作
  33. sw_timer_start(&timer, POWER_OFF_FUNCTION_DELAY, 0);
  34. while (sw_timer_expire(&timer) == 0);
  35. power_on_flag = hw_power_is_on();
  36. //读取主存储区
  37. for (retry = 0; retry < 3; retry++) {
  38. spi_flash_read(0, DATA_MAIN_AREA_ADDR, (uint8_t *)&user_datas[0], POWEROFF_SAVE_BLOCK_SIZE);
  39. if (mh_crc16_calc((unsigned char *)&user_datas[0], POWEROFF_SAVE_BLOCK_SIZE) == 0) {
  40. //如果数据校验成功,需要将数据转存至备份区域
  41. spi_flash_erase_write(0, DATA_BACKUP_AREA_ADDR, (uint8_t *)&user_datas[0], POWEROFF_SAVE_BLOCK_SIZE);
  42. break;
  43. }
  44. }
  45. //当主存储区数据失败时,读取备份区域的数据
  46. if (retry == 3) {
  47. for (retry = 0; retry < 3; retry++) {
  48. spi_flash_read(0, DATA_BACKUP_AREA_ADDR, (uint8_t *)&user_datas[0], POWEROFF_SAVE_BLOCK_SIZE);
  49. if (mh_crc16_calc((unsigned char *)&user_datas[0], POWEROFF_SAVE_BLOCK_SIZE) == 0) {
  50. break;
  51. }
  52. }
  53. }
  54. //如果备份区域数据也失败,清除参数数据域
  55. if (retry == 3) {
  56. memset(user_datas, 0, POWEROFF_SAVE_BLOCK_SIZE);
  57. }
  58. //擦除主存储数据区域,为下次保存做准备
  59. spi_flash_erase(0, DATA_MAIN_AREA_ADDR, POWEROFF_SAVE_BLOCK_SIZE);
  60. }
  61. /**
  62. * 保存参数
  63. *
  64. * @author lxz (2019/6/12/鍛ㄤ笁)
  65. *
  66. * @param void
  67. */
  68. void app_save_parameter(void) {
  69. INTX_DISABLE();
  70. hw_board_enter_powerless();
  71. //保存一次记录
  72. //log_app_save();
  73. //计算校验码
  74. user_datas[POWEROFF_SAVE_BLOCK_SIZE / 2 - 1] = mh_crc16_calc((unsigned char *)&user_datas[0], POWEROFF_SAVE_BLOCK_SIZE - 2);
  75. //写拉flash
  76. hw_spi_init();
  77. hw_spi_flash_attach(0,0);
  78. spi_flash_write(0, ((uint32_t)DATA_MAIN_AREA_ADDR), (const uint8_t *)&user_datas[0], POWEROFF_SAVE_BLOCK_SIZE);
  79. INTX_ENABLE();
  80. // sw_timer_now(&timer);
  81. //while (timer2.second == timer.second) ;
  82. }
  83. /**
  84. * 掉电的处理函数
  85. *
  86. * @author lxz (2019/6/12/鍛ㄤ笁)
  87. *
  88. * @param void
  89. */
  90. void poweroff_app_run(void) {
  91. //当第一次上电有上电标志的时间,才检测掉电保存
  92. if (power_on_flag) {
  93. //周期检测,管脚滤波
  94. if (sw_timer_expire(&timer)) {
  95. if (hw_power_is_off()) {
  96. power_off_sample++;
  97. }
  98. else if (power_off_sample > 0) {
  99. power_off_sample--;
  100. }
  101. sw_timer_start(&timer, 0, POWER_OFF_SAMPLE_TIME);
  102. }
  103. //确定检测到断电
  104. if (power_off_sample >= POWER_OFF_SAMPLE_COUNT) {
  105. //这里需要调用一次保存
  106. //保存参数
  107. app_save_parameter();
  108. //hw_run_status_set(3);
  109. while (1) {
  110. hw_run_status_show();
  111. }
  112. }
  113. }
  114. else {
  115. //当在掉电状态的时候,程序在运行则一直在执行上电的检测,检测时间为连续的200ms
  116. if (sw_timer_expire(&timer)) {
  117. if (hw_power_is_on()) {
  118. power_off_sample++;
  119. }
  120. else if (power_off_sample > 0) {
  121. power_off_sample--;
  122. }
  123. sw_timer_start(&timer, 0, POWER_OFF_SAMPLE_TIME);
  124. }
  125. if (power_off_sample >= POWER_ON_SAMPLE_COUNT) {
  126. power_on_flag = hw_power_is_on();
  127. }
  128. }
  129. }