STM32IIC实战-OLED模板
STM32IIC实战-OLED模板
- 一,SSD1306 控制芯片
- 1, 主要特性
- 2,I2C 通信协议
- 3, 显示原理
- 4, 控制流程
- 5, 开发思路
- 二,HAL I2C API 解析
- I2C 相关 API
- 1,
- 2,
- 3,
- 4,
- 5,
- 三,移植 SSD1306 驱动
- 1,获取并放置驱动文件
- 二,CubeMX 配置 I2C
- 四,移植与配置驱动代码
- 1,添加文件到工程:
- 2,添加头文件路径:
- 3,包含头文件:
- 4,修改 I2C 句柄:
- 五,创建应用层接口与任务
- 1,创建应用文件
- 2,编写应用代码
- 3,包含应用头文件
- 六,集成与测试
在掌握了基础的单片机控制和通信之后,是时候为你的项目添加一块小巧而酷炫的显示屏了。OLED (Organic Light-Emitting Diode) 屏幕因其自发光、高对比度、低功耗和宽视角等优点,在嵌入式项目中越来越受欢迎。
本教程将重点介绍如何驱动基于 SSD1306 控制芯片的单色 OLED 显示屏,这种屏幕通常分辨率为 128x64 或 128x32,常用于显示文本、简单图形和状态信息。
我们将使用 STM32 HAL 库,通过 I2C (Inter-Integrated Circuit) 接口与 OLED 模块通信,并详细介绍如何移植一个常用的 SSD1306 驱动库。
一,SSD1306 控制芯片
SSD1306 是一款广泛用于单色 OLED 显示屏的控制器驱动芯片。了解它的基本特性有助于我们更好地进行驱动开发。
1, 主要特性
显示类型: 单色(通常为白色、蓝色或黄蓝双色)被动矩阵 OLED (PMOLED)。
分辨率: 最大支持 128x64 像素。常见的模块有 128x64 (0.96英寸) 和 128x32 (0.91英寸)。
接口: 支持多种通信接口,包括 I2C、SPI (3线或4线) 和并行接口。本教程聚焦于 I2C 接口。
内部 RAM (GDDRAM): 芯片内置图形显示数据 RAM (Graphic Display Data RAM),大小通常为 128x64位 (1KB)。MCU 通过接口将要显示的像素数据写入 GDDRAM,SSD1306 负责根据 GDDRAM 的内容点亮屏幕上的像素点。
工作电压: 逻辑电压通常为 3.3V 或 5V,但屏幕驱动电压可能需要内部电荷泵升压。
控制方式: 通过发送一系列命令来配置显示参数(如对比度、显示开关、地址模式等),并通过发送数据来更新 GDDRAM 内容。
2,I2C 通信协议
当使用 I2C 接口时,SSD1306 模块通常表现为一个 I2C 从设备,拥有一个固定的设备地址(通常是 0x78 或 0x7A,可能通过模块上的跳线选择)。
与 SSD1306 的 I2C 通信包含两种主要类型的传输:
写命令 (Write Command): MCU 向 SSD1306 发送控制字节,用于设置显示模式、对比度等。
写数据 (Write Data): MCU 向 SSD1306 发送数据字节,这些字节会被写入 GDDRAM,用于更新屏幕显示内容。
SSD1306 通过一个特定的控制字节来区分接收到的数据是命令还是数据。通常,控制字节的格式为:
命令: 0x00 (Co=0, D/C#=0) + Command Byte
数据: 0x40 (Co=0, D/C#=1) + Data Byte
因此,MCU 在发送命令或数据前,需要先发送对应的控制字节。
3, 显示原理
SSD1306 驱动的是被动矩阵 OLED (PMOLED)。屏幕由水平的行线 (Common Electrodes, SEG) 和垂直的列线 (Segment Electrodes, COM) 交叉构成。每个交叉点就是一个像素 (一个 OLED 发光点)。
GDDRAM 映射: 芯片内部的 GDDRAM (图形显示数据 RAM) 存储了每个像素的开关状态。对于 128x64 的屏幕,GDDRAM 通常是 1KB (128 * 64 / 8 = 1024 bytes)。GDDRAM 中的每一位 (bit) 对应屏幕上的一个像素:‘1’ 表示点亮,‘0’ 表示熄灭。
扫描与驱动: SSD1306 通过快速、分时地扫描 COM 线,并根据 GDDRAM 中的数据控制 SEG 线上的电平,来逐行(或逐页)点亮对应的像素。由于人眼的视觉暂留效应,我们感觉整个屏幕是同时亮的。
页面结构: GDDRAM 通常按"页 (Page)"组织。对于 128x64 屏幕,通常分为 8 页 (Page 0 ~ Page 7),每页包含 128 列 x 8 行像素 (128 bytes)。写入数据时,通常需要先设置目标页地址和列地址。
理解 GDDRAM 与像素的映射关系以及页面结构,对于直接操作显存或编写底层驱动至关重要。
4, 控制流程
与 SSD1306 交互通常遵循以下基本流程:
初始化序列 (Initialization Sequence): 上电后,需要向 SSD1306 发送一系列特定的命令来配置其工作状态。这通常包括:
解锁命令(如果需要)。
关闭显示 (0xAE)。
设置显示时钟分频系数和振荡器频率。
设置 MUX 复用比 (决定扫描行数,如 64 行对应 0xA8, 0x3F)。
设置显示偏移 (0xD3, 0x00)。
设置起始行 (0x40 | 0x00)。
配置电荷泵 (Charge Pump) 以产生 OLED 所需的高电压 (0x8D, 0x14)。
配置内存地址模式 (水平、垂直或页面地址模式,0x20, 0x00/0x01/0x02)。
设置 SEG/COM 引脚硬件配置 (0xDA, 0x12)。
设置对比度 (0x81, 0xCF)。
设置预充电周期 (0xD9, 0xF1)。
设置 VCOMH 电压 (0xDB, 0x40)。
设置整个屏幕显示来自 GDDRAM (0xA4) 或强制点亮 (0xA5)。
设置正常/反相显示 (0xA6 / 0xA7)。
开启显示 (0xAF)。
这个初始化序列非常关键,通常由驱动库的 OLED_Init()
函数完成。命令和参数的具体值可能因模块或驱动库而异。
设置地址指针: 在写入像素数据之前,需要发送命令设置 GDDRAM 的目标页地址和列地址 (例如,使用页面地址模式时,发送 0xB0 | page_num, 0x00 | (col & 0x0F), 0x10 | (col >> 4))。
写入数据: 发送写数据指令 (控制字节 0x40) 和随后的像素数据字节。数据会根据设置的地址模式自动写入 GDDRAM,并且地址指针通常会自动递增。
重复 2 和 3: 根据需要更新屏幕的不同区域。
例如,清屏操作本质上就是将 GDDRAM 的所有字节都设置为 0x00。
5, 开发思路
在项目中集成 OLED 显示时,有几种常见的开发策略:
直接命令操作: 直接根据 SSD1306 数据手册发送 I2C/SPI 命令和数据。这种方式最灵活,但也最复杂,需要深入理解芯片细节。适用于资源极其受限或需要高度定制的场景。
封装底层驱动库: 编写或移植一个基础驱动库(如此教程第 4 节示例)。该库封装初始化序列、基本的写命令/数据函数,以及一些基础绘图函数(如清屏、设置点、显示字符/字符串)。这是比较常见的做法,在复杂度和易用性之间取得平衡。
使用图形库 (如 u8g2): 对于需要绘制复杂图形、使用多种字体或构建用户界面的应用,强烈推荐使用成熟的图形库(如此教程第 5 节的 u8g2)。这些库提供了丰富的 API,屏蔽了底层的硬件细节,开发者可以专注于应用逻辑。缺点是会占用更多的 Flash 和 RAM 资源。
显存管理策略:
全缓冲 (Full Buffer): 在 MCU 的 RAM 中创建一个与 OLED 显存同样大小的缓冲区。所有绘图操作先更新 RAM 缓冲区,最后一次性将整个缓冲区发送到 OLED。优点是绘图灵活,避免闪烁;缺点是占用较多 RAM (例如 128x64 屏需要 1KB RAM)。u8g2 的 _f
后缀模式即为此。
页缓冲 (Page Buffer / Partial Buffer): 只在 MCU RAM 中创建一页或几页大小的缓冲区。绘图时按页进行,绘制完一页就发送一页。优点是 RAM 占用少;缺点是绘图逻辑相对复杂,跨页绘制需要特殊处理。u8g2 的 _1
(单页) 或 _2
(双页) 后缀模式属于此类。
无缓冲 (Direct Draw): 不在 MCU 中创建缓冲区,直接计算像素位置并发送命令/数据到 OLED。RAM 占用最少,但绘图效率最低,且容易产生闪烁,通常只适用于非常简单的静态显示。
选择哪种开发思路和显存管理策略,需要根据项目需求、MCU 资源限制以及开发效率要求来权衡。
二,HAL I2C API 解析
STM32 HAL 库为我们提供了方便的函数来操作 I2C 外设,从而与 SSD1306 进行通信。以下是驱动 OLED 时常用的一些 HAL I2C API。
I2C 相关 API
1,
I2C_HandleTypeDef (句柄)
这是 I2C 外设的"控制器"结构体。它包含了 I2C 的配置信息(如时钟速度、地址模式、使用的引脚等)、运行时状态和错误代码。所有 I2C 相关的 HAL 函数都需要传递一个指向该类型结构体的指针(例如 &hi2c1
)。该结构体通常由 CubeMX 自动生成和初始化。
2,
HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c)
用途: 根据 I2C_HandleTypeDef
结构体中的配置信息初始化 I2C 外设。
参数: hi2c - 指向 I2C 句柄的指针。
返回: HAL_OK (成功), HAL_ERROR, HAL_BUSY。
说明: 通常在系统启动时由 CubeMX 生成的 MX_I2C1_Init()
(或类似) 函数内部调用。我们一般不需要手动调用它。
3,
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
用途: 以 Master 模式通过 I2C 发送数据到指定的从设备地址。
参数:
hi2c: 指向 I2C 句柄的指针。
DevAddress: 目标从设备的 7 位地址。注意: HAL 库通常需要传入左移一位的地址(即包含读写位的 8 位地址格式,但最低位会被函数内部处理)。例如,如果 OLED 地址是 0x3C (7位),则应传入 0x3C << 1 或 0x78。具体请参考 HAL 库文档或示例。驱动库内部通常会处理好地址。
pData: 指向要发送的数据缓冲区的指针。
Size: 要发送的数据字节数。
Timeout: 发送超时时间(毫秒)。
返回: HAL_OK, HAL_ERROR, HAL_BUSY, HAL_TIMEOUT。
说明: 这是向 OLED 发送命令或数据的主要方式之一。pData
缓冲区通常需要包含 SSD1306 需要的控制字节 (0x00 或 0x40) 以及后续的命令/数据字节。
4,
HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
用途: 向 I2C 从设备的指定内存地址写入数据。这个函数在很多 I2C 设备驱动中常用,对于 SSD1306 来说,它可以巧妙地用来发送命令和数据。
参数:
hi2c: 指向 I2C 句柄的指针。
DevAddress: 目标从设备的 7 位地址 (同样需要注意左移)。
MemAddress: 目标内存地址。对于 SSD1306,这个参数可以被用来传递控制字节 (0x00 用于命令, 0x40 用于数据)。
MemAddSize: 内存地址的大小,对于传递控制字节,通常设置为 I2C_MEMADD_SIZE_8BIT。
pData: 指向要写入的数据缓冲区的指针 (实际的命令字节或像素数据)。
Size: 要写入的数据字节数。
Timeout: 超时时间(毫秒)。
返回: HAL_OK, HAL_ERROR, HAL_BUSY, HAL_TIMEOUT。
说明: 许多 SSD1306 驱动库(包括我们将要移植的库)会使用 HAL_I2C_Mem_Write
来发送命令和数据。例如,发送一个命令字节 CMD
,会调用 HAL_I2C_Mem_Write(&hi2c1, OLED_ADDR, 0x00, I2C_MEMADD_SIZE_8BIT, &CMD, 1, TIMEOUT)
。发送一个数据字节 DATA
,会调用 HAL_I2C_Mem_Write(&hi2c1, OLED_ADDR, 0x40, I2C_MEMADD_SIZE_8BIT, &DATA, 1, TIMEOUT)
。这种方式简化了驱动代码。
5,
HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout)
用途: 检查指定的 I2C 从设备是否在线并响应其地址。
参数:
hi2c: 指向 I2C 句柄的指针。
DevAddress: 要检查的从设备地址 (同样需要注意左移)。
Trials: 尝试发送地址的次数。
Timeout: 每次尝试的超时时间。
返回: HAL_OK (设备响应), HAL_ERROR, HAL_BUSY, HAL_TIMEOUT (设备未响应)。
说明: 在初始化 OLED 之前,可以调用此函数来确认 OLED 模块是否正确连接并且 I2C 通信正常。有助于调试硬件连接问题。
理解这些基本的 I2C 通信函数,特别是
HAL_I2C_Master_Transmit
或HAL_I2C_Mem_Write
如何被用来发送命令和数据,是成功驱动 OLED 的关键。
三,移植 SSD1306 驱动
1,获取并放置驱动文件
1,在你的项目文件夹(例如 Keil 项目根目录)下,创建一个用于存放第三方组件的文件夹,例如 Components
。
2,在 Components
文件夹内,再创建一个 Oled
文件夹。
创建 Oled 文件夹
3,从下面 Github 仓库下载驱动文件(通常是一个 ZIP 压缩包)。
https://github.com/yangjinhaoaa/OLED0.91-SSD1306-HAL
4,解压下载的文件。找到包含驱动源文件(如 oled.c
, oled.h
, oledfont.h
等)的文件夹(根据文档描述,可能是名为 0.91OLED-SSD1306-STM32HAL
的文件夹)。
5,将该文件夹中的所有 .c
和 .h
文件复制到你之前创建的 Components/Oled
文件夹中。
二,CubeMX 配置 I2C
1,确定引脚: 查阅你的开发板原理图或 OLED 模块说明,确定连接到 STM32 的 I2C SCL (时钟) 和 SDA (数据) 引脚。文档示例使用的是 PB8 (SCL) 和 PB9 (SDA)。
再CubeMX中找到IIC1,先不要使能,先根据上面原理图选择配置的引脚
模式选择为IIC模式,在下方的配置区域 (Configuration),确认 I2C 的参数设置。标准模式 (Standard Mode) 速度 100kHz 或快速模式 (Fast Mode) 400kHz(这里选择快速模式用于后面的u8g2移植) 通常都可以。其他参数可以暂时保持默认。
确保对应的 SCL 和 SDA 引脚已在右侧芯片图上正确分配给所选的 I2C 功能。
生成代码
四,移植与配置驱动代码
1,添加文件到工程:
在 Keil 的 Project 窗口中,右键点击你的目标分组(或新建一个分组,如 Components
),选择 “Add Existing Files to Group…”。
导航到 Components/Oled
文件夹,选择 oled.c
文件并添加。
2,添加头文件路径:
点击魔术棒图标 (Options for Target)。
切换到 “C/C++” 选项卡。
在 “Include Paths” 旁边的文本框后面的 “…” 按钮点击。
添加 Components/Oled
文件夹的路径。
3,包含头文件:
在你项目的主要头文件(例如 main.h
或一个自定义的 mydefine.h
)中,添加 #include "oled.h"
。
4,修改 I2C 句柄:
打开 oled.c
文件。找到驱动代码中使用 I2C 发送函数的地方(通常是调用 HAL_I2C_Mem_Write
或类似函数)。将代码中使用的 I2C 句柄(文档示例中是 &hi2c2
)修改为你项目中实际使用的 I2C 句柄(由 CubeMX 生成,例如 &hi2c1
)。
CubeMX生成的iic文件中,有一个hi2c1句柄
但组件库中使用的是hi2c2句柄,将组件库的句柄修改为我们实际使用的句柄
同时确保组件库中的iic设备地址与我们使用的芯片地址相同
五,创建应用层接口与任务
1,创建应用文件
在你的应用代码文件夹(例如 APP
或 Application
)中,创建 oled_app.c
和 oled_app.h
文件。将 oled_app.c
添加到 Keil 工程中。
2,编写应用代码
将文档中提供的 oled_app.h
和 oled_app.c
的内容复制到对应文件中。Oled_Printf
函数提供了一个方便的、类似 printf
的接口来在 OLED 上显示格式化字符串。oled_task
是一个示例任务,用于显示简单文本。
/* oled_app.h */
#ifndef __OLED_APP_H__
#define __OLED_APP_H__#include "main.h" // 或者你的主要头文件 "mydefine.h"
#include // 需要包含 stdarg.h 用于 va_list
#include // 需要包含 stdio.h 用于 vsnprintf
#include "oled.h" // 包含底层 OLED 驱动头文件int Oled_Printf(uint8_t x, uint8_t y, const char *format, ...);
void oled_task(void);#endif/* oled_app.c */
#include "oled_app.h"// 假设 OLED 宽度为 128 像素,使用 6x8 字体
// 每行 8 像素高,最多 64/8 = 8 行 (y=0~7) 或 32/8 = 4 行 (y=0~3)
// 每列 6 像素宽,最多 128/6 = 21 个字符 (x=0~20? 驱动库可能基于像素位置)
// **注意:** Oled_Printf 的 x, y 参数单位需要参考 OLED_ShowStr 实现,可能是字符位置或像素位置
// 文档中的注释 (0-127, 0-3) 暗示可能是 128x32 屏幕的像素 x 坐标和字符行 y 坐标/*** @brief 使用类似printf的方式显示字符串,显示6x8大小的ASCII字符* @param x 起始 X 坐标 (像素) 或 字符列位置 (需要看 OLED_ShowStr)* @param y 起始 Y 坐标 (像素) 或 字符行位置 (需要看 OLED_ShowStr, 0-3 或 0-7)* @param format, ... 格式化字符串及参数* 例如:Oled_Printf(0, 0, "Data = %d", dat);
**/
int Oled_Printf(uint8_t x, uint8_t y, const char *format, ...)
{char buffer[128]; // 缓冲区大小根据需要调整va_list arg;int len;va_start(arg, format);len = vsnprintf(buffer, sizeof(buffer), format, arg);va_end(arg);// 假设 OLED_ShowStr 使用像素坐标 x 和字符行 yOLED_ShowStr(x, y, (uint8_t*)buffer, 8); // 将 buffer 转为 uint8_t*return len;
}/* Oled 显示任务 */
void oled_task(void)
{// 清屏通常是需要的,否则旧内容会保留OLED_Cls();Oled_Printf(0, 0, "Hello World!!!");Oled_Printf(0, 2, "Welcome to MCU!");// 刷新显示到屏幕 (如果驱动库需要)// OLED_Refresh_Gram(); // 取决于驱动库是否有显存刷新机制
}
注意: 上述
Oled_Printf
的实现假设OLED_ShowStr
的 y 参数是像素坐标。如果OLED_ShowStr
的 y 参数是字符行号,则调用应改为OLED_ShowStr(x, y, (uint8_t*)buffer, 8);
。请查阅你移植的oled.c
中OLED_ShowStr
函数的注释或实现来确认。同时,可能需要调用清屏函数OLED_Cls()
和刷新函数(如果驱动库有缓冲区机制)。
3,包含应用头文件
在你的主要头文件(例如 main.h
或 mydefine.h
)中添加 #include "oled_app.h"
。
六,集成与测试
1,调用初始化: 在 main.c
文件的 main
函数中,在 I2C 初始化 (MX_I2C1_Init()
) 之后,调用 OLED 初始化函数。
2,集成到任务调度器 (如果使用): 如果你使用了任务调度器(如文档中的 scheduler.c
),将 oled_task
添加到任务列表中,并设置合适的执行周期(例如 100ms 或 500ms,取决于刷新需求)。
3,编译和下载: 编译整个工程,并将生成的目标文件下载到你的 STM32 开发板。
4,观察结果: 如果一切顺利,你的 OLED 屏幕应该会显示 “Hello World!!!” 和 “Welcome to MCU!”。
调试提示: 如果屏幕没有显示或显示异常:
检查硬件连接: 确认 SCL, SDA, VCC, GND 连接牢固且正确。
检查 I2C 地址: 确认驱动代码中的OLED_ADDRESS
与模块地址匹配。
检查 I2C 句柄: 确认oled.c
中使用的 I2C 句柄 (&hi2c1
?) 与 CubeMX 生成的一致。
使用HAL_I2C_IsDeviceReady
: 在OLED_Init()
之前调用此函数检查设备是否响应。
查看OLED_Init()
: 确保初始化函数被成功调用。
确认Oled_Printf
实现: 检查OLED_ShowStr
的参数含义,调整Oled_Printf
中的调用。
清屏与刷新: 确保在显示前调用了清屏函数,并在需要时调用了刷新函数(如果驱动库有缓冲区机制)。
相关文章:
STM32IIC实战-OLED模板
STM32IIC实战-OLED模板 一,SSD1306 控制芯片1, 主要特性2,I2C 通信协议3, 显示原理4, 控制流程5, 开发思路 二,HAL I2C API 解析I2C 相关 API1,2,3,4…...
BMVC2023 | 多样化高层特征以提升对抗迁移性
Diversifying the High-level Features for better Adversarial Transferability 摘要-Abstract引言-Introduction相关工作-Related Work方法-Methodology实验-Experiments结论-Conclusion 论文链接 GitHub链接 本文 “Diversifying the High-level Features for better Adve…...
C++ deque双端队列、deque对象创建、deque赋值操作
在deque中,front()是头部元素,back()指的是尾部元素。begin()是指向头部的迭代器,end()是指向尾部的下一个元素的迭代器。 push_front 头部进行插入 pop_front 尾部进行删除 push_back 尾部进行插入 pop_back 尾部进行删除 deque如果同时…...
【论文阅读】人脸修复(face restoration ) 不同先验代表算法整理2
文章目录 一、前述二、不同的先验及代表性论文2.1 几何先验(Geometric Prior)2.2 生成式先验(Generative Prior)2.3 codebook先验(Vector Quantized Codebook Prior)2.4 扩散先验 (Diffusion Pr…...
2025年渗透测试面试题总结-百度面经(题目+回答)
网络安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 百度面经 百度安全工程师面试深度复盘与优化指南 一、项目经验反思与优化策略 二、技术问题深度解析 …...
muduo库TcpConnection模块详解——C++
muduo库中的TcpConnection模块详解 TcpConnection是muduo库中处理TCP连接的核心模块,负责管理单个TCP连接的生命周期、数据读写、状态转换以及事件回调。每个TCP连接对应一个TcpConnection对象,其设计体现了高性能、线程安全和灵活回调的特点。 一、核心…...
aksharetools:大模型智能体框架agno可直接获取A股金融数据
原创内容第889篇,专注智能量化投资、个人成长与财富自由。 今天说说金融智能体开发。 智能体开发需要一个多agent框架。这样的框架,现在太多了,langchain, langgraph,autogen,crewai等等,还有各种低代码平…...
使用Maven部署WebLogic应用
使用Maven部署WebLogic应用 在Maven项目中部署应用到WebLogic服务器可以通过以下几种方式实现: 1. 使用WebLogic Maven插件 (官方推荐) Oracle提供了官方的WebLogic Maven插件,这是最直接的部署方式。 基本配置 <build><plugins><pl…...
[Java][Leetcode simple] 13. 罗马数字转整数
一、自己想的 只有提到的六种情况是-,其他都是 public int romanToInt1(String s) {int res 0;int n s.length();Map<Character, Integer> map new HashMap<>();map.put(I, 1);map.put(V, 5);map.put(X, 10);map.put(L, 50);map.put(C, 100);map.pu…...
【论文阅读】针对BEV感知的攻击
Understanding the Robustness of 3D Object Detection with Bird’s-Eye-View Representations in Autonomous Driving 这篇文章是发表在CVPR上的一篇文章,针对基于BEV的目标检测算法进行了两类可靠性分析,即恶劣自然条件以及敌对攻击。同时也提出了一…...
Ansible模块——设置软件仓库和安装软件包
设置软件仓库 ansible.builtin.rpm_key ansible.builtin.rpm_key 用于在 Fedora/RHEL 上导入或移除 GPG 公钥。 参数名 类型 默认值 说明 fingerprintstrnull 指定公钥的完整指纹(long-form)。在导入前会比对公钥是否匹配此指纹,增强安全…...
基于CentOS7制作OpenSSL 1.1的RPM包
背景:CentOS7 已经不再维护了,有时候需要升级某些组件,网上却没有相关的资源了。尤其是制作OpenSSH 9.6 的RPM包,就会要求OpenSSL为1.1的版本。基于此,还是自己制作吧,以下是踩坑过程。 1、官网提供的源码包…...
【Element UI】表单及其验证规则详细
Form表单 Form表单验证1. 使用方法2. rule参数3. validator回调函数异步服务器验证 Form表单验证 Form组件提供了表单验证的功能,需要通过rules属性传入约定的验证规则,并将Form-Item的prop属性设置为需校验的字段名 1. 使用方法 结构: &…...
使用 Python 打造一个强大的文件系统结构创建器
本文将深入分析一个基于 wxPython 的文件系统结构创建器程序,展示如何通过 CustomTreeCtrl 组件实现文件夹和文件的可视化管理,并提供添加、删除、导入、清空以及创建文件系统结构的强大功能。这个程序不仅适合开发者快速构建文件系统原型,还…...
面试真题 - 高并发场景下Nginx如何优化
Nginx是一款高性能的Web服务器和反向代理服务器,以其轻量级、高并发处理能力和稳定性闻名。在面对高并发场景时,合理的配置与优化策略至关重要,以确保服务的稳定性和响应速度。 以下是针对Nginx进行高并发优化的一些关键配置和策略ÿ…...
学习笔记:黑马程序员JavaWeb开发教程(2025.4.6)
12.4 登录校验-JWT令牌-介绍 JWT(JSON Web Token) 简洁是指JWT是一个简单字符串,自包含指的是JWT令牌,看似是一个随机字符串,但是可以根据需要,自定义存储内容 Header是JSON数据格式,原始JSO…...
机器学习——逻辑回归
一、逻辑回归概念点 逻辑回归(Logistic Regression)是一种广泛使用的统计分析方法和机器学习算法,主要用于处理二分类问题(即因变量为二元类别,如0和1、是和否等)。尽管名字中有“回归”二字,但…...
服务间的“握手”:OpenFeign声明式调用与客户端负载均衡
现在,假设我们有一个新的order-service,它在创建订单时需要获取用户信息。 如果order-service直接硬编码user-service的IP和端口进行调用,会面临以下问题: 缺乏弹性: 如果user-service实例的IP或端口发生变化(在云环境…...
蓝桥杯11届国B 答疑
题目描述 有 n 位同学同时找老师答疑。每位同学都预先估计了自己答疑的时间。 老师可以安排答疑的顺序,同学们要依次进入老师办公室答疑。 一位同学答疑的过程如下: 首先进入办公室,编号为 i 的同学需要 si 毫秒的时间。然后同学问问题老…...
【单机版OCR】清华TH-OCR v9.0免费版
今天向大家介绍一款非常好用的单机版OCR图文识别软件,它不仅功能多,识别能力强,而且还是免费使用的。OCR软件为什么要使用单机版,懂得都懂,因为如果使用在线识别的OCR软件,用户需要将文档上传互联网服务器的…...
蓝牙耳机什么牌子好?倍思值得冲不?
最近总被问“蓝牙耳机什么牌子好”,作为踩过无数坑的资深耳机党,必须安利刚入手的倍思M2s Pro主动降噪蓝牙耳机!降噪、音质、颜值全都在线,性价比直接拉满。 -52dB降噪,通勤摸鱼神器 第一次开降噪就被惊到!…...
Java卡与SSE技术融合实现企业级安全实时通讯
简介 在数字化转型浪潮中,安全与实时数据传输已成为金融、物联网等高安全性领域的核心需求。本文将深入剖析东信和平的Java卡权限分级控制技术与浪潮云基于SSE的大模型数据推送技术,探索如何将这两项创新技术进行融合,构建企业级安全实时通讯系统。通过从零到一的开发步骤,…...
使用Spring Boot和Spring Security构建安全的RESTful API
使用Spring Boot和Spring Security构建安全的RESTful API 引言 在现代Web开发中,安全性是构建应用程序时不可忽视的重要方面。本文将介绍如何使用Spring Boot和Spring Security框架构建一个安全的RESTful API,并结合JWT(JSON Web Token&…...
Win11下轻松搭建wiki.js,Docker.desktop部署指南(mysql+elasticsearch+kibana+wiki.js)
Docker.desktop部署wiki.js指南 前言环境和要求介绍提前准备 1. elasticsearch1.1 部署容器1.2 参数说明1.3 验证容器是否部署成功 2. kibana2.1 部署容器2.2 验证是否部署成功2.3 安装IK分词器 3. MySql3.1 部署容器3.2 增加数据库和wiki.js所需要的账号 4. wiki.js4.1 部署容…...
【JavaWeb】MySQL
1 引言 1.1 为什么学? 在学习SpringBootWeb基础知识(IOC、DI等)时,在web开发中,为了应用程序职责单一,方便维护,一般将web应用程序分为三层,即:Controller、Service、Dao 。 之前的案例中&am…...
数据库实验报告 数据定义操作 3
实验报告(第3次) 实验名称 数据定义操作 实验时间 10月12日1-2节 一、实验内容 1、本次实验是用sql语句创建库和表,语句是固定的,要求熟记这些sql语句。 二、源程序及主…...
寻找树的中心(重心)
题目: 思路: “剥洋葱”:每次剥掉一层叶子结点,直到最后剩余不多于2个节点,这些节点就是树的中心(重心)。 解释: 1、根据图论的知识可以知道,一颗树的中心(…...
Oracle 高水位线(High Water Mark, HWM)
1. 高水位线(HWM)的定义 基本概念:HWM 是 Oracle 数据库中一个段(如表、索引)中已分配并被格式化(Formatted)的存储空间的最高位置。它标识了该段历史上曾达到的最大数据块使用量。 物理意义&a…...
Redis学习专题(二)事务和锁机制
目录 引言 1、事务三特性 2、事务相关指令 :Multi、Exec、discard 快速入门 注意: 3、事务冲突 解决办法: 1.悲观锁 2.乐观锁 3.watch & unwatch 引言 Redis 的事务是什么? 1、Redis 事务是一个单独的隔离操作:事…...
多平台!像素艺术的最佳选择 , 开源像素画工具
项目简介 如果你喜欢作像素风格的游戏或动画,那么这款Pixelorama或许是你的好帮手。它是一款免费开源的像素画编辑器,功能丰富,操作便捷,支持多平台使用(Windows、macOS、Linux)。无论你是像素新手还是老手…...
使用 Kotlin 和 Jetpack Compose 开发 Wear OS 应用的完整指南
环境配置与项目搭建 1. Gradle 依赖配置 // build.gradle (Module) android {buildFeatures {compose true}composeOptions {kotlinCompilerExtensionVersion "1.5.3"} }dependencies {def wear_compose_version "1.2.0"implementation "androidx.…...
JavaScript【5】DOM模型
1.概述: DOM (Document Object Model):当页面被加载时,浏览器会创建页面的文档对象模型,即dom对象;dom对象会被结构化为对象树,如一个HTML文档会被分为head,body等部分,而每个部分又…...
【诊所电子处方专用软件】佳易王个体诊所门诊电子处方开单管理系统:零售药店电子处方服务系统#操作简单#诊所软件教程#药房划价
一、软件试用版资源文件下载说明 (一)若您想体验软件功能,可通过以下方式获取软件试用版资源文件: 访问头像主页:进入作者头像主页,找到第一篇文章,点击文章最后的卡片按钮,即可了…...
【OpenCV】帧差法、级联分类器、透视变换
一、帧差法(移动目标识别): 好处:开销小,不怎么消耗CPU的算力,对硬件要求不高,但只适合固定摄像头 1、优点 计算效率高,硬件要求 响应速度快,实时性强 直接利用连续帧…...
OpenCV 特征检测全面解析与实战应用
在计算机视觉领域,特征检测是从图像中提取关键信息的核心技术,这些关键特征是图像匹配、目标识别、场景理解等复杂任务的基础。OpenCV 作为计算机视觉领域最受欢迎的开源库之一,提供了丰富且高效的特征检测算法。本文将深入介绍 OpenCV 中多种…...
AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年5月17日第80弹
从今天开始,咱们还是暂时基于旧的模型进行预测,好了,废话不多说,按照老办法,重点8-9码定位,配合三胆下1或下2,杀1-2个和尾,再杀6-8个和值,可以做到100-300注左右。 (1)定…...
IDEA反斜杠路径不会显示JUnit运行的工作目录配置问题
1. 当在IDEA基准目录下创建junit-reflect-annotation-proxy-app\\src\\data.txt时,如果是Mac电脑,这种\\文件路径时,IDEA里面不会显示,但在Finder下会显示,是直接创建了文件名为junit-reflect-annotation-proxy-app\sr…...
Linux517 rsync同步 rsync借xinetd托管 配置yum源回顾
计划测试下定时服务 同步成功 是否为本地YUM源内容太少?考虑网络YUM源 单词拼错了 计划后面再看下 MX安装 参考 计划回顾配置YUM源 配置本地YUM源配置外网YUM源配置仓库YUM源(不熟) 参考 参考阿里云 配置完毕 本地yum源配置 先备份 再…...
【论文阅读】A Survey on Multimodal Large Language Models
目录 前言一、 背景与核心概念1-1、多模态大语言模型(MLLMs)的定义 二、MLLMs的架构设计2-1、三大核心模块2-2、架构优化趋势 三、训练策略与数据3-1、 三阶段训练流程 四、 评估方法4-1、 闭集评估(Closed-set)4-2、开集评估&…...
大型语言模型中的QKV与多头注意力机制解析
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
React Flow 节点事件处理实战:鼠标 / 键盘事件全解析(含节点交互代码示例)
本文为《React Agent:从零开始构建 AI 智能体》专栏系列文章。 专栏地址:https://blog.csdn.net/suiyingy/category_12933485.html。项目地址:https://gitee.com/fgai/react-agent(含完整代码示例与实战源)。完整介绍…...
AIGC在电商行业的应用:革新零售体验
AIGC在电商行业的应用:革新零售体验 引言 人工智能生成内容(AIGC)正在深刻改变电商行业的格局。从个性化推荐到智能客服,从产品描述生成到虚拟试衣,AIGC技术正在为电商平台带来前所未有的创新和效率提升。本文将深入探…...
【数据结构】线性表--队列
【数据结构】线性表--队列 一.什么是队列二.队列的实现1.队列结构定义:2.队列初始化函数:3.队列销毁函数:4.入队列函数(尾插):5.出队列函数(头删):6.取队头元素ÿ…...
CSS- 4.1 浮动(Float)
本系列可作为前端学习系列的笔记,代码的运行环境是在HBuilder中,小编会将代码复制下来,大家复制下来就可以练习了,方便大家学习。 HTML系列文章 已经收录在前端专栏,有需要的宝宝们可以点击前端专栏查看! 点…...
Node.js 源码架构详解
Node.js 的源码是一个庞大且复杂的项目,它主要由 C 和 JavaScript 构成。要完全理解每一部分需要大量的时间和精力。我会给你一个高层次的概述,并指出一些关键的目录和组件,帮助你开始探索。 Node.js 的核心架构 Node.js 的核心可以概括为以…...
OpenCV级联分类器
概念 OpenCV 级联分类器是一种基于 Haar 特征、AdaBoost 算法和级联结构的目标检测方法,通过多阶段筛选快速排除非目标区域,实现高效实时检测(如人脸、行人等)。 加载级联分类器 // 加载级联分类器CascadeClassifier cascade;// …...
远程主机状态监控-GPU服务器状态监控-深度学习服务器状态监控
远程主机状态监控-GPU服务器状态监控-深度学习服务器状态监控 ⭐️ 推荐文章: DockerPyCharm远程调试&环境隔离解决方案 1. 整体架构 在本监控系统中,我们采用了Prometheus作为核心监控解决方案,并结合Node Exporter和Grafana构建了一个完整的监控体…...
谈谈未来iOS越狱或巨魔是否会消失
2024年10月的预测,先说结论: 巨魔iOS17.1消失概率为99%。 因为巨魔强依赖的漏洞就是一个签名漏洞,攻击面有限又经过2轮修复,第3次出现漏洞的概率极低。而越狱的话由于系统组件和服务较多,所以出现漏洞概率高攻击面多&…...
【OpenGL学习】(二)OpenGL渲染简单图形
文章目录 【OpenGL学习】(二)OpenGL渲染简单图形OpenGL渲染图形流程顶点,图元和片元VAO,VBO ,EBO着色器示例:使用OpenGL渲染三角形 【OpenGL学习】(二)OpenGL渲染简单图形 OpenGL渲…...
学习深度学习是否要先学习机器学习?
有小伙伴问我,最近做毕设要做一个神经网络的课题,想请教一下需不需要把机器学习也都学习一遍? 永远正确的回答是:建议先学机器学习,再学深度学习。 上面那句你从哪都挑不出毛病,毕竟机器学习是深度学习的基…...