STM32G0xx使用LL库将Flash页分块方式存储数据实现一次擦除可多次写入
STM32G0xx使用LL库将Flash页分块方式存储数据实现一次擦除可多次写入
- 参考例程
- 例程说明
- 一、存储到Flash中的数据
- 二、Flash最底层操作(解锁,加锁,擦除,读写)
- 三、从Flash块中读取数据
- 五、测试验证
参考例程
STM32G0xx HAL和LL库Flash读写擦除操作
STM32G030Cx HAL库Flash擦除或编程操作出错的解决办法
例程说明
1.Flash存储数据采用页分块方式,实现一次擦除多次写入,每块128Byte总共16块,当存满16块后擦除一次
2.将数据写入Flash前,需要前后对比数据,只有数据发生变化才能写入Flash中
3.从Flash读取数据后,进行CRC校验,校验不通过往前继续读取数据,然后重新校验数据
4.将数据写如Flash前需要确保改块都是0xFF,保证写入数据成功
一、存储到Flash中的数据
说明:
- Header用来标识存储的头部信息,在Flash读取或写入时用到
- ubRes用来作块对齐使用,默认进行128Byte对齐
#define FLASH_STORE_PARM_HEADER_TAG (0x6C5A) //固定头信息
#define FLASH_STORE_PARM_BLOCK_SIZE (128) //块大小
#define FLASH_STORE_PARM_BLOCK_COUNT (u16)(FLASH_PAGE_SIZE / FLASH_STORE_PARM_BLOCK_SIZE) //1页分块的数量#pragma pack(1)
typedef struct
{........................
}GlobalParamStore, * GlobalParamStore_t;typedef struct
{........................
}DemarParamStore, * DemarParamStore_t, * pDemarParamStore;typedef struct
{........................
}ExceptionTrace;typedef struct
{........................
}ExtraLibPara;typedef struct
{u16 HeaderTag;u16 StoreIndex;
}FlashStoreHeader, * FlashStoreHeader_t;typedef struct
{FlashStoreHeader Header;GlobalParamStore SysPar;DemarParamStore DemarPar;ExceptionTrace ExpTrace;ExtraLibPara ExtLibPar;u8 ubRes[16];u8 ubCRC8;
}SystemParamStore, * SystemParamStore_t;
#pragma pack()
二、Flash最底层操作(解锁,加锁,擦除,读写)
说明:
- XSUPER_STM32G0_LL_LIB_ENABLE 被使能使用LL库
- Flash相关操作失败可多次尝试,尽可能让操作成功
#define FLASH_OPT_OVERTIMER (0x1FFFF)
#define FLASH_OPT_TRY_COUNT (5)/* Unlock the FLASH control register access */
static u8 ubFLASH_Unlock(void)
{u8 sta = 0;if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00U){/* Authorize the FLASH Registers access */WRITE_REG(FLASH->KEYR, FLASH_KEY1);WRITE_REG(FLASH->KEYR, FLASH_KEY2);/* verify Flash is unlock */if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00U){sta = 1;}}return sta;
}/* Lock the FLASH control register access */
static u8 ubFLASH_Lock(void)
{u8 sta = 1;/* Set the LOCK Bit to lock the FLASH Registers access */SET_BIT(FLASH->CR, FLASH_CR_LOCK);/* verify Flash is locked */if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00u){sta = 0;}return sta;
}/* Gets the page of a given address */
static u32 ulGetPage(u32 startAddr)
{return ((startAddr - FLASH_BASE) / FLASH_PAGE_SIZE);
}/* Erase the specified FLASH memory page */
static u8 ubFLASH_PageErase(u32 page)
{u32 tmp = 0;u32 time = 0;u8 res = 0;/* Get configuration register, then clear page number */tmp = (FLASH->CR & ~FLASH_CR_PNB);/* Set page number, Page Erase bit & Start bit */FLASH->CR = (tmp | (FLASH_CR_STRT | (page << FLASH_CR_PNB_Pos) | FLASH_CR_PER));/* wait for BSY1 in order to be sure that flash operation is ended before allowing prefetch in flash */while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U){if ((++time) > FLASH_OPT_OVERTIMER){res = 1;break;}}/* If operation is completed or interrupted, disable the Page Erase Bit */CLEAR_BIT(FLASH->CR, FLASH_CR_PER);return res;
}/* Program double-word (64-bit) at a specified address */
/* Must EN PG bit before and DIS PG bit after */
static u8 ubFLASH_Program_DoubleWord(u32 addr, u64 data)
{u32 time = 0;/* Wait for last operation to be completed */while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U){if ((++time) > FLASH_OPT_OVERTIMER){return 1;}}/* Set PG bit */SET_BIT(FLASH->CR, FLASH_CR_PG);/* Program first word */*(u32 *)addr = (u32)data;/* Barrier to ensure programming is performed in 2 steps, in right order(independently of compiler optimization behavior) */__ISB();/* Program second word */*(u32 *)(addr + 4U) = (u32)(data >> 32U);/* Wait for last operation to be completed */while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U){if ((++time) > FLASH_OPT_OVERTIMER){return 2;}}return 0;
}/* Wait for a FLASH operation to complete */
static u8 ubFlash_WaitFor_Operate(u32 timeOut)
{u32 timer = 0;u32 error = 0;while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U){if ((++timer) >= timeOut){return 1;}}#if ( XSUPER_STM32G0_LL_LIB_ENABLE > 0)/* check flash errors */error = (FLASH->SR & FLASH_FLAG_SR_ERROR);/* Clear SR register */FLASH->SR = FLASH_FLAG_SR_CLEAR;
#endif#if ( XSUPER_STM32G0_HAL_LIB_ENABLE > 0)/* check flash errors */error = (FLASH->SR & FLASH_SR_ERRORS);/* Clear SR register */FLASH->SR = FLASH_SR_CLEAR;
#endifif (error != 0x00U){return 2;}timer = 0;while ((FLASH->SR & FLASH_SR_CFGBSY) != 0x00U){if ((++timer) > timeOut){return 3;}}return 0;
}/* Read double-word (64-bit) at a specified address */
void vFlash_Read_DoubleWord(u32 startAddr, u64 * pDat, u16 len)
{u16 i = 0;for(i = 0; i < len; ++i){*pDat++ = *(volatile u64 *)(startAddr + (i << 3));}
}static u8 xSuper_Flash_Unlock(void)
{u8 tryCount = 0;for (tryCount = 0; tryCount < FLASH_OPT_TRY_COUNT; ++tryCount){if (!ubFLASH_Unlock()) return 0;ubFlash_WaitFor_Operate(FLASH_OPT_OVERTIMER);}return 1;
}static u8 xSuper_Flash_Lock(void)
{u8 tryCount = 0;for (tryCount = 0; tryCount < FLASH_OPT_TRY_COUNT; ++tryCount){if (!ubFLASH_Lock()) return 0;ubFlash_WaitFor_Operate(FLASH_OPT_OVERTIMER);}return 1;
}static u8 xSuper_Flash_EreasePage(u32 startAddr)
{u8 tryCount = 0;u32 page = ulGetPage(startAddr);for (tryCount = 0; tryCount < FLASH_OPT_TRY_COUNT; ++tryCount){if (!ubFLASH_PageErase(page)) return 0;ubFlash_WaitFor_Operate(FLASH_OPT_OVERTIMER);}return 1;
}static u8 xSuper_Flash_Program(u32 startAddr, u64 * pDat, u16 len)
{u64 rData = 0;u16 i = 0;u8 tryCount = 0;for (i = 0; i < len; ++i){for (tryCount = 0; tryCount < FLASH_OPT_TRY_COUNT; ++tryCount){if(!ubFLASH_Program_DoubleWord(startAddr , pDat[i])){rData = *(volatile u64 *)(startAddr);if (rData != pDat[i]){return 1;}else{startAddr += 8;tryCount = 0;break;}}else{ubFlash_WaitFor_Operate(FLASH_OPT_OVERTIMER);}}if (tryCount) return 2;}return 0;
}u8 ubFlash_Write_DoubleWord_EreasePage(u32 startAddr, u64 * pDat, u16 len, u8 mode)
{//避免HardFault,三级流水线__asm volatile("NOP"); __asm volatile("NOP"); __asm volatile("NOP");__DMB(); __DSB(); __ISB();__asm volatile("NOP"); __asm volatile("NOP"); __asm volatile("NOP");if (xSuper_Flash_Unlock()){#if defined(DEBUG_RELEASE_VERSION_ENABLE) && (DEBUG_RELEASE_VERSION_ENABLE == 0)dprintf("Flash Unlock Error...\r\n");#endifreturn 1;}if (mode){if (xSuper_Flash_EreasePage(startAddr)){xSuper_Flash_Lock();#if defined(DEBUG_RELEASE_VERSION_ENABLE) && (DEBUG_RELEASE_VERSION_ENABLE == 0)dprintf("Flash Erease Error...\r\n");#endifreturn 2;}#if defined(DEBUG_RELEASE_VERSION_ENABLE) && (DEBUG_RELEASE_VERSION_ENABLE == 0)dprintf("Flash Erease OK...\r\n");#endif}if (xSuper_Flash_Program(startAddr, pDat, len)){xSuper_Flash_Lock();#if defined(DEBUG_RELEASE_VERSION_ENABLE) && (DEBUG_RELEASE_VERSION_ENABLE == 0)dprintf("Flash Program Error...\r\n");#endifreturn 3;}if (xSuper_Flash_Lock()){#if defined(DEBUG_RELEASE_VERSION_ENABLE) && (DEBUG_RELEASE_VERSION_ENABLE == 0)dprintf("Flash Lock Error...\r\n");#endifreturn 4;}return 0;
}
三、从Flash块中读取数据
- vRead_System_Parameter开始打印每个结构体大小,便于调试对齐使用
/* 获取读Flash块索引 */
static u16 usGet_Flash_Read_Index(void)
{u16 dat = 0, i = 0;u8 crc = 0;for (i = 0; i < FLASH_STORE_PARM_BLOCK_COUNT; ++i){dat = *(volatile u16 *)(SYSTEM_ARG_STORE_START_ADDRE + (FLASH_STORE_PARM_BLOCK_SIZE * (FLASH_STORE_PARM_BLOCK_COUNT - 1 - i)));if (dat == FLASH_STORE_PARM_HEADER_TAG) {crc = ubCheckSum_CRC8((void *)(SYSTEM_ARG_STORE_START_ADDRE + (FLASH_STORE_PARM_BLOCK_SIZE * (FLASH_STORE_PARM_BLOCK_COUNT - 1 - i))), XOFS(SystemParamStore , ubCRC8));dat = *(volatile u8 *)(SYSTEM_ARG_STORE_START_ADDRE + (FLASH_STORE_PARM_BLOCK_SIZE * (FLASH_STORE_PARM_BLOCK_COUNT - 1 - i)) + (FLASH_STORE_PARM_BLOCK_SIZE - 1));if (dat == crc){return (FLASH_STORE_PARM_BLOCK_COUNT - 1 - i);}}}return FLASH_STORE_PARM_BLOCK_COUNT;
}static void vRead_GlobalSystem_Parameter(void)
{u16 index = usGet_Flash_Read_Index();if (index < FLASH_STORE_PARM_BLOCK_COUNT){/* 读取块内容 */vFlash_Read_DoubleWord(SYSTEM_ARG_STORE_START_ADDRE + (FLASH_STORE_PARM_BLOCK_SIZE * index), (u64 *)&SystemParam, (FLASH_STORE_PARM_BLOCK_SIZE >> 3));#if defined(DEBUG_RELEASE_VERSION_ENABLE) && (DEBUG_RELEASE_VERSION_ENABLE == 0)dprintf("Read Param OK...%u\r\n", SystemParam.Header.StoreIndex);#endif}else{/* 块索引无效 恢复默认值 */vRestoreDefault_GlobalSystemParam();#if defined(DEBUG_RELEASE_VERSION_ENABLE) && (DEBUG_RELEASE_VERSION_ENABLE == 0)dprintf("Restore Param...%u\r\n", SystemParam.Header.StoreIndex);#endif}/* 打印块数据 */#if defined(DEBUG_RELEASE_VERSION_ENABLE) && (DEBUG_RELEASE_VERSION_ENABLE == 0)dprintf("\r\n");dprintf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F \r\n");dprintf("-------------------------------------------------------------\r\n");for (index = 0; index < FLASH_STORE_PARM_BLOCK_SIZE; ++index){if (index && (index % 16 == 0)) dprintf("\r\n");if (index % 16 == 0) dprintf("0x%08X ", (SYSTEM_ARG_STORE_START_ADDRE + (FLASH_STORE_PARM_BLOCK_SIZE * SystemParam.Header.StoreIndex) + index));dprintf("%02X ", *(volatile u8 *)(SYSTEM_ARG_STORE_START_ADDRE + (FLASH_STORE_PARM_BLOCK_SIZE * SystemParam.Header.StoreIndex) + index));}dprintf("\r\n\r\n");#endif
}void vRead_System_Parameter(void)
{#if defined(DEBUG_RELEASE_VERSION_ENABLE) && (DEBUG_RELEASE_VERSION_ENABLE == 0)dprintf("Header Size :%u\r\n", sizeof(FlashStoreHeader));dprintf("SysPar Size :%u\r\n", sizeof(GlobalParamStore));dprintf("DemarPar Size :%u\r\n", sizeof(DemarParamStore));dprintf("ExpTrace Size :%u\r\n", sizeof(ExceptionTrace));dprintf("ExtLibPar Size:%u\r\n", sizeof(ExtraLibPara));dprintf("SystemParamStore Size......%u\r\n", sizeof(SystemParamStore));if (sizeof(SystemParamStore) != FLASH_STORE_PARM_BLOCK_SIZE) while (1);#endifvRead_GlobalSystem_Parameter();
}
四、将数据写入Flash块中
static u16 usGet_Flash_Write_Index(void)
{u16 dat = 0, i = 0, x = 0;u8 uFlg = 0;for (i = 0; i < FLASH_STORE_PARM_BLOCK_COUNT; ++i){dat = *(volatile u16 *)(SYSTEM_ARG_STORE_START_ADDRE + (FLASH_STORE_PARM_BLOCK_SIZE * i));if (dat == 0xFFFFU){uFlg = 0;for (x = 0; x < FLASH_STORE_PARM_BLOCK_SIZE; ++x){dat = *(volatile u8 *)(SYSTEM_ARG_STORE_START_ADDRE + (FLASH_STORE_PARM_BLOCK_SIZE * i) + x);if (dat != 0xFFU){uFlg = 1;break;}}if (!uFlg) {return i;}}}return FLASH_STORE_PARM_BLOCK_COUNT;
}static void vSave_GlobalSystem_Parameter(void)
{u8 * pSrc = (u8 *)&SystemParam;u8 mode = 0, dat = 0;u16 index = 0;for (index = 0; index < FLASH_STORE_PARM_BLOCK_SIZE; ++index){dat = *(volatile u8 *)(SYSTEM_ARG_STORE_START_ADDRE + (FLASH_STORE_PARM_BLOCK_SIZE * SystemParam.Header.StoreIndex) + index);if (dat != *pSrc++){mode = 1;break;}}if (!mode){#if defined(DEBUG_RELEASE_VERSION_ENABLE) && (DEBUG_RELEASE_VERSION_ENABLE == 0)dprintf("Flash Pram Same...%u\r\n", SystemParam.Header.StoreIndex);#endifreturn;}mode = 0;index = usGet_Flash_Write_Index();if (index < FLASH_STORE_PARM_BLOCK_COUNT){SystemParam.Header.StoreIndex = index;}else{SystemParam.Header.StoreIndex = 0;mode = 1;}SystemParam.ubCRC8 = ubCheckSum_CRC8((void *)(&SystemParam), XOFS(SystemParamStore , ubCRC8));if (ubFlash_Write_DoubleWord_EreasePage((SYSTEM_ARG_STORE_START_ADDRE + (FLASH_STORE_PARM_BLOCK_SIZE * SystemParam.Header.StoreIndex)), (u64 *)&SystemParam, (FLASH_STORE_PARM_BLOCK_SIZE >> 3), mode)){#if defined(DEBUG_RELEASE_VERSION_ENABLE) && (DEBUG_RELEASE_VERSION_ENABLE == 0)dprintf("Flash Write Error...%u\r\n", SystemParam.Header.StoreIndex);#endif}else{#if defined(DEBUG_RELEASE_VERSION_ENABLE) && (DEBUG_RELEASE_VERSION_ENABLE == 0)dprintf("Flash Write OK...%u CRC:%02X\r\n", SystemParam.Header.StoreIndex, SystemParam.ubCRC8);#endif}
}void vSave_System_Parameter(void)
{vSave_GlobalSystem_Parameter();
}
五、测试验证
只需调用一下函数即可:
从Flash块中读取数据
void vSave_System_Parameter(void)
将数据写入Flash块中
void vRead_System_Parameter(void)
相关文章:

STM32G0xx使用LL库将Flash页分块方式存储数据实现一次擦除可多次写入
STM32G0xx使用LL库将Flash页分块方式存储数据实现一次擦除可多次写入 参考例程例程说明一、存储到Flash中的数据二、Flash最底层操作(解锁,加锁,擦除,读写)三、从Flash块中读取数据五、测试验证 参考例程 STM32G0xx HAL和LL库Flash读写擦除操…...

SAP B1 认证考试习题 - 解析版(三)
前一篇:《SAP B1 认证考试习题 - 解析版(二)》 题目纯享版合集:《SAP B1 认证考试习题 - 纯享版》 五、运费(附加费用) 57. 以下哪个选项能够影响库存商品的价格 A. 仅为总量级别的附加费用 B. 只为行级…...

数据库开发规范
一、概述 本规范规定了,软件项目团队开发数据库的全流程规范。规范覆盖了数据库设计、管理及配套文件等。 二、项目阶段 项目阶段包括需求评审(需求分析阶段)、技术评审(方案阶段)、数据库开发…...

使用python向钉钉群聊发送消息
使用python向钉钉群聊发送消息 一、在钉钉群中新建机器人二、使用代码发送消息 一、在钉钉群中新建机器人 在群设置中添加机器人 选择自定义 勾选对应的安全设置 完成后会展示webhook,将地址复制出来,并记录,后面会用到 二、使用代码发送消…...

YOLOv11改进:SE注意力机制【注意力系列篇】(附详细的修改步骤,以及代码,与其他一些注意力机制相比,不仅准确度更高,而且模型更加轻量化。)
如果实验环境尚未搭建成功,可以参考这篇文章 ->【YOLOv11超详细环境搭建以及模型训练(GPU版本)】 文章链接为:YOLOv11超详细环境搭建以及模型训练(GPU版本)-CSDN博客 -------------------------------…...

STM32 基于HAL库和STM32cubeIDE的应用教程 (二)--GPIO的使用
如果有什么不懂的地方欢迎私聊博主,欢迎小白,博主必一一解答。 在 STM32 中,GPIO(通用输入输出)是与外部硬件接口进行交互的主要方式之一。STM32 HAL 库提供了简洁的接口来配置和控制 GPIO 引脚。下面是使用 STM32 HA…...

【毫米波雷达(七)】自动驾驶汽车中的精准定位——RTK定位技术
一、什么是RTK? RTK,英文全名叫做Real-time kinematic,也就是实时动态。这是一个简称,全称其实应该是RTK(Real-time kinematic,实时动态)载波相位差分技术。 二、RTK的组装 如上图所示&#x…...

Transformer和BERT的区别
Transformer和BERT的区别比较表: 两者的位置编码: 为什么要对位置进行编码? Attention提取特征的时候,可以获取全局每个词对之间的关系,但是并没有显式保留时序信息,或者说位置信息。就算打乱序列中token…...

linux 加载uPD720201固件
硬件 jetson orin nano jetpack 35.5.0 uPD720201是瑞萨推出的怕pcie扩展usb3.0芯片,支持flash主动加载与在系统被动加载 本文介绍如何做到没接flash情况下由系统加载固件 在uPD720201没接spi flash时候nano启动会报XhciDxe错误而自动重启,首先需要在ue…...

C语言中的信号量semaphore详解
在C语言中,**信号量(Semaphore)**是一种常用的同步机制,用于控制多个线程或进程对共享资源的访问。信号量可以实现类似于锁的效果,但更为灵活,适用于并发编程场景。 1. 什么是信号量 信号量可以看作是一个…...

0087__DirectX11 With Windows SDK--02 顶点/像素着色器的创建、顶点缓冲区
DirectX11 With Windows SDK--02 顶点/像素着色器的创建、顶点缓冲区-CSDN博客...

Windows换机华为擎云(银河麒麟V10+麒麟9000C CPU)后,使用selenium的程序怎么办(20241030)
原本的 seleniumChrome 已无法正常工作。chromedriver 报错:不支持 Linux/aarch64。 1、尝试Firefox、edge驱动。Firefox有一个geckodriver版本与Firefox版本的对照表,我看了一下,感觉他们是始终跟进新技术的。银河麒麟的很多库都是几年前的…...

linux 下 signal() 函数的用法,信号类型在哪里定义的?
--------------------------------------------------- author: hjjdebug date: 2024年 11月 07日 星期四 14:47:33 CST description: linux 下 signal() 函数的用法 --------------------------------------------------- signal 是linux 下最基础的进程通讯机制…...

享元模式及其运用场景:结合工厂模式和单例模式优化内存使用
介绍 享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享对象来减少内存使用,尤其是对于大量相似对象的场景。享元模式通常与工厂模式和单例模式结合使用,从而有效地控制和复用对象的创建。在享元模式中&am…...

【物联网技术】ESP8266 WIFI模块在STA模式下实现UDP与电脑/手机网络助手通信——UDP数据透传
前言:完成ESP8266 WIFI模块在STA模式下实现UDP与电脑/手机网络助手通信——实现UDP数据透传 STA模式,通俗来说就是模块/单片机去连接路由器/热点来通信。 UDP协议,是传输层协议,UDP没有服务器和客户端的说法。 本实验需要注意,wifi模块/单片机与电脑/手机需要连接在同一个…...

【SQL Server】华中农业大学空间数据库实验报告 实验一 数据库
实验目的 熟悉了解掌握SQL Server软件的基本操作与使用方法,认识界面,了解其两个基本操作系统文件,并能熟练区分与应用交互式与T-SQL式两种方法在SQL Server中如何进行操作;学习有关数据库的基本操作,包括:…...

操作系统页面置换算法Java实现(LFU,OPT,LRU,LFU,CLOCK)
FIFO先进先出算法 java import java.util.LinkedList; import java.util.Queue; public class Main { //先进先出的思想 是 用一个队列去模拟数据 如果当前不存在就是发生缺页中断了 就需要添加 如果已经满了 将队头的元素出队 即可 //先进先出 就是一个数组 frameCount publi…...

Request和Response
前言 这一节主要讲的是Request和Response还有一些实例 1. 介绍 就是这两个参数 WebServlet("/demo7") public class ServletDemo7 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletExcepti…...

【青牛科技】GC8549替代LV8549/ONSEMI在摇头机、舞台灯、打印机和白色家电等产品上的应用分析
引言 在现代电子产品中,控制芯片的性能直接影响到设备的功能和用户体验。摇头机、舞台灯、打印机和白色家电等领域对控制精度、功耗和成本等方面的要求日益提高。LV8549/ONSEMI等国际品牌的芯片曾是这些产品的主要选择,但随着国内半导体技术的进步&…...

(十二)JavaWeb后端开发——MySQL数据库
目录 1.数据库概述 2.MyQSL 3.数据库设计 DDL 4.MySQL常见数据类型 5.DML 1.数据库概述 数据库:DataBase(DB),是存储和管理数据的仓库 数据库管理系统:DataBase ManagementSystem(DBMS),操纵和管理数据库的大型软件 SQL&a…...

pnpm管理多工作区依赖
pnpm是一个支持多包仓库的一个包管理工具,那么怎么可以在项目根目录下执行pnpm install的时候,也能同步让所有的工作区都能够通安装依赖呢? 方式一,在执行pnpm install指令的时候,添加recursive参数: pnpm install --recursive 方式二,在项目的根目录下通过pnpm的配置文件p…...

如何在本地Linux服务器搭建WordPress网站结合内网穿透随时随地可访问
文章目录 前言1. 安装WordPress2. 创建WordPress数据库3. 安装相对URL插件4. 安装内网穿透发布网站4.1 命令行方式:4.2. 配置wordpress公网地址 5. 配置WordPress固定公网地址 前言 本文主要介绍如何在Linux Ubuntu系统上使用WordPress搭建一个本地网站,…...

二、应用层,《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》
文章目录 零、前言一、应用层协议原理1.1 网络应用的体系结构1.1.1 客户-服务器(C/S)体系结构1.1.2 对等体(P2P)体系结构1.1.3 C/S 和 P2P体系结构的混合体 1.2 进程通信1.2.1 问题1:对进程进行编址(addressing)&#…...

面粉直供系统|基于java和小程序的食品面粉直供系统设计与实现(源码+数据库+文档)
面粉直供系统 目录 基于java和小程序的食品面粉直供系统设计与实现 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大厂码农|毕设布道师&#x…...

十四:java web(6)-- Spring Spring MVC
目录 Spring MVC 1.1 Spring MVC 概述 1.1.1 什么是 MVC 模式 1.1.2 Spring MVC 工作原理 1.2 Spring MVC 核心组件 1.2.1 DispatcherServlet 1.2.2 控制器(Controller) 1.2.3 请求映射(RequestMapping) 1.2.4 视图解析器…...

Java代码实现策略模式处理支付付款业务
1.需求:因为付款功能集成的第三方支付SDK越来越来多不好维护,改用策略模式实现,来代替代码中多余的if else 判断。 2.什么是策略模式? 策略模式(Strategy Pattern)是一种行为型设计模式,它允许在运行时选择算法的行为。该模式将不同的算法封装成独立的策略类,并使这些…...

unity3d————四元数概念
一、定义与表示 四元数是由一个实数部分和三个虚数部分组成,通常表示为q w xi yj zk,其中w是实数,x、y、z是实数系数,i、j、k是虚数单位,满足以下关系: i j k -1ij k,ji -kjk i&…...

spring相关的面试题
Spring 框架是 Java 开发中最常用的框架之一,因此在面试中经常会被问到与 Spring 相关的问题。以下是一些常见的 Spring 面试题及其答案。 基础概念 什么是 Spring 框架? Spring 框架是一个开源的 Java 平台,用于构建企业级应用程序。它提供…...

STM32外设之SPI的介绍
### STM32外设之SPI的介绍 SPI(Serial Peripheral Interface)是一种高速的,全双工,同步的通信总线,主要用于EEPROM、FLASH、实时时钟、AD转换器等外设的通信。SPI通信只需要四根线,节约了芯片的管脚&#x…...

二十三、Mysql8.0高可用集群架构实战
文章目录 一、MySQL InnoDB Cluster1、基本概述2、集群架构3、搭建一主两从InnoDB集群3.1、 安装3个数据库实例3.2、安装mysqlrouter和安装mysqlshell3.2.1、安装mysql-router3.2.2、安装mysql-shell 3.3、InnoDB Cluster 初始化3.3.1、参数及权限配置预需求检测3.3.2、初始化I…...