[ESP8266学习笔记]components_nvs 非易失性存储 Non-Volatile Storage(NVS),保存数据到flash
1.简介
有时我们需要保存一些信息,然后在下次启动时使用。
我们希望这些数据在掉电的时候不会丢失。esp8266没有自己的rom,所以我们需要保存在外部flash中。
官方已经为我们提供了很多api,我们可以直接使用SDK中的components。
SDK编译环境搭建:https://blog.csdn.net/valonshen/article/details/104124127
由于esp8266文档中没有相关说明,参考esp32:https://docs.espressif.com/projects/esp-idf/zh_CN/latest/api-reference/storage/nvs_flash.html#
非易失性存储 (NVS) 库主要用于在 flash 中存储键值格式的数据。NVS 最适合存储一些较小的数据,而非字符串或二进制大对象 (BLOB) 等较大的数据。如需存储较大的 BLOB 或者字符串,请考虑使用基于磨损均衡库的 FAT 文件系统。
NVS 的操作对象为键值对,其中键是 ASCII 字符串,当前支持最大键长为 15 个字符,值可以为以下几种类型:
- 整数型:uint8_t、int8_t、uint16_t、int16_t、uint32_t、int32_t、uint64_t 和 int64_t;
- 以 \0 结尾的字符串;
- 可变长度的二进制数据 (BLOB)
2. 部分API介绍
esp_err_t nvs_flash_init(void)
初始化默认NVS分区,需要在其他API调用之前调用。esp8266将flash分成几个分区,每个分区的地址偏移和大小都可以自行配置,我会在另一个文章在介绍。
返回值:
- ESP_OK if storage was successfully initialized.
- ESP_ERR_NVS_NO_FREE_PAGES if the NVS storage contains no empty pages (which may happen if NVS partition was truncated)
- ESP_ERR_NOT_FOUND if no partition with label “nvs” is found in the partition table one of the error codes from the underlying
flash storage driver
esp_err_t nvs_flash_erase(void)
擦除默认NVS分区所有数据。若要继续使用,需调用nvs_flash_init初始化。
返回值:
- ESP_OK on success
- ESP_ERR_NOT_FOUND if there is no NVS partition labeled “nvs” in the partition table
esp_err_t nvs_open(const char *name, nvs_open_mode_t open_mode, nvs_handle_t * out_handle)
void nvs_close(nvs_handle_t handle)
用于打开和关闭 NVS分区。name为最多15字节的命名空间,用于防止键值对名称的冲突。在不同的命名空间中允许出现相同名称的键值对,但在同一个命名空间中键值对的名称是唯一的。handle用于后续读写键值对操作。
目前使用esp8266的SDK,nvs打开的句柄类型需改成 nvs_handle,而esp-ief是nvs_handle_t
返回值:
- ESP_OK if storage handle was opened successfully
- ESP_ERR_NVS_NOT_INITIALIZED if the storage driver is not initialized
- ESP_ERR_NVS_PART_NOT_FOUND if the partition with label “nvs” is not found
- ESP_ERR_NVS_NOT_FOUND id namespace doesn’t exist yet and mode is NVS_READONLY
- ESP_ERR_NVS_INVALID_NAME if namespace name doesn’t satisfy constraints
- other error codes from the underlying storage driver
参数:
- name: Namespace name. Maximal length is determined by the underlying implementation, but is guaranteed to be at least 15 characters. Shouldn’t be empty.
- open_mode: NVS_READWRITE or NVS_READONLY. If NVS_READONLY, will open a handle for reading only. All write requests will be rejected for this handle.
- out_handle: If successful (return code is zero), handle will be returned in this argument.
esp_err_t nvs_set_i8(nvs_handle_t handle, const char *key, int8_t value)
esp_err_t nvs_set_u8(nvs_handle_t handle, const char *key, uint8_t value)
esp_err_t nvs_set_i16(nvs_handle_t handle, const char *key, int16_t value)
esp_err_t nvs_set_u16(nvs_handle_t handle, const char *key, uint16_t value)
esp_err_t nvs_set_i32(nvs_handle_t handle, const char *key, int32_t value)
esp_err_t nvs_set_u32(nvs_handle_t handle, const char *key, uint32_t value)
esp_err_t nvs_set_i64(nvs_handle_t handle, const char *key, int64_t value)
esp_err_t nvs_set_u64(nvs_handle_t handle, const char *key, uint64_t value)
esp_err_t nvs_set_str(nvs_handle_t handle, const char *key, const char *value)
esp_err_t nvs_get_i8(nvs_handle_t handle, const char *key, int8_t *out_value)
保存数值键值对,键的名字在同一命名空间内必须保持唯一,支持最长15字节的ASCII字符串。实际的存储操作将在nvs_commit被调用时完成。
返回值:
- ESP_OK if value was set successfully
- ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
- ESP_ERR_NVS_READ_ONLY if storage handle was opened as read only
- ESP_ERR_NVS_INVALID_NAME if key name doesn’t satisfy constraints
- ESP_ERR_NVS_NOT_ENOUGH_SPACE if there is not enough space in the underlying storage to save the value
- ESP_ERR_NVS_REMOVE_FAILED if the value wasn’t updated because flash write operation has failed. The value was written however, and update will be finished after re-initialization of nvs, provided that flash operation doesn’t fail again.
- ESP_ERR_NVS_VALUE_TOO_LONG if the string value is too long
参数:
- handle: Handle obtained from nvs_open function. Handles that were opened read only cannot be used.
- key: Key name. Maximal length is determined by the underlying implementation, but is guaranteed to be at least 15
- characters. Shouldn’t be empty.
- value: The value to set. For strings, the maximum length (including null character) is 4000 bytes.
esp_err_t nvs_get_u8(nvs_handle_t handle, const char *key, uint8_t *out_value)
esp_err_t nvs_get_i16(nvs_handle_t handle, const char *key, int16_t *out_value)
esp_err_t nvs_get_u16(nvs_handle_t handle, const char *key, uint16_t *out_value)
esp_err_t nvs_get_i32(nvs_handle_t handle, const char *key, int32_t *out_value)
esp_err_t nvs_get_u32(nvs_handle_t handle, const char *key, uint32_t *out_value)
esp_err_t nvs_get_i64(nvs_handle_t handle, const char *key, int64_t *out_value)
esp_err_t nvs_get_u64(nvs_handle_t handle, const char *key, uint64_t *out_value)
esp_err_t nvs_get_str(nvs_handle_t handle, const char *key, char *out_value, size_t *length)
读取相应键值对的数据。
返回值
- ESP_OK if the value was retrieved successfully
- ESP_ERR_NVS_NOT_FOUND if the requested key doesn’t exist
- ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
- ESP_ERR_NVS_INVALID_NAME if key name doesn’t satisfy constraints
- ESP_ERR_NVS_INVALID_LENGTH if length is not sufficient to store data
参数:
- handle: Handle obtained from nvs_open function.
- key: Key name. Maximal length is determined by the underlying implementation, but is guaranteed to be at least 15
- characters. Shouldn’t be empty.
- out_value: Pointer to the output value. May be NULL for nvs_get_str and nvs_get_blob, in this case required length will be returned in length argument.
- length: A non-zero pointer to the variable holding the length of out_value. In case out_value a zero, will be set to the length required to hold the value. In case out_value is not zero, will be set to the actual length of the value written. For nvs_get_str this includes zero terminator.
esp_err_t nvs_commit(nvs_handle_t handle)
将修改的键值对写入flash。所以操作过键值对后,执行此命令。
返回值:
- ESP_OK if the changes have been written successfully
- ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
- other error codes from the underlying storage driver
参数:
- handle: Storage handle obtained with nvs_open. Handles that were opened read only cannot be used.
esp_err_t nvs_erase_key(nvs_handle_t handle, const char *key)
擦除某一命名空间的键值对。
3. 代码示例
#include <string.h>
#include <stdlib.h>
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "nvs.h"
static const char* TAG = "main";
void app_main(void)
{
size_t length;
char* buf ;
// Initialize NVS
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
// NVS partition was truncated and needs to be erased
// Retry nvs_flash_init
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_ERROR_CHECK( err );
// Open
printf("\n");
printf("Opening Non-Volatile Storage (NVS) handle... ");
nvs_handle my_handle;
err = nvs_open("storage", NVS_READWRITE, &my_handle);
if (err != ESP_OK) {
printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err));
} else {
printf("Done\n");
}
// Read
printf("Reading string from NVS ... \r\n");
//若传入的buffer为null,数据长度将保存在length中
err = nvs_get_str(my_handle, "string", NULL,&length);
switch (err) {
case ESP_OK:
buf = (char*)malloc(length);
if(nvs_get_str(my_handle,"string",buf,&length) == ESP_OK){
ESP_LOGI(TAG,"get NVS data key: string, value: %s",buf);
}
else{
ESP_LOGE(TAG,"get NVS data fault");
}
free(buf);
nvs_erase_key(my_handle,"string");
ESP_LOGI(TAG,"erase key");
break;
case ESP_ERR_NVS_NOT_FOUND:
ESP_LOGI(TAG,"no found NVS Key");
if( nvs_set_str(my_handle,"string","exampleString") == ESP_OK ){
ESP_LOGI(TAG,"write key");
}
else{
ESP_LOGE(TAG,"nvs key write fault");
}
break;
default :
printf("Error (%s) reading!\n", esp_err_to_name(err));
}
//需要commit才能生效修改
nvs_commit(my_handle);
nvs_close(my_handle);
vTaskDelay(800);
esp_restart();
}
执行
idf.py flash monitor
将打印如下信息:
第一次打印
Opening Non-Volatile Storage (NVS) handle… Done
Reading string from NVS …
I (305) main: no found NVS Key
I (312) main: write key
Done
等待8s重启,第二次打印
Opening Non-Volatile Storage (NVS) handle… Done
Reading string from NVS …
I (306) main: get NVS data key: string, value: exampleString
I (317) main: erase key
更多推荐



所有评论(0)