STM32 利用FlashDB库实现在线扇区数据管理不丢失

STM32 利用FlashDB库实现在线扇区数据管理不丢失


  • 📍FalshDB地址:https://gitee.com/Armink/FlashDB
  • ✨STM32没有片内EEPROM这样的存储区,虽然有备份寄存器,仅可以实现对少量数据的频繁存储,但是依赖备份电源(BAT引脚)为芯片维持供电,才能保持数据的不丢失。FlashDB库利用在线对片内或片外存储扇区进行管理,可以有效的保存数据,掉电不丢失。在不增加像EEPROM外设的情况下,有效利用内部空余的flash空间,进行数据存储,也可以对片外spi flash存储芯片进行数据管理。类似esp32的NVS空间,也有使用键值对,进行数据存储和管理。
  • 🌿FlashDB库,目前包含STM32F1、F4的相关Keil MDK demo现成的工程例程,可以直接测试使用,可以移植到STM32其他型号单片机上使用。目前是支持STM32和esp8266的。
  • 🧨移植指南:https://armink.gitee.io/flashdb/#/zh-cn/porting
  • 🔖个人使用的是STM32F427进行demo测试,测试结果和说明文档内容相符。
    在这里插入图片描述
  • 🥕以下内容是该项目作者的对其的相关内容的介绍:

📘FlashDB使用场景介绍

  • 🎉如今,物联网产品种类越来越多,运行时产生的数据种类及总量及也在不断变大。FlashDB 提供了多样化的数据存储方案,不仅资源占用小,并且存储容量大,非常适合用于物联网产品。下面是主要应用场景:
  • 键值数据库 :
    • 产品参数存储
    • 用户配置信息存储
    • 小文件管理
  • 时序数据库 :
    存储动态产生的结构化数据:如 温湿度传感器采集的环境监测信息,智能手环实时记录的人体健康信息等
    记录运行日志:存储产品历史的运行日志,异常告警的记录等

KVDB 键值数据库介绍

  • 🌿KVDB 的基础功能的使用:

记录开机次数:

void kvdb_basic_sample(fdb_kvdb_t kvdb)
{struct fdb_blob blob;int boot_count = 0;FDB_INFO("==================== kvdb_basic_sample ====================\n");{ /* GET the KV value *//* get the "boot_count" KV value */fdb_kv_get_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count)));/* the blob.saved.len is more than 0 when get the value successful */if (blob.saved.len > 0) {FDB_INFO("get the 'boot_count' value is %d\n", boot_count);} else {FDB_INFO("get the 'boot_count' failed\n");}}{ /* CHANGE the KV value *//* increase the boot count */boot_count ++;/* change the "boot_count" KV's value */fdb_kv_set_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count)));FDB_INFO("set the 'boot_count' value to %d\n", boot_count);}FDB_INFO("===========================================================\n");
}
  • 🌿字符串类型 KV

字符串 KV 的相关功能,字符串 KV 作为一个特殊的 KV 类型,其 Key 与 Value 均为字符串,常被用于参数存储、命令存储等可读性要求较高的场景。

void kvdb_type_string_sample(fdb_kvdb_t kvdb)
{FDB_INFO("==================== kvdb_type_string_sample ====================\n");{ /* CREATE new Key-Value */char temp_data[10] = "36C";/* It will create new KV node when "temp" KV not in database. */fdb_kv_set(kvdb, "temp", temp_data);FDB_INFO("create the 'temp' string KV, value is: %s\n", temp_data);}{ /* GET the KV value */char *return_value, temp_data[10] = { 0 };/* Get the "temp" KV value.* NOTE: The return value saved in fdb_kv_get's buffer. Please copy away as soon as possible.*/return_value = fdb_kv_get(kvdb, "temp");/* the return value is NULL when get the value failed */if (return_value != NULL) {strncpy(temp_data, return_value, sizeof(temp_data));FDB_INFO("get the 'temp' value is: %s\n", temp_data);}}{ /* CHANGE the KV value */char temp_data[10] = "38C";/* change the "temp" KV's value to "38C" */fdb_kv_set(kvdb, "temp", temp_data);FDB_INFO("set 'temp' value to %s\n", temp_data);}{ /* DELETE the KV by name */fdb_kv_del(kvdb, "temp");FDB_INFO("delete the 'temp' finish\n");}FDB_INFO("===========================================================\n");
}
  • 遍历所有 KV

遍历 KVDB 中的所有 KV ,用户可以在遍历 KV 时增加自己的处理动作。

  • 首先初始化了 KVDB 的迭代器,然后使用迭代器 API ,将 KVDB 的所有 KV 逐一遍历出来。
    遍历出来的 KV 对象含有 KV 的一些属性,包括:key name, value saved addr, value length 等,用户通过 fdb_blob_read 配合 fdb_kv_to_blob 读取出来,做一些自己的业务处理。
void kvdb_tarversal_sample(fdb_kvdb_t kvdb)
{struct fdb_kv_iterator iterator;fdb_kv_t cur_kv;struct fdb_blob blob;size_t data_size;uint8_t *data_buf;fdb_kv_iterator_init(kvdb, &iterator);while (fdb_kv_iterate(kvdb, &iterator)) {cur_kv = &(iterator.curr_kv);data_size = (size_t) cur_kv->value_len;data_buf = (uint8_t *) malloc(data_size);if (data_buf == NULL) {FDB_INFO("Error: malloc failed.\n");break;}fdb_blob_read((fdb_db_t) kvdb, fdb_kv_to_blob(cur_kv, fdb_blob_make(&blob, data_buf, data_size)));/** balabala do what ever you like with blob...*/free(data_buf);}
}

在这里插入图片描述

  • 二进制大对象 (BLOB)

时序数据库

  • TSDB 基础示例,具体介绍:https://armink.gitee.io/flashdb/#/zh-cn/sample-tsdb-basic
  • 该示例主要演示了 TSDB 的基础功能,包括 TSL(时序记录)的追加、查询及状态修改功能。

samples/tsdb_sample.c ,包含追加、查询及状态修改这几个过程,大致代码如下:

void tsdb_sample(fdb_tsdb_t tsdb)
{struct fdb_blob blob;FDB_INFO("==================== tsdb_sample ====================\n");{ /* APPEND new TSL (time series log) */struct env_status status;/* append new log to TSDB */status.temp = 36;status.humi = 85;fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status)));FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi);status.temp = 38;status.humi = 90;fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status)));FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi);}{ /* QUERY the TSDB *//* query all TSL in TSDB by iterator */fdb_tsl_iter(tsdb, query_cb, tsdb);}{ /* QUERY the TSDB by time *//* prepare query time (from 1970-01-01 00:00:00 to 2020-05-05 00:00:00) */struct tm tm_from = { .tm_year = 1970 - 1900, .tm_mon = 0, .tm_mday = 1, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 };struct tm tm_to = { .tm_year = 2020 - 1900, .tm_mon = 4, .tm_mday = 5, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 };time_t from_time = mktime(&tm_from), to_time = mktime(&tm_to);size_t count;/* query all TSL in TSDB by time */fdb_tsl_iter_by_time(tsdb, from_time, to_time, query_by_time_cb, tsdb);/* query all FDB_TSL_WRITE status TSL's count in TSDB by time */count = fdb_tsl_query_count(tsdb, from_time, to_time, FDB_TSL_WRITE);FDB_INFO("query count is: %u\n", count);}{ /* SET the TSL status *//* Change the TSL status by iterator or time iterator* set_status_cb: the change operation will in this callback** NOTE: The actions to modify the state must be in orderC.*       like: FDB_TSL_WRITE -> FDB_TSL_USER_STATUS1 -> FDB_TSL_DELETED -> FDB_TSL_USER_STATUS2*       The intermediate states can also be ignored.*       such as: FDB_TSL_WRITE -> FDB_TSL_DELETED*/fdb_tsl_iter(tsdb, set_status_cb, tsdb);}FDB_INFO("===========================================================\n");
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/734815.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

美国签证|附面签相关事项√

小伙伴最近都忙着办签证吧!但是需要注意的是,美国的签证跟其他任何国家的签证不同,并不是办理了就一定拿得到,据说概率是50%左右。所以办理美国签证,不要太着急啦!先来了解一下美国签证的相片该怎么拍叭 ✅…

RocketMQ的事务消息流程

什么是事务消息? 事务消息是一种在发送方和接收方之间保证消息传递的一致性和可靠性的消息传递机制。在消息发送过程中,生产者可以将消息发送到消息队列,但不会立即被消费者接收和处理。相反,消息会先进入一种“准备”状态&#x…

用chatgpt写insar地质灾害的论文,重复率只有1.8%,chatgpt4.0写论文不是梦

突发奇想,想用chatgpt写一篇论文,并看看查重率,结果很惊艳,说明是确实可行的,请看下图。 下面是完整的文字内容。 InSAR (Interferometric Synthetic Aperture Radar) 地质灾害监测技术是一种基于合成孔径雷达…

【JavaScript】JavaScript 变量 ① ( JavaScript 变量概念 | 变量声明 | 变量类型 | 变量初始化 | ES6 简介 )

文章目录 一、JavaScript 变量1、变量概念2、变量声明3、ES6 简介4、变量类型5、变量初始化 二、JavaScript 变量示例1、代码示例2、展示效果 一、JavaScript 变量 1、变量概念 JavaScript 变量 是用于 存储数据 的 容器 , 通过 变量名称 , 可以 获取 / 修改 变量 中的数据 ; …

第十五届蓝桥杯模拟赛(第三期)

大家好,我是晴天学长,本次分享,制作不易,本次题解只用于学习用途,如果有考试需要的小伙伴请考完试再来看题解进行学习,需要的小伙伴可以点赞关注评论一波哦!蓝桥杯省赛就要开始了,祝…

【DimPlot】【FeaturePlot】使用小tips

目录 DimPlot函数参数解析 栅格化点图 放大 ggplot2 图例的点,修改图例的标题 FeaturePlot函数参数解析 调整FeaturePlot颜色 分组绘制featureplot 随手笔记,持续更新中。。。 Reference DimPlot函数参数解析 object: 一个Seurat对象,…

工作纪实46-关于微服务的上线发布姿势

蓝绿部署 在部署时,不需要将旧版本的服务停掉,而是将新版本与旧版本同时运行,新版本测试无误之后再将旧版本停掉。这样可以避免再升级的过程中如果失败服务不可用的问题,因为同时部署了两个版本的程序,使得硬件资源是…

【项目笔记】java微服务:黑马头条(day01)

文章目录 环境搭建、SpringCloud微服务(注册发现、服务调用、网关)1)课程对比2)项目概述2.1)能让你收获什么2.2)项目课程大纲2.3)项目概述2.4)项目术语2.5)业务说明 3)技术栈4)nacos环境搭建4.1)虚拟机镜像准备4.2)nacos安装 5)初始工程搭建5.1)环境准备5.2)主体结构 6)登录6.1…

JavaScript中的Set和Map:理解与使用

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

C++:类和对象(三)——拷贝构造函数和运算符重载

目录 一、拷贝构造函数 1.概念 2.特性 二、赋值运算符重载 1.运算符重载 2.赋值运算符重载 (1)注意的点: (2)赋值运算符不允许被重载为全局函数,只能重载为类的成员函数 (3)…

C++ 字符串OJ

目录 1、14. 最长公共前缀 2、 5. 最长回文子串 3、 67. 二进制求和 4、43. 字符串相乘 1、14. 最长公共前缀 思路一:两两字符串进行比较,每次比较过程相同,可以添加一个函数辅助比较,查找最长公共前缀。 class Solution { pu…

【C++】函数模板和类模板

目录 1.泛型编程 2.函数模板 2.1函数模板的定义格式 2.2函数模板的实例化 2.3函数模板参数的匹配原则 3.类模板 3.1类模板的定义格式 3.2类模板的实例化 3.3模板的分离编译 1.泛型编程 泛型编程:编写与类型无关的通用代码,是代码复用的一种手段…

【前端CSS】CSS的3种基本选择器和5种高级选择器使用方式

目录 前言 基本选择器 1.1 标签选择器 1.2 ID选择器 1.3 类选择器 高级选择器 2.1 并集选择器 2.2 交集选择器 2.3 后代选择器 2.4 子元素选择器 2.5 属性选择器 前言 1W:什么是CSS选择器? CSS选择器由HTML元素的id、class属性或元素名本身以及…

SpringBoot中定时任务、corn表达式

SpringBoot中定时任务、corn表达式 corn表达式网站:https://cron.qqe2.com/ 方法上加上Scheduled(cron表达式) 启动类上加上EnableScheduling 示例 启动类上 启动类加上EnableScheduling开启定时任务。 SpringBootApplication EnableScheduling public class…

vue 在什么情况下在数据发生改变的时候不会触发视图更新

在 Vue 中,通常数据发生变化时,视图会自动更新。但是,有几种情况可能导致数据变化不会触发视图更新: 1.对象属性的添加或删除: Vue 无法检测到对象属性的添加或删除。因为 Vue 在初始化实例时对属性执行了 getter/se…

VUE3 使用axios网络请求

1.新建工程 参考,VUE3 环境搭建:https://blog.csdn.net/LQ_001/article/details/136293795,运行命令 vue create vue-demo 2.引入axios 不管何种引用,都要在工程中安装 axios 包。安装命令:npm install --save axio…

C语言——函数指针——函数指针变量(详解)

函数指针变量 函数指针变量的作用 函数指针变量是指向函数的指针,它可以用来存储函数的地址,并且可以通过该指针调用相应的函数。函数指针变量的作用主要有以下几个方面: 回调函数:函数指针变量可以作为参数传递给其他函数&…

拿捏算法的复杂度

目录 前言 一:算法的时间复杂度 1.定义 2.简单的算法可以数循环的次数,其余需要经过计算得出表达式 3.记法:大O的渐近表示法 表示规则:对得出的时间复杂度的函数表达式,只关注最高阶,其余项和最高阶…

【音视频开发好书推荐2】《FFmpeg 音视频开发基础与实战》

1、多媒体处理开源库FFmpeg概述 享有盛名的音视频多媒体处理开源库FFmpeg,做过音视频编解码开发的同学基本都用过,即便没做过这方面开发,也会听说过这个开源库。 FFmpeg是目前最全面的开源音视频编解码库,包括常用的音视频编码协议…

JavaScript原型和原型链

JavaScript每个对象拥有一个原型对象 需要注意的是,只有函数对象才有 prototype 属性 当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索&#xff…