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…...
Sparse4D运行笔记
Sparse4D有三个版本,其中V1和V2版本的官方文档中环境依赖写得比较模糊且依赖库有版本冲突。 1. Sparse4D V1 创建环境 conda create sparse4dv1 python3.8 激活环境 conda activate sparse4dv1 安装torch, torchvision, torchaudio pip install torch1.13.0c…...
Redis设计与实现——分布式Redis
Redis Sentinel(哨兵) Sentinel 的工作机制 故障检测(Failure Detection) 主观下线(Subjective Down):单个 Sentinel 实例检测到主节点在30 秒内无响应,标记其为 SDOWN。 客观下线…...
多指标组合策略
该策略(MultiConditionStrategy)是一种基于多种技术指标和市场条件的交易策略。它通过综合考虑多个条件来生成交易信号,从而决定买入或卖出的时机。 以下是对该策略的详细分析: 交易逻辑思路 1. 条件1:星期几和价格变化判断 - 该条件根据当前日期是星期几以及价格的变化…...

c#车检车构客户管理系统软件车辆年审短信提醒软件
# CMS_VehicleInspection 车检车构客户管理系统软件车辆年审短信提醒软件 # 开发背景 软件是给泸州某公司开发的车检车构客户管理系统软件。用于在车检年审到期前一个月给客户发送车检短信提醒 # 功能描述 主要功能:车辆年审前一个月给客户发年审短信提醒…...
Java爬虫能处理京东商品数据吗?
Java爬虫完全可以处理京东商品数据。通过Java爬虫技术,可以高效地获取京东商品的详细信息,包括商品名称、价格、图片、描述等。这些信息对于市场分析、选品上架、库存管理和价格策略制定等方面具有重要价值。以下是一个完整的Java爬虫示例,展…...

通俗版解释CPU、核心、进程、线程、协程的定义及关系
通俗版解释(比喻法) 1. CPU 和核心 CPU 一个工厂(负责干活的总部)。核心 工厂里的车间(比如工厂有4个车间,就能同时处理4个任务)。 2. 进程 进程 一家独立运营的公司(比如一家…...

大语言模型 11 - 从0开始训练GPT 0.25B参数量 MiniMind2 准备数据与训练模型 DPO直接偏好优化
写在前面 GPT(Generative Pre-trained Transformer)是目前最广泛应用的大语言模型架构之一,其强大的自然语言理解与生成能力背后,是一个庞大而精细的训练流程。本文将从宏观到微观,系统讲解GPT的训练过程,…...

USRP 射频信号 采集 回放 系统
USRP 射频信号采集回放系统 也可以叫做: 利用宽带RF录制和回放系统实现6G技术研究超宽带射频信号采集回放系统使用NI USRP平台实现射频信号录制和回放操作演示USRP也能实现多通道宽带信号流盘回放了! 对于最简单的实现方法就是使用LabVIEW进行实现 采…...

【skywalking】index“:“skywalking_metrics-all“},“status“:404}
skywalking 启动报错 java.lang.RuntimeException: {"error":{"root_cause":[{"type":"index_not_found_exception","reason":"no such index [skywalking_metrics-all]","resource.t ype":"inde…...
handsome主题美化及优化:10.1.0最新版 - 1
文章目录 前言右侧导航栏主题标题居中页面两侧框架留白间距handsome 原生入站提示评论一键赞、踩、打卡时光机头像圆形logo 扫光赞赏按钮跳动鼠标点击特效复制版权提示彩色标签云及右栏数字自定义右键响应时间和访客总数全站字数统计版权提示时间流逝添加心知天气总结 前言 ha…...
(9)python开发经验
文章目录 1 os.path.join()拼接路径2 条件变量3 添加临时环境变量 更多精彩内容👉内容导航 👈👉Qt开发 👈👉python开发 👈 1 os.path.join()拼接路径 os.path.join() 是 Python 中处理文件路径拼接的核心函…...

【C++详解】string各种接口如何使用保姆级攻略
文章目录 一、string介绍二、string使用构造函数析构函数赋值运算符重载string的遍历修改方法1、下标[]2、迭代器3、范围for 迭代器使用详解const迭代器反向迭代器(reverse) Capacity(容量相关)size/lengthmax_sizecapacityclear/emptyshrink_to_fit(缩容)reserve(扩…...

2025深圳杯D题法医物证多人身份鉴定问题四万字思路
Word版论文思路和千行Python代码下载:https://www.jdmm.cc/file/2712074/ 引言 法医遗传学中的混合生物样本分析,特别是短串联重复序列(Short Tandem Repeat, STR)分型结果的解读,是现代刑事侦查和身份鉴定领域的核心…...

【时时三省】(C语言基础)字符数组应用举例2
山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 例题: 有3个字符串,要求找出其中“最大”者。 解题思路: 可以设一个二维的字符数组str,大小为320,即有3行20列(每一…...

Mysql触发器(附案例)
文章目录 触发器简介1、insert类型2、update类型3、delete类型总结 触发器简介 触发器是与表有关的数据库对象,指定在 insert/update/delete 之前或之后,触发并执行触发器中定义的SQL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性…...

使用DDR4控制器实现多通道数据读写(十二)
一、章节概括 这一节使用interconnect RTL ip核将DDR4与四个读写通道级联,在测试工程中,将四个通道同时写入/读出地址与数据,并使用modelsim仿真器仿真,四个通道同时发送写请求或读请求后,经过interconnect后ÿ…...

Kafka 生产者工作流程详解
以下是 Kafka 生产者工作流程的清晰分步解释,结合关键机制与用户数据: 1. 生产者初始化与数据发送 主线程创建生产者对象,调用 send(ProducerRecord) 发送消息。 拦截器(可选):可添加自定义逻辑(…...

完整卸载 Fabric Manager 的方法
目录 ✅ 完整卸载 Fabric Manager 的方法 1️⃣ 停止并禁用服务 2️⃣ 卸载 Fabric Manager 软件包 3️⃣ 自动清理无用依赖(可选) 4️⃣ 检查是否卸载成功 ✅ 补充(仅清除服务,不删包) ✅ 完整卸载 Fabric Mana…...

地下停车场调频广播无线覆盖系统:融合精准选频光纤传输均匀覆盖于一体的创新型地下车库广播无线覆盖平台
地下停车场调频广播无线覆盖系统:融合精准选频光纤传输均匀覆盖于一体的创新型地下车库广播无线覆盖平台 北京海特伟业科技有限公司任洪卓发布于2025年5月16日 在现代城市建设中,地下停车场已成为商业综合体、写字楼、住宅区及交通枢纽的标配设施。然而…...

【Linux】进程间通信(一):认识管道
📝前言: 这篇文章我们来讲讲进程间通信——认识管道 🎬个人简介:努力学习ing 📋个人专栏:Linux 🎀CSDN主页 愚润求学 🌄其他专栏:C学习笔记,C语言入门基础&a…...

中大型水闸安全监测系统解决方案
一、方案概述 中大型水闸作为水利工程的重要组成部分,承担着调节水位、控制水流、防洪排涝等多重功能,在防洪减灾、水资源配置、生态环境改善等方面发挥着巨大作用。然而,由于历史原因,许多水闸存在建设标准偏低、质量较差、配套设…...

蓝桥杯12届国B 123
题目描述 小蓝发现了一个有趣的数列,这个数列的前几项如下: 1,1,2,1,2,3,1,2,3,4,⋯ 小蓝发现,这个数列前 1 项是整数 1,接下来 2 项是整数 1 至 2,接下来 3 项是整数 1 至 3,接下来 4 项是整数 1 至 4&…...

Harmony开发 List、Grid拖动自定义排序实现
1. Harmony开发 List、Grid拖动自定义排序实现 1.1. List拖动功能 本示例基于显式动画、List组件实现了ListItem的上下拖动、ListItem切换以及ListItem插入的效果。 实现思路:List手势拖动 @Entry @Component struct ListDragPage {@State private arr: string[] = [0, …...

迅龙3号基于兆讯MH22D3适配CST328多点触摸驱动开发笔记
MH22D3芯片是兆讯公司新推出的基于cortex-M3内核的新一代芯片,专注于显示应用,其主频高达216Mhz,64KB SRAM,512KB Flash,开发UI应用游刃有余。详细介绍请看:MH22D3新一代显控应用性价比之王 新龙微基于MH22…...
【001】.so文件分析之 ELF格式符号
.so 文件的结构标识主要依据 ELF 格式(Executable and Linkable Format) 一个 .so 文件其实是一个 ELF(可执行与可链接格式) 文件,里面包含多个结构标识符和段(Sections)用于支持动态加载、符号…...

QT之LayOut布局
文章目录 QFormLayoutQGridLayoutQFormLayout、QGridLayout、QHBoxLayout、QVBoxLayout综合案例用QFormLayout 代替 界面左边部分的QGridLayout QFormLayout #include "widget.h"#include <QFormLayout> #include <QLineEdit>Widget::Widget(QWidget *p…...

无需配置光猫,使用网管交换机配合路由器的IPTV功能实现单线复用
一、背景 弱电箱和电视柜只预留了一根网线,路由器放在电视柜,想实现既可以上网又可以正常观看iptv,本文提供了一种方法。 二、准备工作 1、带iptv功能的路由器;2、水星sg105pro网管交换机;3、网线若干; …...
C++类与对象--1 特性一:封装
C面向对象三大特性: (1)封装;(2)继承;(3)多态; C认为万物皆是对象,对象上有对应的属性(数据)和行为(方法&…...

Linux:计算机的层状结构
1.冯诺依曼体系结构 我们常见的计算机,如笔记本、台式机。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系结构。 CPU:运算器和控制器组成。运算器主要工作是做算术运算和逻辑运算。控制器主要工作是协调设备之间信息流动的…...