ESP32存储blog笔记
2025-09-10 来源:cnblogs
基于ESP-IDF4.1
1 #include 2 #include 'freertos/FreeRTOS.h' 3 #include 'freertos/task.h' 4 #include 'esp_system.h' 5 #include 'nvs_flash.h' 6 #include 'nvs.h' 7 #include 'driver/gpio.h' 8 9 #define STORAGE_NAMESPACE 'storage' 10 11 12 //保存设备重启数 13 esp_err_t save_restart_counter(void) 14 { 15 nvs_handle_t my_handle; 16 esp_err_t err; 17 18 // 打开 19 err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle); 20 if (err != ESP_OK) return err; 21 22 // 读取 23 int32_t restart_counter = 0; 24 err = nvs_get_i32(my_handle, 'restart_conter', &restart_counter); 25 if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err; 26 27 // 写入 28 restart_counter++; 29 err = nvs_set_i32(my_handle, 'restart_conter', restart_counter); 30 if (err != ESP_OK) return err; 31 32 // 提交写入的值 33 err = nvs_commit(my_handle); 34 if (err != ESP_OK) return err; 35 36 // 关闭 37 nvs_close(my_handle); 38 return ESP_OK; 39 } 40 41 /* Save new run time value in NVS 42 by first reading a table of previously saved values 43 and then adding the new value at the end of the table. 44 Return an error if anything goes wrong 45 during this process. 46 */ 47 esp_err_t save_run_time(void) 48 { 49 nvs_handle_t my_handle; 50 esp_err_t err; 51 52 // 打开 53 err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle); 54 if (err != ESP_OK) return err; 55 56 // 读取内存空间大小 57 size_t required_size = 0; // value will default to 0, if not set yet in NVS 58 err = nvs_get_blob(my_handle, 'run_time', NULL, &required_size); 59 if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err; 60 61 // 读取之前保存的blob 62 uint32_t* run_time = malloc(required_size + sizeof(uint32_t)); 63 if (required_size > 0) { 64 err = nvs_get_blob(my_handle, 'run_time', run_time, &required_size); 65 if (err != ESP_OK) { 66 free(run_time); 67 return err; 68 } 69 } 70 71 // 写入值,包含之前保存的blob 72 required_size += sizeof(uint32_t); 73 run_time[required_size / sizeof(uint32_t) - 1] = xTaskGetTickCount() * portTICK_PERIOD_MS; 74 err = nvs_set_blob(my_handle, 'run_time', run_time, required_size); 75 free(run_time); 76 77 if (err != ESP_OK) return err; 78 79 // 提交 80 err = nvs_commit(my_handle); 81 if (err != ESP_OK) return err; 82 83 // 关闭 84 nvs_close(my_handle); 85 return ESP_OK; 86 } 87 88 89 //从NVS读取和打印重启计数和运行时表 90 esp_err_t print_what_saved(void) 91 { 92 nvs_handle_t my_handle; 93 esp_err_t err; 94 95 // 打开 96 err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle); 97 if (err != ESP_OK) return err; 98 99 // 读取重启数 100 int32_t restart_counter = 0; // NVS没有设置值时需要设置默认值0 101 err = nvs_get_i32(my_handle, 'restart_conter', &restart_counter); 102 if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err; 103 printf('Restart counter = %dn', restart_counter); 104 105 // 读取运行时blob 106 size_t required_size = 0; 107 //获取内存空间存储从NVS读取的blob 108 err = nvs_get_blob(my_handle, 'run_time', NULL, &required_size); 109 if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err; 110 printf('Run time:n'); 111 if (required_size == 0) { 112 printf('Nothing saved yet!n'); 113 } else { 114 //malloc和free是申请内存空间与释放内存空间的函数 115 uint32_t* run_time = malloc(required_size); 116 err = nvs_get_blob(my_handle, 'run_time', run_time, &required_size); 117 if (err != ESP_OK) { 118 free(run_time); 119 return err; 120 } 121 for (int i = 0; i < required_size / sizeof(uint32_t); i++) { 122 printf('%d: %dn', i + 1, run_time[i]); 123 } 124 free(run_time); 125 } 126 127 // 关闭 128 nvs_close(my_handle); 129 return ESP_OK; 130 } 131 132 133 void app_main(void) 134 { 135 esp_err_t err = nvs_flash_init(); 136 if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { 137 // NVS分区被截断,需要擦除并重新初始化 138 ESP_ERROR_CHECK(nvs_flash_erase()); 139 err = nvs_flash_init(); 140 } 141 ESP_ERROR_CHECK( err ); 142 143 err = print_what_saved(); 144 if (err != ESP_OK) printf('Error (%s) reading data from NVS!n', esp_err_to_name(err)); 145 146 err = save_restart_counter(); 147 if (err != ESP_OK) printf('Error (%s) saving restart counter to NVS!n', esp_err_to_name(err)); 148 149 gpio_pad_select_gpio(GPIO_NUM_0); 150 gpio_set_direction(GPIO_NUM_0, GPIO_MODE_DEF_INPUT); 151 152 // 读取GPIO0状态,低电平超过一秒则保存运行时并重启 153 while (1) { 154 if (gpio_get_level(GPIO_NUM_0) == 0) { 155 vTaskDelay(1000 / portTICK_PERIOD_MS); 156 if(gpio_get_level(GPIO_NUM_0) == 0) { 157 err = save_run_time(); 158 if (err != ESP_OK) printf('Error (%s) saving run time blob to NVS!n', esp_err_to_name(err)); 159 printf('Restarting...n'); 160 fflush(stdout); 161 esp_restart(); 162 } 163 } 164 vTaskDelay(200 / portTICK_PERIOD_MS); 165 } 166 }
- ESP32/8266固件备份方法
- upyOS:基于 MicroPython 的模块化操作系统,兼容 ESP32、RP2040 等微控制器
- ESP32与STM32哪个更适合初学者?问题解析与对比
- STM32与ESP32核心应用场景解析及PCB设计实践(深度探讨)
- ESP32与STM32:比较并非明智之举
- ESP32与STM32:性能对比分析及选型指南
- STM32与ESP32:核心差异详解
- 串口、并口、USB、UART及RS232/RS485接口与ESP32、STM32的应用解析
- ESP32音频输入-MAX4466,MAX9814,SPH0645LM4H,INMP441
- ESP32 ADF windows开发环境搭建 适配ADF到ESP32A1S
- 六大全新产品系列推出,MCX A微控制器家族迎来创新
- 意法半导体全新STM32C5系列,重新定义入门级微控制器性能与价值,赋能万千智能设备
- 模组复用与整机重测在SRRC、CCC、CTA/NAL认证中的实践操作指南
- 有源晶振与无源晶振的六大区别详解
- 英飞凌持续巩固全球微控制器市场领导地位
- 使用 Keil Studio for Visual Studio Code开发 STM32 设备
- 从控制到系统:TI利用边缘AI重塑嵌入式MCU的边界
- 蓝牙信道探测技术原理与开发套件实践
- Microchip 推出生产就绪型全栈边缘 AI 解决方案,赋能MCU和MPU实现 智能实时决策
- LoRa、LoRaWAN、NB-IoT与4G DTU技术对比及工业无线方案选型分析




