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

STM32外设SPI FLASH应用实例

STM32外设SPI FLASH应用实例

  • 1. 前言
    • 1.1 硬件准备
    • 1.2 软件准备
  • 2. 硬件连接
  • 3. 软件实现
    • 3.1 SPI 初始化
    • 3.2 QW128 SPI FLASH 驱动
    • 3.3 乒乓存储实现
  • 4. 测试与验证
    • 4.1 数据备份测试
    • 4.2 数据恢复测试
  • 5 实例
    • 5.1 参数结构体定义
    • 5.2 存储参数到 SPI FLASH
    • 5.3 从 SPI FLASH 读取参数
    • 5.4 示例:存储和读取参数
    • 5.6 注意事项
  • 6. 总结

1. 前言

在嵌入式系统中,数据的存储和备份是一个非常重要的功能。SPI FLASH 是一种常见的非易失性存储器,具有容量大、速度快、接口简单等优点。本文将介绍如何在 STM32F103 上使用 SPI 接口操作 QW128 SPI FLASH,并通过乒乓存储的方式实现数据备份。

1.1 硬件准备

  • STM32F103 开发板
  • QW128 SPI FLASH 模块
  • 杜邦线若干

1.2 软件准备

  • Keil MDK 或 STM32CubeIDE
  • STM32 HAL 库

2. 硬件连接

将 QW128 SPI FLASH 模块与 STM32F103 开发板连接,具体连接方式如下:

QW128 引脚STM32F103 引脚
CSPA4
SCKPA5
MISOPA6
MOSIPA7
GNDGND
VCC3.3V

在这里插入图片描述

3. 软件实现

使用STM32CUBE配置SPI通信
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.1 SPI 初始化

首先,我们需要初始化 SPI 接口。使用 STM32CubeMX 配置 SPI1 外设,并生成初始化代码。

void MX_SPI1_Init(void)
{hspi1.Instance = SPI1;hspi1.Init.Mode = SPI_MODE_MASTER;hspi1.Init.Direction = SPI_DIRECTION_2LINES;hspi1.Init.DataSize = SPI_DATASIZE_8BIT;hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;hspi1.Init.NSS = SPI_NSS_SOFT;hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi1.Init.TIMode = SPI_TIMODE_DISABLE;hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi1.Init.CRCPolynomial = 10;if (HAL_SPI_Init(&hspi1) != HAL_OK){Error_Handler();}
}

3.2 QW128 SPI FLASH 驱动

接下来,我们编写 QW128 SPI FLASH 的驱动代码,包括读写操作。

#define QW128_CMD_WRITE_ENABLE 0x06
#define QW128_CMD_WRITE_DISABLE 0x04
#define QW128_CMD_READ_STATUS_REG 0x05
#define QW128_CMD_WRITE_STATUS_REG 0x01
#define QW128_CMD_READ_DATA 0x03
#define QW128_CMD_PAGE_PROGRAM 0x02
#define QW128_CMD_SECTOR_ERASE 0x20
#define QW128_CMD_CHIP_ERASE 0xC7void QW128_WriteEnable(void)
{uint8_t cmd = QW128_CMD_WRITE_ENABLE;HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}void QW128_WriteDisable(void)
{uint8_t cmd = QW128_CMD_WRITE_DISABLE;HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}uint8_t QW128_ReadStatusReg(void)
{uint8_t cmd = QW128_CMD_READ_STATUS_REG;uint8_t status;HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY);HAL_SPI_Receive(&hspi1, &status, 1, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);return status;
}void QW128_WriteStatusReg(uint8_t status)
{uint8_t cmd[2] = {QW128_CMD_WRITE_STATUS_REG, status};QW128_WriteEnable();HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, cmd, 2, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}void QW128_ReadData(uint32_t addr, uint8_t *data, uint16_t len)
{uint8_t cmd[4] = {QW128_CMD_READ_DATA, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF};HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, cmd, 4, HAL_MAX_DELAY);HAL_SPI_Receive(&hspi1, data, len, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}void QW128_PageProgram(uint32_t addr, uint8_t *data, uint16_t len)
{uint8_t cmd[4] = {QW128_CMD_PAGE_PROGRAM, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF};QW128_WriteEnable();HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, cmd, 4, HAL_MAX_DELAY);HAL_SPI_Transmit(&hspi1, data, len, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}void QW128_SectorErase(uint32_t addr)
{uint8_t cmd[4] = {QW128_CMD_SECTOR_ERASE, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF};QW128_WriteEnable();HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, cmd, 4, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}void QW128_ChipErase(void)
{uint8_t cmd = QW128_CMD_CHIP_ERASE;QW128_WriteEnable();HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}

3.3 乒乓存储实现

乒乓存储是一种常用的数据备份策略,通过交替使用两个存储区域来确保数据的完整性和可靠性。

#define PAGE_SIZE 256
#define SECTOR_SIZE 4096
#define BUFFER_SIZE 1024uint8_t buffer[BUFFER_SIZE];
uint32_t current_sector = 0;void PingPong_Backup(uint8_t *data, uint16_t len)
{// 擦除当前扇区QW128_SectorErase(current_sector * SECTOR_SIZE);// 写入数据for (uint16_t i = 0; i < len; i += PAGE_SIZE){QW128_PageProgram(current_sector * SECTOR_SIZE + i, data + i, PAGE_SIZE);}// 切换到下一个扇区current_sector = (current_sector + 1) % 2;
}void PingPong_Restore(uint8_t *data, uint16_t len)
{// 读取数据QW128_ReadData(current_sector * SECTOR_SIZE, data, len);
}

4. 测试与验证

4.1 数据备份测试

uint8_t test_data[BUFFER_SIZE];
for (uint16_t i = 0; i < BUFFER_SIZE; i++)
{test_data[i] = i % 256;
}PingPong_Backup(test_data, BUFFER_SIZE);

4.2 数据恢复测试

uint8_t restore_data[BUFFER_SIZE];
PingPong_Restore(restore_data, BUFFER_SIZE);// 验证数据
for (uint16_t i = 0; i < BUFFER_SIZE; i++)
{if (restore_data[i] != test_data[i]){// 数据不一致,处理错误Error_Handler();}
}

5 实例

5.1 参数结构体定义

以下是参数结构体的定义,基于你提供的代码:

typedef enum
{BAUD_9600,BAUD_19200,BAUD_115200
} BAUD_ENUM;typedef struct
{BAUD_ENUM CommBaud;          // 通信波特率uint8_t OnOffCtrl;           // 启停操作方式(0-本地;1-远程485;2-模拟量)uint8_t ModeCtrl;            // 模式修改方式(0-本地;1-远程485;2-模拟量)uint8_t SetValCtrl;          // 设定修改方式(0-本地;1-远程485;2-模拟量)uint8_t MasterSlaver;        // 主副机设置(0-主机;1-副机;2-单机)uint8_t TestMode;            // 测试模式uint8_t DebugMode;           // 调试模式uint8_t DeviceModel;         // 设备型号(0-3KW;2-20KW风冷)uint8_t DeviceSer[32];       // 设备序列号uint8_t AlarmEnable;         // 告警使能(0-关闭;1-使能)uint8_t CommProto;           // 通信协议(0-Modbus;1-Profibus)uint16_t UdcLimit;           // Udc调节限定值uint16_t IdcLimit;           // Idc调节限定值uint16_t PdcLimit;           // Pdc调节限定值uint8_t ModeSlect;           // 调节模式选择(0-Udc;1-Idc;2-Pdc)uint8_t PWM1Freq;            // PWM1频率(40~80表示40KHz~80KHz)
} DeviceParams;

5.2 存储参数到 SPI FLASH

我们可以将参数结构体存储到 SPI FLASH 的指定地址。以下是存储函数的实现:

#include "stm32f1xx_hal.h"
#include "spi_flash.h"  // 假设这是 QW128 SPI FLASH 的驱动头文件#define PARAMS_FLASH_ADDR 0x00000000  // 参数存储的起始地址void SaveParamsToFlash(DeviceParams *params)
{// 擦除 SPI FLASH 的指定扇区QW128_SectorErase(PARAMS_FLASH_ADDR);// 将参数结构体写入 SPI FLASHQW128_PageProgram(PARAMS_FLASH_ADDR, (uint8_t *)params, sizeof(DeviceParams));
}

5.3 从 SPI FLASH 读取参数

从 SPI FLASH 中读取参数结构体的实现如下:

void LoadParamsFromFlash(DeviceParams *params)
{// 从 SPI FLASH 读取参数结构体QW128_ReadData(PARAMS_FLASH_ADDR, (uint8_t *)params, sizeof(DeviceParams));
}

5.4 示例:存储和读取参数

以下是一个完整的示例,展示如何初始化参数、存储到 SPI FLASH 以及从 SPI FLASH 读取参数:

int main(void)
{HAL_Init();SystemClock_Config();MX_SPI1_Init();  // 初始化 SPIMX_GPIO_Init();  // 初始化 GPIO// 初始化参数结构体DeviceParams params = {.CommBaud = BAUD_115200,.OnOffCtrl = 1,.ModeCtrl = 1,.SetValCtrl = 1,.MasterSlaver = 0,.TestMode = 0,.DebugMode = 1,.DeviceModel = 2,.DeviceSer = "1234567890ABCDEF1234567890ABCDEF",.AlarmEnable = 1,.CommProto = 0,.UdcLimit = 1000,.IdcLimit = 500,.PdcLimit = 2000,.ModeSlect = 1,.PWM1Freq = 60};// 存储参数到 SPI FLASHSaveParamsToFlash(&params);// 从 SPI FLASH 读取参数DeviceParams loadedParams;LoadParamsFromFlash(&loadedParams);// 验证读取的参数是否正确if (memcmp(&params, &loadedParams, sizeof(DeviceParams)) == 0){printf("Parameters loaded successfully!\n");}else{printf("Parameter load failed!\n");}while (1){// 主循环}
}

5.6 注意事项

  1. SPI FLASH 的寿命

    • SPI FLASH 的擦写次数有限(通常为 10 万次左右),频繁擦写可能导致损坏。建议在设计中尽量减少擦写操作。
  2. 数据对齐

    • 确保参数结构体的数据对齐与 SPI FLASH 的页大小(通常为 256 字节)匹配,避免跨页写入。
  3. 数据校验

    • 在存储和读取参数时,可以添加 CRC 校验或校验和,确保数据的完整性。
  4. 备份机制

    • 可以使用乒乓存储策略,将参数存储在两个不同的扇区中,确保在一个扇区损坏时可以从另一个扇区恢复数据。

6. 总结

本文介绍了如何在 STM32F103 上使用 SPI 接口操作 QW128 SPI FLASH,并通过乒乓存储的方式实现数据备份。通过这种方式,可以有效地提高数据的可靠性和系统的稳定性。希望本文对大家有所帮助,欢迎在评论区留言讨论。


相关文章:

STM32外设SPI FLASH应用实例

STM32外设SPI FLASH应用实例 1. 前言1.1 硬件准备1.2 软件准备 2. 硬件连接3. 软件实现3.1 SPI 初始化3.2 QW128 SPI FLASH 驱动3.3 乒乓存储实现 4. 测试与验证4.1 数据备份测试4.2 数据恢复测试 5 实例5.1 参数结构体定义5.2 存储参数到 SPI FLASH5.3 从 SPI FLASH 读取参数5…...

PHP支付宝--转账到支付宝账户

官方参考文档&#xff1a; ​https://opendocs.alipay.com/open/62987723_alipay.fund.trans.uni.transfer?sceneca56bca529e64125a2786703c6192d41&pathHash66064890​ 可以使用默认应用&#xff0c;也可以自建新应用&#xff0c;此处以默认应用来讲解【默认应用默认支持…...

太空飞船任务,生成一个地球发射、火星着陆以及下一次发射窗口返回地球的动画3D代码

import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation from mpl_toolkits.mplot3d import Axes3D# 天体参数设置&#xff08;简化模型&#xff09; AU 1.5e8 # 天文单位&#xff08;公里&#xff09; earth_orbital_radius …...

埃拉托斯特尼筛法来生成素数表【C语言】

代码&#xff1a; char *prime(int MAX) {char *a (char*)malloc(MAX * sizeof(char));if (a NULL) {fprintf(stderr, "Memory allocation failed\n");exit(EXIT_FAILURE);}memset(a, 1, MAX * sizeof(char));a[0] 0;a[1] 0;for (int i 2; i * i < MAX; i) …...

VSCode 实用快捷键

前文 VSCode 作为文本编辑神器, 熟练使用其快捷键更是效率翻倍, 本文介绍 VSCode 常用的实用的快捷键 实用快捷键 涉及到文本操作, 搜索定位, 多光标, 面板打开等快捷键 功能快捷键复制光标当前行 (不需要鼠标选中) Ctrl C 剪切光标当前行 (不需要鼠标选中) Ctrl X 当前行下…...

Ubuntu24.04无脑安装docker(含图例)

centos系统请看这篇 Linux安装Docker教程&#xff08;详解&#xff09; 一. ubuntu更换软件源 请看这篇&#xff1a;Ubuntu24.04更新国内源 二. docker安装 卸载老版docker(可忽略) sudo apt-get remove docker docker-engine docker.io containerd runc更新软件库 sudo a…...

近地面无人机植被定量遥感与生理参数反演

近地面无人机植被遥感是指利用无人机&#xff08;UAV&#xff09;搭载传感器&#xff0c;在低空&#xff08;通常低于 100 米&#xff09;对植被进行高分辨率遥感观测和数据采集的技术。这种技术结合了无人机的高灵活性和遥感的高精度&#xff0c;广泛应用于农业、生态学、林业…...

如何创建自定义权限的kubeconfig

如何创建自定义权限的kubeconfig 有些小伙伴问如何做自定义权限的kubeconfig首先看下我们怎么了解我们控制的权限的api以及涉及的资源和动作权限从哪里可以轻松查看了解了上面的&#xff0c;接下来就简单了&#xff0c;和简单的授权流程一致1、创建一个账户2、创建想要的角色或…...

使用 pjsua2 开发呼叫机器人,批量拨打号码并播放固定音频

如何使用 pjsua2 开发呼叫机器人,批量拨打号码并播放固定音频 声明 该播客仅提供实现思路,并非实际的方案记录,不要盲目照搬。 pjsua2库的安装会有较多问题,请参考本人之前的播客进行安装 pjsua2。 pjsua2 库具体的 api 说明请参考开源库内的 范例代码。 引言 在今天的…...

使用nvm管理node.js版本,方便vue2,vue3开发

在Vue项目开发过程中&#xff0c;我们常常会遇到同时维护Vue2和Vue3项目的情况。由于不同版本的Vue对Node.js 版本的要求有所差异&#xff0c;这就使得Node.js 版本管理成为了一个关键问题。NVM&#xff08;Node Version Manager&#xff09;作为一款强大的Node.js 版本管理工具…...

Breakout Tool

思科 CML 使用起来还是很麻烦的&#xff0c;很多操作对于习惯了 secure crt 或者 putty 等工具的网络工程师都不友好。 Breakout Tool 提供对远程实验室中虚拟机控制台与图形界面的本地化接入能力&#xff0c;其核心特性如下&#xff1a; Console 访问&#xff1a;基于 Telnet…...

网络安全-攻击流程-用户层

用户层攻击主要针对操作系统中的用户空间应用程序及用户权限&#xff0c;利用软件漏洞、配置错误或用户行为弱点进行攻击。以下是常见的用户层攻击类型及其流程&#xff0c;以及防御措施&#xff1a; 1. 缓冲区溢出攻击 攻击流程&#xff1a; 目标识别&#xff1a;确定存在漏…...

内网下,Ubuntu (24.10) 离线安装docker最新版教程

一般在数据比较敏感的情况下&#xff0c;是无法使用网络的&#xff0c;而对于Ubuntu系统来说&#xff0c;怎么离线安装docker呢&#xff1f; 下面我给大家来讲一下&#xff1a; 采用二进制安装&#xff1a; 1.下载docker离线包 官网下载&#xff1a; Index of linux/static…...

用deepseek学大模型08-卷积神经网络(CNN)

yuanbao.tencent.com 从入门到精通卷积神经网络(CNN),着重介绍的目标函数&#xff0c;损失函数&#xff0c;梯度下降 标量和矩阵形式的数学推导&#xff0c;pytorch真实能跑的代码案例以及模型,数据&#xff0c;预测结果的可视化展示&#xff0c; 模型应用场景和优缺点&#xf…...

6.【线性代数】—— 列空间和零空间

六 列空间和零空间 1. 列空间 C(A)2. 零空间 N(A)2.1 定义2.2 为什么零空间是一个子空间&#xff1f;2.3 Axb的解空间&#xff0c;是一个子空间吗&#xff1f; 1. 列空间 C(A) [ c o l 11 c o l 21 c o l 31 c o l 12 c o l 22 c o l 32 c o l 13 c o l 23 c o l 33 ] ⏟ A [ a…...

Spring SmartLifecycle:精准控制Bean的生命周期

一、核心作用 SmartLifecycle 是 Spring 框架中用于 精确控制组件生命周期阶段 的高级接口&#xff0c;主要解决三类问题&#xff1a; 有序启停&#xff1a;控制多个组件启动/关闭顺序阶段化处理&#xff1a;将初始化/销毁操作划分为不同阶段上下文感知&#xff1a;获取应用上…...

【ISO 14229-1:2023 UDS诊断(会话控制0x10服务)测试用例CAPL代码全解析②】

ISO 14229-1:2023 UDS诊断【会话控制0x10服务】_TestCase02 作者&#xff1a;车端域控测试工程师 更新日期&#xff1a;2025年02月15日 关键词&#xff1a;UDS诊断、0x10服务、诊断会话控制、ECU测试、ISO 14229-1:2023 TC10-002测试用例 用例ID测试场景验证要点参考条款预期…...

gitee SSH 公钥设置教程

Gitee 提供了基于 SSH 协议的 Git 服务,在使用 SSH 协议访问仓库仓库之前,需要先配置好账户 SSH 公钥。 1、生成秘钥 Windows 用户建议使用 Windows PowerShell 或者 Git Bash,在 命令提示符 下无 cat 和 ls 命令。 ssh-keygen -t ed25519 -C "Gitee SSH Key"中间…...

Wireshark 输出 数据包列表本身的值

在 Wireshark 中&#xff0c;如果你想输出数据包列表本身的值&#xff08;例如&#xff0c;将数据包的摘要信息、时间戳、源地址、目的地址等导出为文本格式&#xff09;&#xff0c;可以使用 导出为纯文本文件 的功能。以下是详细步骤&#xff1a; 步骤 1&#xff1a;打开 Wir…...

electron 学习

文章目录 1.注意项1.1 安装前最好设置一下代理 官网 tutorial https://www.electronjs.org/docs/latest/tutorial/tutorial-prerequisites 1.注意项 1.1 安装前最好设置一下代理 npm config set registry https://registry.npmmirror.com/...

Asp.Net Core MVC 中级开发教程

Asp.Net Core MVC 中级开发教程 一、Asp.Net Core Mvc 区域使用 ASP.NET Core MVC的Areas使用整理 - 天马3798 - 博客园 二、Asp.Net Core 路径处理 Asp.Net Core Web相对路径、绝对路径整理 Asp.Net Core获取当前上下文对象 三、Asp.Net Core 服务使用和封装 四、Asp.Net …...

DeepSeek与ChatGPT的全面对比

在人工智能&#xff08;AI&#xff09;领域&#xff0c;生成式预训练模型&#xff08;GPT&#xff09;已成为推动技术革新的核心力量。OpenAI的ChatGPT自发布以来&#xff0c;凭借其卓越的自然语言处理能力&#xff0c;迅速占据市场主导地位。然而&#xff0c;近期中国AI初创公…...

什么是网络安全?网络安全防范技术包括哪些?

伴随着互联网的发展&#xff0c;它已经成为我们生活中不可或缺的存在&#xff0c;无论是个人还是企业&#xff0c;都离不开互联网。正因为互联网得到了重视&#xff0c;网络安全问题也随之加剧&#xff0c;给我们的信息安全造成严重威胁&#xff0c;而想要有效规避这些风险&…...

使用Java爬虫获取1688按图搜索商品(拍立淘API接口)

在电商领域&#xff0c;按图搜索商品&#xff08;拍立淘&#xff09;是一种非常实用的功能&#xff0c;尤其适合用户通过图片快速查找相似商品。1688开放平台提供了按图搜索商品的API接口&#xff0c;允许开发者通过图片获取相关的商品信息。本文将详细介绍如何使用Java爬虫技术…...

物联网技术赋能预测性维护的深度剖析与前景展望

一、引言 1.1 研究背景与意义 随着信息技术的飞速发展,物联网技术已逐渐渗透到各个行业领域,成为推动产业变革和创新的重要力量。物联网通过将各种设备、物品与互联网连接,实现数据的采集、传输和交互,为各行业带来了前所未有的智能化和自动化水平提升。在工业领域,设备…...

前端工程化的具体实现细节

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

Dav_笔记14:优化程序提示 HINTs -4

指定全局表提示 指定表的提示通常是指发生提示的DELETE&#xff0c;SELECT或UPDATE查询块中的表&#xff0c;而不是指语句引用的任何视图中的表。 如果要为显示在视图中的表指定提示&#xff0c;Oracle建议使用全局提示&#xff0c;而不是在视图中嵌入提示。 您可以使用包含具…...

解锁享元模式:内存优化与性能提升的关键密码

系列文章目录 待后续补充~~~ 文章目录 一、享元模式初相识二、享元模式的核心概念2.1 内部状态与外部状态2.2 享元角色剖析 三、Java 代码中的享元模式3.1 简单示例代码实现3.2 代码解析与关键步骤 四、实际应用场景探秘4.1 文本编辑器中的享元模式4.2 游戏开发中的享元模式4.3…...

负载均衡 方式

DNS 软件负载均衡 Nginx 也是 软件负载均衡 各种策略 1、轮询&#xff08;默认&#xff09; 2、weight&#xff08;权重&#xff09; 3、IP Hash &#xff08;会话粘滞&#xff09; 4、fair 5、UrlHash...

CAS单点登录(第7版)18.日志和审计

如有疑问&#xff0c;请看视频&#xff1a;CAS单点登录&#xff08;第7版&#xff09; 日志和审计 Logging 概述 Logging CAS 提供了一个日志记录工具&#xff0c;用于记录重要信息事件&#xff0c;如身份验证成功和失败;可以对其进行自定义以生成用于故障排除的其他信息。…...

Linux多版本管理工具介绍

一、update-alternatives工具 1. 简介 update-alternatives是Linux系统自带的一个用于管理多个版本命令的工具。它允许用户在不同的软件版本之间进行切换&#xff0c;而不需要手动修改环境变量或者链接文件。 2. 基本使用 查看已安装的alternatives 使用命令update-alterna…...

DeepSeek笔记(二):DeepSeek局域网访问

如果有多台电脑&#xff0c;可以通过远程访问&#xff0c;实现在局域网环境下多台电脑共享使用DeepSeek模型。在本笔记中&#xff0c;首先介绍设置局域网多台电脑访问DeepSeek-R1模型。 一、启动Ollama局域网访问 1.配置环境变量 此处本人的操作系统是Windows11&#xff0c;…...

摄像头畸变矫正

简单介绍 所谓畸变其实就是由摄像头引起的图片失真, 一般在广角摄像头表现明显, 原本平整的桌面通过镜头看像个球面, 直观的解释直线被拍成了曲线, 这让我想起来了一个表情包. 去畸变的办法 首先我们需要一个标准棋盘(印有特定的标定图案), 如图: 把它摊平放在桌子上, 然后用…...

EasyRTC:智能硬件适配,实现多端音视频互动新突破

一、智能硬件全面支持&#xff0c;轻松跨越平台障碍 EasyRTC 采用前沿的智能硬件适配技术&#xff0c;无缝对接 Windows、macOS、Linux、Android、iOS 等主流操作系统&#xff0c;并全面拥抱 WebRTC 标准。这一特性确保了“一次开发&#xff0c;多端运行”的便捷性&#xff0c…...

机器视觉--图像的运算(乘法)

一、引言 在图像处理领域&#xff0c;Halcon 是一款功能强大且广泛应用的机器视觉软件库。它提供了丰富的算子和工具&#xff0c;能够满足各种复杂的图像处理需求。图像的乘法运算作为其中一种基础操作&#xff0c;虽然不像一些边缘检测、形态学处理等操作那样被频繁提及&…...

蓝桥杯 Java B 组之哈希表应用(两数之和、重复元素判断)

Day 5&#xff1a;哈希表应用&#xff08;两数之和、重复元素判断&#xff09; 一、哈希表&#xff08;Hash Table&#xff09;基础 1. 什么是哈希表&#xff1f; 哈希表&#xff08;Hash Table&#xff09; 是一种键值对&#xff08;key-value&#xff09;存储的数据结构&…...

Kafka分区管理大师指南:扩容、均衡、迁移与限流全解析

#作者&#xff1a;孙德新 文章目录 分区分配操作(kafka-reassign-partitions.sh)1.1 分区扩容、数据均衡、迁移(kafka-reassign-partitions.sh)1.2、修改topic分区partition的副本数&#xff08;扩缩容副本&#xff09;1.3、Partition Reassign场景限流1.4、节点内副本移动到不…...

vue 接口传formdata

在Vue中&#xff0c;如果你需要向服务器发送FormData对象&#xff0c;通常是为了上传文件或者需要发送表单数据。FormData是一个非常有用的工具&#xff0c;因为它可以直接使用表单元素的值以及文件内容&#xff0c;并以一种浏览器兼容的方式来发送这些数据。下面是如何在Vue中…...

图像处理篇---基本OpenMV图像处理

文章目录 前言1. 灰度化&#xff08;Grayscale&#xff09;2. 二值化&#xff08;Thresholding&#xff09;3. 掩膜&#xff08;Mask&#xff09;4. 腐蚀&#xff08;Erosion&#xff09;5. 膨胀&#xff08;Dilation&#xff09;6. 缩放&#xff08;Scaling&#xff09;7. 旋转…...

DeepSeek预测25考研分数线

25考研分数马上要出了。 目前&#xff0c;多所大学已经陆续给出了分数查分时间&#xff0c;综合往年情况来看&#xff0c;每年的查分时间一般集中在2月底。 等待出成绩的日子&#xff0c;学子们的心情是万分焦急&#xff0c;小编用最近爆火的“活人感”十足的DeepSeek帮大家预…...

数据融合的经典模型:早期融合、中期融合与后期融合的对比

数据融合是处理多源数据时非常重要的技术&#xff0c;尤其是在多模态学习、传感器网络和智能系统中。它的目标是将来自不同来源、不同模态的数据进行有效结合&#xff0c;从而获得更准确、更全面的信息。在数据融合的过程中&#xff0c;不同的融合策略能够在性能、效率和应用场…...

Linux环境Docker使用代理推拉镜像

闲扯几句 不知不觉已经2月中了&#xff0c;1个半月忙得没写博客&#xff0c;这篇其实很早就想写了&#xff08;可追溯到Docker刚刚无法拉镜像的时候&#xff09;&#xff0c;由于工作和生活上的事比较多又在备考软考架构&#xff0c;拖了好久…… 简单记录下怎么做的&#xf…...

LabVIEW用CANopen的设备属性配置与心跳消息和PDO读取

本示例展示了如何通过SDO&#xff08;服务数据对象&#xff09;配置设备属性&#xff0c;以及如何读取从设备周期性发送的心跳消息和PDO&#xff08;进程数据对象&#xff09;消息。通过该示例&#xff0c;可以有效地进行设备配置并实现数据监控&#xff0c;适用于CANopen网络中…...

DeepSeek01-本地部署大模型

一、ollama简介&#xff1a; 什么是 Ollama&#xff1f; Ollama 是一个用于本地部署和管理大模型的工具。它提供了一个简单的命令行界面&#xff0c; 使得用户可以轻松地下载、运行和管理各种大模型。Ollama 支持多种模型格式&#xff0c; 并且可以与现有的深度学习框架&#x…...

python学opencv|读取图像(七十五)人脸识别:Fisherfaces算法和LBPH算法

【1】引言 前序学习进程中&#xff0c;已经掌握了使用Eigenfaces算法进行的人脸识别。相关文章链接为&#xff1a; python学opencv|读取图像&#xff08;七十四&#xff09;人脸识别&#xff1a;EigenFaces算法-CSDN博客 在此基础上&#xff0c;学习剩余两种人脸识别算法&am…...

UMLS数据下载及访问

UMLS数据申请 这个直接在官网上申请即可&#xff0c;记得把地址填全&#xff0c;基本都会拿到lisence。 UMLS数据访问 UMLS的数据访问分为网页访问&#xff0c;API访问以及数据下载后的本地访问&#xff0c;网页访问&#xff0c;API访问按照官网的指示即可&#xff0c;这里主…...

UE_C++ —— Container TArray

目录 一&#xff0c;TArray 二&#xff0c;Creating and Filling an Array 三&#xff0c;Iteration 四&#xff0c;Sorting 五&#xff0c;Queries 六&#xff0c;Removal 七&#xff0c;Operators 八&#xff0c;Heap 九&#xff0c;Slack 十&#xff0c;Raw Memor…...

第435场周赛:奇偶频次间的最大差值 Ⅰ、K 次修改后的最大曼哈顿距离、使数组包含目标值倍数的最少增量、奇偶频次间的最大差值 Ⅱ

Q1、奇偶频次间的最大差值 Ⅰ 1、题目描述 给你一个由小写英文字母组成的字符串 s 。请你找出字符串中两个字符的出现频次之间的 最大 差值&#xff0c;这两个字符需要满足&#xff1a; 一个字符在字符串中出现 偶数次 。另一个字符在字符串中出现 奇数次 。 返回 最大 差值…...

模拟解决哈希表冲突

目录 解决哈希表冲突原理&#xff1a; 模拟解决哈希表冲突代码&#xff1a; 负载因子&#xff1a; 动态扩容&#xff1a; 总结&#xff1a; HashMap和HashSet的总结&#xff1a; 解决哈希表冲突原理&#xff1a; 黑色代表一个数组&#xff0c;当 出现哈希冲突时&#xff0…...

UIView 与 CALayer 的联系和区别

今天说一下UIView 与 CALayer 一、UIView 和 CALayer 的关系 在 iOS 开发中&#xff0c;UIView 是用户界面的基础&#xff0c;它负责处理用户交互和绘制内容&#xff0c;而 CALayer 是 UIView 内部用于显示内容的核心图层&#xff08;Layer&#xff09;。每个 UIView 内部都有…...