【工具使用】STM32CubeMX-片内Flash读写操作
一、概述
无论是新手还是大佬,基于STM32单片机的开发,使用STM32CubeMX都是可以极大提升开发效率的,并且其界面化的开发,也大大降低了新手对STM32单片机的开发门槛。
本文主要讲述STM32芯片片内Flash功能的应用及其相关知识。
二、软件说明
STM32CubeMX是ST官方出的一款针对ST的MCU/MPU跨平台的图形化工具,支持在Linux、MacOS、Window系统下开发,其对接的底层接口是HAL库,另外习惯于寄存器开发的同学们,也可以使用LL库。STM32CubeMX除了集成MCU/MPU的硬件抽象层,另外还集成了像RTOS,文件系统,USB,网络,显示,嵌入式AI等中间件,这样开发者就能够很轻松的完成MCU/MPU的底层驱动的配置,留出更多精力开发上层功能逻辑,能够更进一步提高了嵌入式开发效率。
演示版本 6.1.0
三、片内Flash功能简介
首先看下Flash的概念,Flash(闪存)是一种非易失性存储技术,广泛应用于电子设备中。它结合了 ROM(只读存储器)的非易失性和 RAM(随机存取存储器)的可读写特性,成为现代数据存储的核心组件。最早的Flash是EEPROM(电可擦可编程只读存储器),EEPROM的特点是可单个字节擦写,但缺点就是效率低、成本高,于是就有人提出块擦除
的概念,并在几年后推出首款NOR-Flash芯片,命名为Flash Memory,跟传统EEPROM对比,降低了成本,并提高了擦除效率。下面简单看下两者的对比:
特性 | EEPROM | Flash |
---|---|---|
擦除单位 | 字节(Byte)级擦除,可随机修改单个字节 | 块(Block)或页(Page)级擦除(如 4KB/8KB/64KB) |
擦写寿命 | 高(10 万 - 100 万次 P/E 循环) | 中低(SLC: 10 万次,MLC: 1 万次,TLC/QLC: 1000-3000 次) |
读写速度 | 写入:中等(约 100μs / 字节) 读取:快(约 50-100ns) | 写入:慢(需先擦除整块,约 1-10ms / 页) 读取:快(随机读取快) |
存储密度 | 低(成本高),容量通常为 KB 级别 | 高(成本低),容量从 MB 到 TB 级别 |
随机访问能力 | 支持按字节随机读写,无需预先擦除 | 仅支持块级擦除,写入前需擦除整个块 |
典型应用场景 | 配置参数存储(如 I2C EEPROM) 频繁更新的小数据(如计数器) | 程序代码存储(如 MCU 片内 Flash) SSD、U 盘、存储卡等大容量存储 |
数据保存时间 | 长(>10 年) | 中(5-10 年,依赖存储技术和使用环境) |
成本 / 位 | 高 | 低(Flash 是主流低成本方案) |
技术实现复杂度 | 简单(电路结构直接) | 复杂(需 FTL 磨损均衡、ECC 纠错等技术) |
注:因为Flash有擦写寿命,所以不可以频繁擦写,要控制擦写次数。
简单介绍完通用Flash后,我们来看一下STM32内部的Flash是怎么样的,这里以STM32F103C8T6为例,内部Flash总共有128k(官方文档会写只有64k,但实际是有128k的,只是出厂的时候他们只保证64k是测试过没问题的),分成128页,每页1k的大小。STM32内部的Flash一般是用来存储代码,所以在单片机启动地址的选择中,有一个就是从0x08000000开始。除了存储代码以外,内部Flash还可以用来存储一些需要掉电后仍需要保持的数据。
操作Flash时一般是需要关闭中断的,因为把Flash当成一个资源来看时,内核是需要使用一些通信指令去操作Flash的。当操作Flash时,内核需要发送指令去操作Flash,如果此时几个指令发送到一半时,突然产生中断,中断的代码是在Flash中的,相当于此时内核又重新发送指令去读取Flash中的代码指令,从时序上来看,是中断和操作Flash两个操作共用了Flash这一个资源,从而造成重入问题。一般出现这种问题会报硬件错误。然而STM32自身做了保护,即在擦除或写入时,会禁止读取,即擦除或写入Flash期间,中断无法执行。下面是官方STM32F10xxx 闪存编程手册(PM0075)
的描述。
四、片内Flash配置
有了以上一些基础知识,接下来我们来实现一个实际点的功能,存储一个数据,用来识别该软件是否第一次使用,如果是,那就打印一条第一次使用的信息,否则则打印欢迎回来的信息。首先先做个Flash的配置,这个功能配置很简单,简单到根本不需要单独配置。CubeMX直接配个带时钟的最简易的工程能跑就行。
为了方便新手学习,这里还是一张图演示搞定。
配置完时钟后,就直接来看实现吧,对于内部Flash,其实我们最关心的就是读跟写的功能,对于片内Flash来说,读取可以直接使用指针索引即可,但为了方便学习,这里还是写下具体实现。
- HAL库代码实现
#define FLASH_USER_START_ADDR 0x08004000U // 用户Flash起始地址
#define FLASH_USER_END_ADDR 0x08010000U // 用户Flash结束地址/*** @brief 写入数据到STM32F103内部Flash,支持跨页擦写* @param startAddress: 写入的起始地址,必须是2字节对齐* @param data: 待写入数据的指针* @param size: 待写入数据的字节数* @retval HAL_StatusTypeDef: 操作状态*/
HAL_StatusTypeDef FLASH_WriteData(uint32_t startAddress, uint8_t* data, uint32_t size)
{HAL_StatusTypeDef status = HAL_OK;uint32_t pageError = 0;uint32_t currentAddress = startAddress;uint32_t dataIndex = 0;uint32_t firstPage = startAddress / FLASH_PAGE_SIZE;uint32_t lastPage = (startAddress + size - 1) / FLASH_PAGE_SIZE;/* 检查地址和数据合法性 */if ((startAddress < FLASH_USER_START_ADDR) || (startAddress + size > FLASH_USER_END_ADDR) ||(startAddress % 2 != 0) || (size % 2 != 0)){return HAL_ERROR;}/* 解锁Flash控制器 */status = HAL_FLASH_Unlock();if (status != HAL_OK) return status;/* 擦除涉及的页 */FLASH_EraseInitTypeDef eraseInit;eraseInit.TypeErase = FLASH_TYPEERASE_PAGES;eraseInit.PageAddress = firstPage * FLASH_PAGE_SIZE;eraseInit.NbPages = lastPage - firstPage + 1;status = HAL_FLASHEx_Erase(&eraseInit, &pageError);if (status != HAL_OK) goto FLASH_OPERATION_END;/* 写入数据(按半字,即16位操作) */while (dataIndex < size){uint16_t halfWordData = (uint16_t)(data[dataIndex + 1] << 8) | data[dataIndex];status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, currentAddress, halfWordData);if (status != HAL_OK) break;currentAddress += 2;dataIndex += 2;}FLASH_OPERATION_END:/* 锁定Flash控制器 */HAL_FLASH_Lock();return status;
}/*** @brief 读取STM32F103内部Flash数据,支持跨页读取* @param startAddress: 读取的起始地址,必须是2字节对齐* @param data: 待读取数据的指针* @param size: 待读取数据的字节数* @retval HAL_StatusTypeDef: 操作状态*/
HAL_StatusTypeDef FLASH_ReadData(uint32_t startAddress, uint8_t* data, uint32_t size)
{for (uint32_t i = 0; i < size; i++){data[i] = *((uint8_t *)startAddress + i);}return HAL_OK;
}uint8_t write_en = 0; // 写入使能
uint32_t write_addr = 0; // 写入数据的Flash首地址(基于0x08004000)
uint8_t write_data[FLASH_PAGE_SIZE]; // 待写入的数据uint8_t read_en = 0; // 读取使能
uint32_t read_addr = 0; // 读取数据的Flash首地址(基于0x08004000)
uint8_t read_data[FLASH_PAGE_SIZE]; // 待读取的数据/* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */if (write_en){FLASH_WriteData(FLASH_USER_START_ADDR + write_addr, write_data, FLASH_PAGE_SIZE);write_en = 0;}if (read_en){FLASH_ReadData(FLASH_USER_START_ADDR + read_addr, read_data, FLASH_PAGE_SIZE);read_en = 0;}/* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
- 效果演示
五、注意事项
- 正常来讲,Flash要写入数据前,必须先擦除原本的整页的数据,但STM32内部Flash是支持不擦除写入的,但必须确保数据是从1变成0,因为Flash本身的特性,数据从0变1只能是通过擦除的动作来实现。
- 因为内部Flash最小的擦除单位是页,所以当需要修改同一页里的某个数据时,必须先把整页数据读至RAM,然后整页擦除,修改RAM中要改变的值,再将整页RAM写回Flash中,所以操作Flash时,RAM至少要留与Flash页大小一致的一片空间。
- 擦除或写入Flash前需要关闭中断,不然会出现重入问题,导致出现硬件错误。但STM32除外,因为STM32擦写Flash时内部会禁止读取Flash。
- 写Flash前,需要确认写入的数据是否跟原本的数据一样,如果是一样的可以不写入。因为Flash存在擦写寿命,如果过于频繁地操作擦写Flash,当达到擦写的寿命时,Flash会损坏。一般标称可擦写10w次。
六、相关链接
对于刚入门的小伙伴可以先看下STM32CubeMX的基础使用及Keil的基础使用。
【工具使用】STM32CubeMX-基础使用篇
【工具使用】Keil5软件使用-基础使用篇
相关文章:
【工具使用】STM32CubeMX-片内Flash读写操作
一、概述 无论是新手还是大佬,基于STM32单片机的开发,使用STM32CubeMX都是可以极大提升开发效率的,并且其界面化的开发,也大大降低了新手对STM32单片机的开发门槛。 本文主要讲述STM32芯片片内Flash功能的应用及其相关知识…...
Java转Go日记(三十九):Gorm查询
1.1.1. 查询 // 获取第一条记录,按主键排序db.First(&user)SELECT * FROM users ORDER BY id LIMIT 1;// 获取最后一条记录,按主键排序db.Last(&user)SELECT * FROM users ORDER BY id DESC LIMIT 1;// 获取所有记录db.Find(&users)SELECT *…...
终端安全与终端管理:有什么区别及其重要性?
在当今快速发展的远程和混合工作环境中,IT 团队面临双重挑战:一方面需保护终端免受日益增长的网络风险,另一方面要管理跨越日益分散网络的设备。这些需求催生了两个关键的 IT 解决方案:终端安全和终端管理。尽管二者时常被共同讨论…...
【二分 优先队列】P3611 [USACO17JAN] Cow Dance Show S|普及+
本文涉及的基础知识点 C二分查找 C堆(优先队列) [USACO17JAN] Cow Dance Show S 题面翻译 题目描述 经过几个月的排练,奶牛们基本准备好展出她们的年度舞蹈表演。今年她们要表演的是著名的奶牛芭蕾——“cowpelia”。 表演唯一有待决定的是舞台的尺寸。一个大…...
蓝桥杯分享经验
系列文章目录 提示:小白先看系列 第一章 蓝桥杯的钱白给吗 文章目录 系列文章目录前言一、自我介绍二、经验讲解:1.基础知识2.进阶知识3.个人观点 三、总结四、后续 前言 第十六届蓝桥杯已经省赛已经结束了,相信很多小伙伴也已经得到自己的成绩了。接下…...
TDengine 安全部署配置建议
背景 TDengine 的分布式、多组件特性导致 TDengine 的安全配置是生产系统中比较关注的问题。本文档旨在对 TDengine 各组件及在不同部署方式下的安全问题进行说明,并提供部署和配置建议,为用户的数据安全提供支持。 安全配置涉及组件 TDengine 包含多…...
Grafana当前状态:SingleStat面板
Grafana的SingleStat面板是一种用于展示单个关键指标(KPI)的可视化组件,特别适合需要突出显示核心业务指标的场景(如实时销售额、在线用户数、系统错误率等)。它通过简洁的布局和丰富的样式选项,帮助用户快速聚焦核心数据。Singlem Panel侧重于展示系统的…...
专题五:floodfill算法(太平洋大西洋水流问题)
以leetcode417题为例 题目解析: 整张图,左边深蓝的是太平洋,右边浅蓝的是大西洋,你需要在矩阵中找到一个点,使其可以流向太平洋又可以流向大西洋,并且你每次流的时候只能由高到低,或者相等到相…...
【HTML】【面试提问】HTML面试提问总结
第一章 HTML基础相关提问 1.1 HTML基本概念 1.1.1 什么是HTML HTML 即超文本标记语言(HyperText Markup Language)😎,它是用于创建网页的标准标记语言。简单来说,HTML 就像是搭建房屋的砖块🧱࿰…...
解锁MySQL性能调优:高级SQL技巧实战指南
高级SQL技巧:解锁MySQL性能调优的终极指南 开篇 当前,随着业务系统的复杂化和数据量的爆炸式增长,数据库性能调优成为了技术人员面临的核心挑战之一。尤其是在高并发、大数据量的场景下,SQL 查询的性能直接影响到整个系统的响应…...
数据分析与应用---数据可视化基础
目录 Matplotlib基础绘图 (一)、pyplot绘图基础语法与常用参数 1、pyplot基础语法 (1) 创建画布与创建子图 (2) 添加画布内容 (3) 保存与显示图形 案例代码 2. 设置pyplot的动态…...
android双屏之副屏待机显示图片
摘要:android原生有双屏的机制,但需要芯片厂商适配框架后在底层实现。本文在基于芯发8766已实现底层适配的基础上,仅针对上层Launcher部分对系统进行改造,从而实现在开机后副屏显示一张待机图片。 副屏布局 由于仅显示一张图片&…...
oracle序列自增问题
1.先查询表名对应的序列名称 SELECT trigger_name, trigger_type, triggering_event FROM all_triggers WHERE table_name 表名;2. 查询id最大值 SELECT MAX(ID) FROM 表名;3. 查询下一次生成ID SELECT SJCJ_ENERGY_DATA_INSERTID.NEXTVAL FROM DUAL;4. 设置临时步长,越过…...
FLASHDB API分析
fdb_kvdb_init 函数详解 fdb_kvdb_init 是 FlashDB 框架中用于 初始化键值数据库(KVDB) 的核心接口,其功能涵盖底层存储配置、默认数据加载与多模式适配。以下从功能、参数、使用场景及注意事项展开分析: 一、功能与作用 …...
使用 ABP vNext 集成 MinIO 构建高可用 BLOB 存储服务
🚀 使用 ABP vNext 集成 MinIO 构建高可用 BLOB 存储服务 本文基于 ABP vNext MinIO 的对象存储集成实践,系统讲解从 MinIO 部署、桶创建、ABP 集成、上传 API、安全校验、预签名访问,到测试、扩展及多租户支持的全过程。目标是构建一套可复…...
3.安卓逆向2-安卓文件目录
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 内容参考于:图灵Python学院 上一个内容:2.安卓逆向2-adb指令 首先使用adb连接到手机,如下图使用adb命令列出手机的目录&am…...
云原生时代的系统可观测性:理念变革与实践体系
📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:为什么可观测性在云原生时代变得更加重要? 传统应用系统运行于固定服务器,拓扑结构稳定、依赖路径清晰,排查故障依赖日志和人工经验已足够支撑运维。但在云原生环境中,系统正快速演变为: 微…...
力扣网-复写零
1.题目要求 2.题目链接 1089. 复写零 - 力扣(LeetCode) 3.题目解答 class Solution {public void duplicateZeros(int[] arr) {int cur0,dest-1,narr.length;while(cur<n){//遇到0就dest走两步if(arr[cur]0){dest2;}//遇到非零元素dest就走一步els…...
高项-挣值管理TCPI
TCPI(完工尚需绩效指数)的英文全称及含义 TCPI 是项目管理(尤其是挣值管理EVM, Earned Value Management)中的一个关键指标,其英文全称为: To-Complete Performance Index 中文译为**“完工尚需绩效指数”…...
Java大厂面试三轮问答:微服务与数据库技术深度解析
Java大厂面试:谢飞机的三轮挑战 第一轮:微服务基础与电商场景设计 面试官: "谢飞机,假设我们要设计一个电商平台,需要支持用户下单、支付以及订单追踪。你会如何设计微服务架构?" 谢飞机: "呃&#…...
Linux 移植 Docker 详解
一、移植前的环境准备 在将 Docker 移植到 Linux 系统之前,需要确保系统满足一定的条件,以保证 Docker 能够稳定运行。 1. 操作系统版本要求 Docker 对 Linux 操作系统版本有一定的要求,不同的 Docker 版本适配不同的 Linux 发行版及版本。常…...
滑动验证码缺口识别与自动化处理技术解析
在如今的网络安全环境中,滑动验证码作为一种主流的人机验证方案,被广泛应用。它的核心挑战主要集中在两个方面:一是如何准确地识别出缺口位置,二是如何模拟出逼真的拖动轨迹。 一、缺口识别技术方案 (一)…...
C++字符串处理:`std::string`和`std::string_view`的区别与使用
在 C中,std::string和std::string_view都用于处理字符串,但它们的用途和性能特点有很大不同。本教程将通过代码示例和流程图,帮助你快速掌握它们的使用方法。 1.什么是std::string和std::string_view? 1.1std::string std::str…...
Uniapp中动态控制scroll-view滚动的方式
在Uniapp 4.45中,动态修改scroll-view的scroll-left属性时无法触发滚动(直接设置scroll-left属性值没问题),这通常是因为数据更新与 DOM 渲染之间的异步特性导致的。知道了原因,但是直接修改scroll-left属性值还是失败…...
手机怎么查看网络ip地址?安卓/iOS设备查询指南
在移动互联网时代,IP地址作为设备的网络身份证,无论是网络调试、远程连接还是排查故障都至关重要。本文将系统介绍安卓和iOS设备查看IP地址的多种方法,帮助您快速掌握这一实用技能。 一、安卓手机查看IP地址方法 1、通过WiFi设置查看 打开设…...
R语言+贝叶斯网络:涵盖贝叶斯网络的基础、离散与连续分布、混合网络、动态网络,Gephi可视化,助你成为数据分析高手!
🔍 在现代生态、环境及地学研究中,变量及其因果关系的推断是核心课题之一。然而,传统的因果关系研究通常依赖于昂贵的实验,而实验结果往往与天然环境中的实际因果联系存在较大偏差。例如,在生态系统中,物种…...
手机内存不够,哪些文件可以删?
1️⃣应用缓存文件 安卓:通过「文件管理器」→「Android」→「data」或「cache」文件夹(部分需权限),或直接在应用设置中清除缓存 iOS:无需手动清理,系统会自动管理,或在应用内设置中清除&…...
C语言之 比特(bit)、字节(Byte)、字(Word)、整数(Int)
在C语言中,经常出现上述的概念,即比特(bit)、字节(Byte)、字(Word)、整数(Int)。查看C语言标准,比特(bit)的定义如下&…...
组态王通过开疆智能profinet转ModbusTCP网关连接西门子PLC配置案例
本案例是组态王通过使用开疆智能研发的Profinet转ModbusTCP网关采集西门子1200PLC中数据的案例。 网关配置 首先来配置网关的参数,打开网关配置软件“Gateway Configuration Studio” 由于组态王那侧设定为ModbusTCP客户端所以网关作为ModbusTCP服务器。新建项目…...
GO语言学习(五)
GO语言学习(五) 前面我们已经学了一些关于golang的基础知识,从这一期开始,我们就来讲解一下基于golang为后端的web开发,首先这一期为一些golang为后端的web开发基础讲解,我们将会从web的工作方式、golang如…...
Supermemory:让大模型拥有“长效记忆“
目录 引言:打破大语言模型的记忆瓶颈,迎接AI交互新范式 一、Supermemory 核心技术 1.1 透明代理机制 1.2 智能分段与检索系统 1.3 自动Token管理 二、易用性 三、性能与成本 四、可靠性与兼容性 五、为何选择 Supermemory? 六、对…...
Hooks实现原理与自定义Hooks
React Hooks 是 React 16.8 引入的一种机制,允许在函数组件中使用状态(state)、副作用(effect)等功能,而无需编写 class 组件。其核心原理是通过闭包和链表结构,在 React 的 Fiber 架构中管理组…...
【NLP】35. 构建高质量标注数据
如何构建高质量标注数据?大语言模型背后的那只“看不见的手” 在讨论大语言模型(LLM)性能突破时,人们总是聚焦在模型参数、结构设计和训练技巧上。但真正懂行的人都知道——再好的模型也离不开一手好数据,尤其是那些“…...
2024CCPC吉林省赛长春邀请赛 Java 做题记录
目录 I. The Easiest Problem G. Platform Game L. Recharge E. Connected Components I. The Easiest Problem 签到题 直接输出 21 即可 // github https://github.com/Dddddduo // github https://github.com/Dddddduo/acm-java-algorithm // github https://github.com/…...
黑马程序员C++2024新版笔记 第三章 数组
1.数组定义 数组是一批相同类型的元素(element)的集合组成的数据结构。 声明语法: <数据类型> <数组名> [<数组长度>] int v[6] // 声明了可以存放6个int数字的数组 数组的每个元素有编号,称之为下标索引…...
Golang的网络安全策略实践
Golang的网络安全策略实践 一、理解网络安全的重要性 当今的网络环境中,安全问题日益突出,各种类型的攻击如雨后春笋般涌现,给个人和组织的信息资产造成了严重威胁。因此,制定和实施有效的网络安全策略至关重要。 二、Golang在网络…...
SAP学习笔记 - 开发13 - CAP 之 添加数据库支持(Sqlite)
上一章学习了CAP开发准备,添加Service。 SAP学习笔记 - 开发12 - CAP 之 开发准备,添加服务-CSDN博客 本章继续学习CAP开发 - 添加数据库支持(Sqlite)。 目录 1,数据库准备 - H2 内存数据库 - Sqlite数据库 a&…...
DRIVEGPT4: 通过大语言模型实现可解释的端到端自动驾驶
《DriveGPT4: Interpretable End-to-End Autonomous Driving via Large Language Model》 2024年10月发表,来自香港大学、浙江大学、华为和悉尼大学。 多模态大型语言模型(MLLM)已成为研究界关注的一个突出领域,因为它们擅长处理…...
LLM最后怎么输出值 解码语言模型:从权重到概率的奥秘
LM Head Weights(语言模型头部权重):左侧的“LM Head Weights”表示语言模型头部的权重矩阵,它是模型参数的一部分。权重矩阵与输入数据进行运算。Logits(未归一化对数概率):经过与LM Head Weig…...
Better Faster Large Language Models via Multi-token Prediction 原理
目录 模型结构: Memory-efficient implementation: 实验: 1. 在大规模模型上效果显著: 2. 在不同类型任务上的效果: 为什么MLP对效果有提升的几点猜测: 1. 并非所有token对生成质量的影响相同 2. 关…...
【NLP】34. 数据专题:如何打造高质量训练数据集
构建大语言模型的秘密武器:如何打造高质量训练数据集? 在大语言模型(LLM)如 GPT、BERT、T5 爆发式发展的背后,我们常常关注模型架构的演化,却忽视了一个更基础也更关键的问题:训练数据从哪里来…...
uniapp 微信小程序 获取openId
嗨,我是小路。今天主要和大家分享的主题是“uniapp 微信小程序 获取openId”。 一、主要属性 1.uni.login 二、实例代码 1、前端代码 uni.login({provider: weixin,success: (res) > {uni.showLoading({title: 登录中...,mask: true})let code res.…...
企业标准信息公共服务平台已开放标准通编辑器访问入口
标准通 数字化标准编辑器 专业、高效、便捷 企业标准信息公共服务平台 近日,企业标准信息公共服务平台已开放标准通编辑器访问入口,可进入官网指定版块使用! 核心功能亮点 解决企业痛点 传统标准编制,需反复核对格式、逐条…...
小米MUJIA智能音频眼镜来袭
智能眼镜赛道风云再起,小米新力作MIJIA智能音频眼镜2正式亮相,引发市场热议。 这款产品在设计和功能上都有显著提升,为用户带来更舒适便捷的佩戴体验,同时也标志着小米在智能眼镜领域的持续深耕。 轻薄设计,舒适体验 …...
Node.js 实战八:服务部署方案对比与实践
你开发好了接口,准备上线,然后开始犹豫: “直接 node app.js 启就行了吗?” “要不要用 PM2?听说 Docker 更稳?” “Serverless 是不是就不用管服务器了?” 部署是从“能运行”到“能长久运行”…...
地下水安全监测实施方案
一、方案目标 本方案的核心目标在于构建一个全方位、科学严谨且高效运转的地下水监测体系,旨在实现对地下水资源全方位的动态监测、科学化的管理和有效的保护。监测的具体目标涵盖了地下水位、流量以及水质等多个关键性指标,通过精准的数据采集和分析&am…...
HTTP由浅入深
概述 超文本传输协议(HTTP, Hypertext Transfer Protocol) 是一种用于传输超媒体文档(例如 HTML)的应用层协议。它最初被设计用于 Web 浏览器与 Web 服务器之间的通信,但也广泛应用于其他客户端与服务器的交互。 HTT…...
Conda 环境下安装 GCC 和 glibc (crypt.h) 教程
Conda 环境下安装 GCC 和 glibc (crypt.h) 教程 由于运行Low-Light Image Enhancement via Structure Modeling and Guidance原始论文代码,发现服务器的gcc版本太老,没法运行。同时缺少libxcrypt (crypt.h),不得不询问gpt进行解答。发现可以…...
C++面试3——const关键字的核心概念、典型场景和易错陷阱
const关键字的核心概念、典型场景和易错陷阱 一、const本质:类型系统的守护者 1. 与#define的本质差异 维度#defineconst编译阶段预处理替换编译器类型检查作用域无作用域(全局污染)遵循块作用域调试可见性符号消失保留符号信息类型安全无类…...
超小多模态视觉语言模型MiniMind-V 训练
简述 MiniMind-V 是一个超适合初学者的项目,让你用普通电脑就能训一个能看图说话的 AI。训练过程就像教小孩:先准备好图文材料(数据集),教它基础知识(预训练),再教具体技能…...