当前位置: 首页 > wzjs >正文

感谢使用wordpress进行创作快推达seo

感谢使用wordpress进行创作,快推达seo,网站建设常用视频格式,cms网站搭建目录 0. 个人简介 && 授权须知1. Flash 和 EEROM 基本情况2. 场景要求3. 软件设计思路4. 代码展示4.1 flash.h4.2 flash.c 0. 个人简介 && 授权须知 📋 个人简介 💖 作者简介:大家好,我是喜欢记录零碎知识点的菜鸟…

目录

  • 0. 个人简介 && 授权须知
  • 1. Flash 和 EEROM 基本情况
  • 2. 场景要求
  • 3. 软件设计思路
  • 4. 代码展示
    • 4.1 flash.h
    • 4.2 flash.c

0. 个人简介 && 授权须知

image-20230911133730620

📋 个人简介

  • 💖 作者简介:大家好,我是喜欢记录零碎知识点的菜鸟打工人。😎
  • 📝 个人主页:欢迎访问我的博客主页🔥…
    • https://blog.csdn.net/qq_39217004?spm=1010.2135.3001.5343
  • 🎉 支持我:点赞👍+收藏⭐️+留言📝
  • 📣 系列专栏:嵌入式Linux开发 🍁 🍁
  • 💬格言:写文档啊不是写文章,重要的还是直白!🔥

转载文章,禁止声明原创;不允许直接二次转载,转载请根据原文链接联系作者

若无需改版,在文首清楚标注作者及来源/原文链接,并删除【原创声明】,即可直接转载。
但对于未注明转载来源/原文链接的文章,我将保留追述的权利。

https://blog.csdn.net/qq_39217004?spm=1010.2135.3001.5343

作者:积跬步、至千里

image-20230911133724204

场景分析:
在嵌入式开发中,EEPROM 因其非易失性存储特性,常用于保存配置参数等数据。EEPROM 的擦写次数一般在10万次左右。

单片机一般通过 IIC 接口外加一个 EEROM 存储芯片

但是,有些小项目为了节省成本或者以前维护的一些项目,只能把 flash 划分出一段空间,当数据存储空间来用。

这样的缺点是

  1. 升级固件时如果固件变大了,一旦覆盖了原来划分的数据存储区域,那数据就没了。
  2. Flash 的擦写次数一般都是在 1万次 左右,这个次数可是远小于 EEROM

1万次,在很多场景下并不够。
因此本文参考
老板说:单片机,Flash模拟EEPROM,16字节,算法轮询存储给我做到100万次的存储次数 ,
的思路,通过软件设计,提高flash的擦写次数。

1. Flash 和 EEROM 基本情况

  1. 独立的EEPROM芯片是可以直接写字节的,即使覆盖写也无须擦除,
  2. 单片机的FLASH 写入数据之前,必须按页来擦除,先擦除再写入

2. 场景要求

程序一共有15个字节的内容需要断电保存,每改变其中一个字节就需要保存一次,做到100万次的一个存储次数。

单片机的 Flash 一共是 128KB ,从0x08000000----0x0801FFFF,一共64页,每页2KB。

3. 软件设计思路

以每个 page 2KB 的大小为一个节点,假设数据要存储到【最后一个page】,设计思路如下:

  1. 从第一个 page 开始写入,第一次写前16字节,然后更新写入地址索引到第16个字节
  2. 第二次从 17-31 字节写入,然后更新写入地址索引到第32个字节,依次循环

这样来算,每个 page 可以存储 2048/16 = 128 次,写满一页擦除一次,理论上存储次数能达到128 × 1万次/页 = 128万次。

4. 代码展示

4.1 flash.h

#ifndef FLASH__H
#define FLASH__H#include "stm32g0xx_hal.h"
#include <string.h>// FLASH配置
#define FLASH_BASE_ADDR 0x0801F800 // FLASH最后一页起始地址 (128KB - 2KB)
#define PAGE_SIZE 2048             // STM32G071页面大小为2KB
#define STATE_SIZE 16             // 结构体大小(填充到24字节)typedef struct {unsigned int  color;                  // 颜色unsigned int  seconds;                // 秒数unsigned char mode;                   // 模式unsigned char number;                 // 序号unsigned char padinng[5];             // 预留5unsigned char checksum;               // 1字节,校验和
}dataState;extern dataState old_state;
extern dataState current_state;
void printState(dataState *state);
HAL_StatusTypeDef flash_program(unsigned int addr, unsigned char* data, unsigned int len);
void read_flash(unsigned int addr, unsigned char* data, unsigned int len);
void init_flash_addr(void);
void save_state(dataState* state);
void get_state(dataState* state);
void update_state(dataState* state);#endif

4.2 flash.c

// 初始化:查找最新有效数据
void init_flash_addr(void) {dataState temp_state;uint32_t addr = FLASH_BASE_ADDR;uint32_t last_valid_addr = FLASH_BASE_ADDR;int found_valid_data = 0;while (addr < FLASH_BASE_ADDR + PAGE_SIZE) {read_flash(addr, (uint8_t*)&temp_state, STATE_SIZE);// 检查是否全0xFFuint8_t all_ff[STATE_SIZE];memset(all_ff, 0xFF, STATE_SIZE);int is_all_ff = (memcmp(&temp_state, all_ff, STATE_SIZE) == 0);if (!is_all_ff && temp_state.checksum == calculate_checksum(&temp_state)) {last_valid_addr = addr;found_valid_data = 1;memcpy(&current_state, &temp_state, STATE_SIZE);        } else {     break;}addr += STATE_SIZE;}flash_addr = last_valid_addr + (found_valid_data ? STATE_SIZE : 0);if(found_valid_data)printf("init first,found valid data,last_valid_addr:%X\r\n",last_valid_addr);elseprintf("init first,it is all ff,it is the first data\r\n");if (flash_addr > FLASH_BASE_ADDR + PAGE_SIZE)     {printf("init erase page 2KB\r\n");erase_page(FLASH_BASE_ADDR);flash_addr = FLASH_BASE_ADDR;}if (!found_valid_data) {printf("not found valid data\r\n");current_state.color = 100;current_state.seconds = 200;current_state.mode = 1;current_state.number = 1;current_state.checksum = calculate_checksum(&current_state);__disable_irq(); flash_program(FLASH_BASE_ADDR, (uint8_t*)&current_state, STATE_SIZE);__enable_irq(); flash_addr = FLASH_BASE_ADDR + STATE_SIZE;       }printState(&current_state);
}
  1. 第一步,先从第一个地址读取第一个16字节,然后判断是不是全部等于0xFF,如果第一次是就证明是第一次,下一步flash_addr就不需要增加STATE_SIZE,写入地址索引就是FLASH_BASE_ADDR
  2. 第二步,如果不全是0xFF并且校验字节通过,证明这是一组有效数据,我们先将此数据更新到current_state,但是这里还不能证明是最后一组有效数据,因为最后一组有效数据才是我们要找到的数据。
  3. 继续检查下一组数据,直到检查到一组数据是全0xFF,证明上一组数据就是最后一组有效数据,就跳出,此时我们也就找到了最后一组有效数据的起始地址。
  4. 此地址增加STATE_SIZE就是最新可以存储数据的地址索引了。
  5. 如果没找到有效数据,证明是第一次,就写入默认数值并保存,更新索引。

保存数据save_state函数:

oid save_state(dataState* state) {dataState last_state;if (flash_addr > FLASH_BASE_ADDR) {read_flash(flash_addr - STATE_SIZE, (uint8_t*)&last_state, STATE_SIZE);if (memcmp(&last_state, state, STATE_SIZE) == 0) {printf("数据没有变化,直接返回");return; }}__disable_irq(); if (flash_addr + STATE_SIZE > FLASH_BASE_ADDR + PAGE_SIZE) {printf("erase page 2KB\r\n");erase_page(FLASH_BASE_ADDR);flash_addr = FLASH_BASE_ADDR;   }state->checksum = calculate_checksum(state);flash_program(flash_addr, (uint8_t*)state, STATE_SIZE);flash_addr += STATE_SIZE; __enable_irq(); 
}

函数就比较简单了,首先将要保存的数据与最新存储的数据做对比,如果没变化,就不操作;如果地址超出范围了,就先擦除整个页,更新写索引到FLASH_BASE_ADDR,接着保存数据到当下最新写地址索引即可。

http://www.dtcms.com/wzjs/840455.html

相关文章:

  • 做网站的一个月能赚多少钱php网站怎么做静态化
  • 做网站用什么服务器主题之家wordpress
  • dw如何建设网站个人网站建设网站排名优化
  • 网站初期推广方案html指令代码大全
  • 商务网站建设需要多少钱阿里巴巴网站的搜索引擎优化案例
  • 一个网站添加多个网址住建设部官方网站
  • 如何编辑网站后台百度引擎搜索引擎
  • 建设门户网站需要注意什么页面紧急情况访问升级跳拿笔记
  • html网站登录界面模板下载营销推广哪家好
  • 台州网站快速优化排名wordpress 获取摘要
  • 郓城住房和城乡建设局网站吴中区住房和城乡建设局网站
  • 胶州市网站建设软件app制作
  • 网站建设分为哪三部分公众号可以做分类信息网站吗
  • 济南网站优化公司哪家好网站建设是网络工程师吗
  • 建个网站需要多少钱网推方案
  • 网站通知做文献的格式新手如何做分销
  • 福建省建设厅官方网站flash做ppt的模板下载网站
  • 中建交通建设集团有限公司网站站长工具集
  • 网站开发属于固定资产吗深圳正规seo
  • 营销的网站外贸跨境电商平台
  • 服务器上建设网站互联网营销推广方案
  • 广州金融网站设计百度验证网站的好处
  • 惠州企业网站建设长沙网站推广平台
  • 网站开发实训基本要求怎样让百度搜索到自己的网站
  • 网站建设基础功能友山建站优化
  • 爱网站免费一站二站Iis 建网站为什么说没有该用户
  • 公司网站在百度搜不到wordpress 翻页功能
  • 搭建dede网站服务器手机站模板
  • 传媒大学附近网站建设公司欧米茄官方手表
  • 佛山企业网站自助建站娄底企业网站建设制作