news 2026/9/10 17:43:18

STM32F407与DS18B20温度报警系统实战:从单总线时序到OLED显示

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32F407与DS18B20温度报警系统实战:从单总线时序到OLED显示

简介:这是一份基于STM32F407的嵌入式温度监测报警工程,使用DS18B20采集环境温度,搭配4针0.96寸OLED显示屏实时刷新数据,并借助RTC时钟模块附加当前日期显示,适合正在学习STM32 GPIO、定时器、I2C/SPI通信及OLED驱动开发的初中级读者。工程实现了温度超出设定范围即触发声光报警的完整逻辑,代码结构清晰,且在STM32F4系列芯片上具备良好的可移植性。压缩包共210个文件,体积约7.05MB,其中包含51个h头文件与49个c源文件,以及Keil工程配置文件(uvprojx/uvoptx)、编译生成的hex/axf/map烧录文件、链接脚本、启动汇编文件等,打开工程即可查看或直接编译烧录验证。目前已有2844人学习下载。资料基于作者多次测试稳定的代码整理而成,可在此基础上方便地扩展上位机通信、数据记录、多路传感器采集等功能,是快速上手STM32F4外设驱动与裸机开发的实用素材。

1. 基于STM32F407的DS18B20温度报警系统先从需求倒推方案

接了个小需求:给冷柜做一个温度监控,开机就能在屏幕上看到当前温度,超限就响铃,屏幕角落再放一行日期。多数人第一反应是买现成的温控模块,但要改阈值、改显示内容就得动厂家固件,反而更费事。用 STM32F407 最小系统板、DS18B20 和一块 4 针 0.96 寸 OLED,整套物料成本最低,程序也能完全自己掌控。这也是 STM32 温度传感器报警系统这类项目最常见的组合:F407 主频高、外设全,DS18B20 测温简单,OLED 显示直观。

这个标题看起来简单,真正动手时三个坎绕不过去:DS18B20 的单总线时序在 HAL 库下怎么写才稳定、OLED 的 I2C 驱动是走硬件外设还是软件模拟、报警逻辑怎么避免在阈值附近反复触发。下面把这三条线拆开讲,最后给一个可以直接上板的 main 框架。手上有 STM32F407 开发板和 0.96 寸 OLED 显示模块的话,跟着步骤走一遍,两小时内能跑出第一版。

2. 用 STM32F407 写 DS18B20 时序:单总线到底怎么拉

DS18B20 的核心是单总线协议,数据线只有一根,既要传数据又要传时序参考。理解它用不着把数据手册背下来,抓住复位、写时隙、读时隙这三组动作就够了。

2.1 单总线协议的核心:复位、读时隙、写时隙

主机和 DS18B20 之间通过拉低总线的时间长短来区分信号。平时总线被上拉电阻拉到 3.3V,器件不动作时是高电平;任何一方要通信,就把总线拉低。每次读取温度前必须做一次复位握手,目的是让 DS18B20 知道主机要开始一轮操作。

2.1.1 复位与存在脉冲:上电后先看器件在不在

复位时序分四步:主机把总线拉低 480us 以上,然后释放;DS18B20 检测到这个下降沿后,等 15 到 60us,主动把总线拉低 60 到 240us;主机在释放总线后的 60us 左右去读电平,读到低说明器件在线,读到高说明总线上没有 DS18B20。

uint8_t DS18B20_Reset(void) { uint8_t pulse; DS18B20_LOW; // 主机拉低总线 delay_us(480); // 至少 480us,常用 500us DS18B20_HIGH; // 释放总线,等待器件响应 delay_us(70); // 60us 到 240us 之间采样 pulse = DS18B20_READ; // 读回 0=存在,1=未检测到 delay_us(410); // 补足整个复位时隙 return pulse; }

引脚宏DS18B20_LOWDS18B20_HIGHDS18B20_READ对应 PA0 的写低、写高和读操作。pulse读取的是 IDR 寄存器,即使引脚配置成开漏输出,只要释放总线后外部上拉生效,读到的电平就是真实的总线状态。这里返回1表示异常;能检测到器件时返回0

2.1.2 写时隙和读时隙的 1us 差

写时隙最小 60us。写 0 是主机拉低总线并保持 60us;写 1 是主机拉低 1 到 15us 后立刻释放,让上拉电阻把总线拉高。读时隙同样由主机发起:拉低 1 到 15us 后释放,然后主机在 15us 内采样电平。DS18B20 会在主机释放后立刻把总线拉低或保持高,所以采样点不能太靠后,超过 15us 容易读到 1。

关键时序参数可以收成一张表,调试时对照着查:

时序主机动作DS18B20 动作时间要求
复位拉低 480us 后释放拉低 60~240us采样点在释放后 60us 附近
写 0拉低并保持等待整个时隙 60~120us
写 1拉低 1~15us 后释放等待采样窗口在 15~60us
读 0/1拉低 1~15us 后释放15us 内拉低或保持高主机在第 15us 采样
温度转换等待内部转换12 位分辨率最大 750ms

2.2 用 HAL 库模拟单总线:GPIO 开漏输出与延时

HAL 库的HAL_GPIO_WritePinHAL_GPIO_ReadPin本身不慢,但HAL_Delay最小单位是 1ms,没法用在 15us 的采样窗口上。常见做法是用 DWT 实现微秒延时,或者用普通 for 循环粗略卡时间。DWT 更准确,而且不占用定时器。

2.2.1 引脚初始化:为什么必须开漏

DS18B20 数据线推荐配成开漏输出。开漏模式下写 1 相当于释放总线,引脚被外部上拉拉高;写 0 才是真正拉低。这样主机和 DS18B20 能同时操作同一条线,不会出现推挽输出时两边打架的情况。

void DS18B20_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 开漏输出,写1=释放 GPIO_InitStruct.Pull = GPIO_PULLUP; // 内部上拉,配合外部4.7k GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); }

GPIO_PULLUP只是兜底,板上最好再加一个 4.7k 上拉到 3.3V。测量时用示波器看 DS18B20 数据脚,如果低电平拖尾明显,通常是上拉偏小或走线太长。

2.2.2 1us 延时:用 DWT 而不是 HAL_Delay

DWT 是 Cortex-M4 内核自带的调试计数器,168MHz 下一个 tick 约 6ns,做微秒延时足够。

static void DWT_Delay_Init(void) { CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; } static void delay_us(uint32_t us) { uint32_t start = DWT->CYCCNT; uint32_t ticks = us * (SystemCoreClock / 1000000U); while ((DWT->CYCCNT - start) < ticks); }

SystemCoreClock默认是 168MHz,计算出的ticks就是延时对应的周期数。注意 DWT 计数器是 32 位的,DWT->CYCCNT - start用无符号减法处理回绕,所以长时间运行也不用担心溢出。

2.3 读温度完整流程与分辨率配置

单根总线上只挂一个 DS18B20 时,流程固定为:复位、跳过 ROM、启动温度转换、等待、再复位、跳过 ROM、读暂存器。

2.3.1 跳过 ROM 读单个 DS18B20 的时序顺序
float DS18B20_ReadTemperature(void) { uint8_t buf[9]; if (DS18B20_Reset()) return -100.0f; // 未检测到器件 DS18B20_WriteByte(0xCC); // 跳过ROM,单点使用 DS18B20_WriteByte(0x44); // 启动温度转换 HAL_Delay(750); // 12位分辨率最长750ms if (DS18B20_Reset()) return -100.0f; DS18B20_WriteByte(0xCC); DS18B20_WriteByte(0xBE); // 读暂存器,从第0字节开始 for (uint8_t i = 0; i < 9; i++) { buf[i] = DS18B20_ReadByte(); // 前2字节是温度,第9字节CRC } int16_t raw = ((int16_t)buf[1] << 8) | buf[0]; return raw * 0.0625f; // 12位分辨率,LSB=0.0625度 }

0xCC跳过 ROM 适用于单点测温,省去匹配 64 位序列号。启动转换命令是0x44,它会让 DS18B20 进入转换状态,转换期间数据线保持低电平;用HAL_Delay(750)是为了避免死等,也简化了超时处理。读暂存器用0xBE,前两个字节分别是温度低字节和高字节,第 9 个字节是 CRC,如果需要更严谨的校验,可以按数据手册的 CRC 多项式算一遍再判断。

2.3.2 12 位分辨率下的转换时间表

DS18B20 默认 12 位分辨率,最小刻度 0.0625 度。也可以把分辨率改低来换速度,写入配置寄存器0x4E后需要把告警高低字节一起补齐。

分辨率转换时间温度精度适用场景
9 位93.75ms0.5 度快速巡检
10 位187.5ms0.25 度一般监控
11 位375ms0.125 度温控要求较高
12 位750ms0.0625 度默认,按这个值写延时

如果发现读温度偶发出现 85 度,那是 DS18B20 上电时的固化值,不是真实温度,程序里可以先读一次丢弃,或者对连续两次数值做合理性判断。

3. 0.96 寸 OLED 显示模块的 HAL 库驱动:从模拟 I2C 到汉字

4 针 0.96 寸 OLED 显示模块用的是 SSD1306 驱动芯片,接口是 I2C。和 DS18B20 的单总线不同,OLED 只需要主机单向写数据,逻辑上简单很多。

3.1 SSD1306 寻址模式与 4 针接线的对应关系

SSD1306 的 128x64 显存分成 8 页,每页 8 个像素高。写数据时有两种常用寻址模式:页寻址和水平寻址。页寻址下写完一列自动加 1,到 127 后回到开头,适合逐行显示;水平寻址适合整屏填充。之后显示的日期、温度都是用页寻址模式来做,代码直观。

4 针 OLED 的引脚定义固定:GND、VCC、SCL、SDA。VCC 接 3.3V,SCL 接 PB6,SDA 接 PB7,正好是 STM32F407 的 I2C1 引脚位置。不过 F407 的硬件 I2C 对时序要求严格,加上 OLED 走线稍长就容易出现偶发死锁,实际项目里很多人直接用模拟 I2C,也就是用两个 GPIO 手写时序。模拟 I2C 的优点是随便换引脚、不用排查外设状态寄存器,调试门槛低不少。

3.2 用 HAL 库模拟 I2C 点亮 OLED 的最小代码

模拟 I2C 时,SCL 用推挽输出,SDA 配成开漏输出。这样 SDA 释放时是被上拉拉高的,主机也能读回从机的 ACK,不需要切换方向。

3.2.1 起始停止与 ACK 处理
static void I2C_Start(void) { OLED_SDA_HIGH; OLED_SCL_HIGH; delay_us(5); OLED_SDA_LOW; // SCL高电平期间SDA拉低,产生起始条件 delay_us(5); OLED_SCL_LOW; } static void I2C_Stop(void) { OLED_SDA_LOW; OLED_SCL_HIGH; delay_us(5); OLED_SDA_HIGH; // SCL高电平期间SDA拉高,产生停止条件 delay_us(5); } static uint8_t I2C_WaitAck(void) { OLED_SDA_HIGH; // 释放SDA,等从机拉低 delay_us(3); OLED_SCL_HIGH; delay_us(3); uint8_t ack = OLED_SDA_READ; // 低电平表示从机已应答 OLED_SCL_LOW; delay_us(3); return ack; } static void I2C_SendByte(uint8_t dat) { for (uint8_t i = 0; i < 8; i++) { OLED_SCL_LOW; if (dat & 0x80) OLED_SDA_HIGH; else OLED_SDA_LOW; delay_us(2); OLED_SCL_HIGH; // SCL上升沿,从机采样 delay_us(2); dat <<= 1; } OLED_SCL_LOW; }

起始条件和停止条件都要求在 SCL 为高时切换 SDA。发送字节时先准备 SDA 数据,再拉高 SCL,让从机在上升沿采样。I2C_WaitAck如果返回非 0,说明 OLED 没有响应,常见原因是地址写错或者 SDA 没接上拉。

3.2.2 初始化命令序列

SSD1306 上电后默认处于关闭显示状态,必须先发初始化命令再点亮。核心命令如下:

命令参数作用
0xAE / 0xAF关闭 / 打开显示
0xD50x80显示时钟分频
0xA80x3F复用比 1/64
0x8D0x14开启电荷泵,必须设
0x200x02页寻址模式
0x810xCF对比度
0xA1 / 0xC8段重映射与扫描方向
0xDA0x12COM 引脚硬件配置
void OLED_Init(void) { delay_us(100); // 上电等待 OLED_WriteCmd(0xAE); // 关闭显示 OLED_WriteCmd(0xD5); OLED_WriteCmd(0x80); OLED_WriteCmd(0xA8); OLED_WriteCmd(0x3F); OLED_WriteCmd(0xD3); OLED_WriteCmd(0x00); OLED_WriteCmd(0x40); // 显示起始行0 OLED_WriteCmd(0x8D); OLED_WriteCmd(0x14); // 电荷泵开 OLED_WriteCmd(0x20); OLED_WriteCmd(0x02); // 页寻址 OLED_WriteCmd(0xA1); OLED_WriteCmd(0xC8); OLED_WriteCmd(0xDA); OLED_WriteCmd(0x12); OLED_WriteCmd(0x81); OLED_WriteCmd(0xCF); OLED_WriteCmd(0xD9); OLED_WriteCmd(0xF1); OLED_WriteCmd(0xDB); OLED_WriteCmd(0x40); OLED_WriteCmd(0xA4); OLED_WriteCmd(0xA6); OLED_WriteCmd(0xAF); // 打开显示 }

这里OLED_WriteCmd发的是控制字节0x00加命令本身;OLED_WriteData发的是控制字节0x40加数据。凡是0xAF之后屏幕还黑着,优先查电荷泵0x8D0x14有没有配上。

3.3 显示温度与日期:8x16 字符和 16x16 中文字模

OLED 本身没有字库,所有字形都要以点阵数据形式写进显存。做报警系统,至少要准备两套字模:ASCII 的 8x16 字符和汉字的 16x16 点阵。

3.3.1 ASCII 字模的打点逻辑
void OLED_ShowChar(uint8_t x, uint8_t page, char ch) { const uint8_t *src = &asc2_1616[(ch - ' ')][0]; OLED_SetCursor(x, page); for (uint8_t i = 0; i < 16; i++) { OLED_WriteData(src[i]); // 每一列一个字节,共16列 } }

asc2_1616是一个 95 行、每行 16 字节的字模表,用取模软件从标准 ASCII 字库生成。OLED_SetCursor内部会发送页地址和列地址。显示一行字符串时,每显示一个字符后x += 8,到 120 左右自动换行。

3.3.2 OLED 显示汉字的取模参数

汉字宽度是 16 像素,一个 16x16 字形占 32 字节。取模软件生成时配置为“逐行式、阴码、列行式”,得到的就是从左上角开始、每行两个字节、共 16 行的数据。显示时上半页写前 16 字节,下半页写后 16 字节。

void OLED_ShowCN16(uint8_t x, uint8_t page, uint8_t index) { OLED_SetCursor(x, page); // 上半页 for (uint8_t i = 0; i < 16; i++) { OLED_WriteData(font16x16[index][i]); } OLED_SetCursor(x, page + 1); // 下半页 for (uint8_t i = 16; i < 32; i++) { OLED_WriteData(font16x16[index][i]); } }

font16x16是按固定顺序排列的汉字点阵数组,比如前 20 个位置分别对应“温度报警系统正常异常”之类的字符。128x64 的屏一页最多放 8 个 16x16 汉字,一行放 4 个比较舒服。OLED 显示汉字的关键是把取模方式和数据排列对齐,排不对就会出现字上下两半错位。

4. 报警阈值、滞回与日期显示的软件实现

温度读出来、日期显示出来后,剩下就是把报警逻辑做对。这个环节最容易出现的是蜂鸣器在阈值附近疯狂抖动。

4.1 阈值判断与滞回:为什么蜂鸣器会临界抖动

如果判断写成“温度大于 30 度就响,小于 30 度就停”,那么温度在 29.9 和 30.1 之间波动时,报警信号会不停翻转,继电器触点很快烧掉。解决手段是滞回:进条件用高阈值,出条件用低阈值,中间留一个缓冲区。

4.1.1 滞回参数设置表

以高温报警为例,合理的一组参数是:

参数说明
高温报警阈值30.0 度超过后进入报警
高温恢复阈值29.0 度低于该值才解除报警
低温报警阈值5.0 度低于后进入报警
低温恢复阈值6.0 度高于该值才解除报警
温差点1.0 度滞回带宽度
4.1.2 区间判断代码
typedef struct { float high_threshold; // 高温报警点 float low_threshold; // 低温报警点 float hysteresis; // 滞回带宽 uint8_t alarm; // 当前报警状态 } Alarm_t; void Alarm_Update(Alarm_t *a, float temp) { if (temp >= a->high_threshold || temp <= a->low_threshold) { a->alarm = 1; // 进入报警区 } else if (temp <= a->high_threshold - a->hysteresis && temp >= a->low_threshold + a->hysteresis) { a->alarm = 0; // 回到安全区才解除 } }

判断逻辑强调区间而不是单点。温度从 29.5 升到 30.2,alarm置 1;之后必须回落到 29.0 以下才清零,中间的 29.3、29.8 都不会触发。低温度报警同理,需要回升到低阈值加滞回带后才能解除。这样写还有个好处:不会出现两条独立判断互相覆盖的 bug。

4.2 报警动作执行与状态回显

报警状态的消费方通常有三个:蜂鸣器、OLED 顶部的状态文字、串口日志。蜂鸣器接到一个 GPIO 上,用推挽输出驱动主动蜂鸣器,高电平响;如果接的是继电器模块,要留意继电器线圈需要三极管或光耦驱动,不能直接挂单片机引脚上。

void Alarm_Execute(Alarm_t *a) { HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, a->alarm ? GPIO_PIN_SET : GPIO_PIN_RESET); if (a->alarm) { OLED_ShowCN16(0, 4, 0); // 显示“报警”两个汉字 OLED_ShowCN16(32, 4, 1); } else { OLED_ShowCN16(0, 4, 2); // 显示“正常” OLED_ShowCN16(32, 4, 3); } }

实际项目里蜂鸣器不宜一直响,常见做法是alarm为真时让蜂鸣器按 1Hz 占空比响。这个可以放到主循环里用HAL_GetTick()做,不影响温度采集的节拍。

4.3 日期显示:软 RTC 的实现与边界

标题里“附带日期显示”有两种实现路径。第一种是 STM32F407 内部 RTC,需要外接 32768Hz 晶振和备份电池;第二种是软件 RTC,用一个结构体保存年月日时分秒,在主循环里每秒加 1。开发板上不一定贴了 RTC 晶振,软 RTC 更稳妥。

4.3.1 闰年与月份天数

日期不能止步于秒数累加,月份天数和闰年必须处理。闰年规则是:能被 4 整除但不能被 100 整除,或者能被 400 整除。

const uint8_t MonthDays[] = {31,28,31,30,31,30,31,31,30,31,30,31}; uint8_t IsLeapYear(uint16_t year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); } void SoftRTC_Tick(SoftRTC_t *rtc) { rtc->second++; if (rtc->second < 60) return; rtc->second = 0; rtc->minute++; if (rtc->minute < 60) return; rtc->minute = 0; rtc->hour++; if (rtc->hour < 24) return; rtc->hour = 0; rtc->day++; uint8_t max_day = MonthDays[rtc->month - 1]; if (rtc->month == 2 && IsLeapYear(rtc->year)) max_day = 29; if (rtc->day <= max_day) return; rtc->day = 1; rtc->month++; if (rtc->month > 12) { rtc->month = 1; rtc->year++; } }

这个函数放在 1ms 或 10ms 的主循环里用标志位触发,每秒调用一次。注意格式化和显示时,year用完整四位年号,OLED 上用%04d-%02d-%02d输出。

4.3.2 校准初始时间

软 RTC 掉电不保持,上电时需要一个初始时间。最简单的方式是在代码里写死一个默认值,再留一个串口命令或两个按键来调整。串口方式更省 IO:

SoftRTC_Init(&rtc, 2025, 1, 7, 12, 0, 0); // 每年发布前改一次

如果要做到掉电后日期不丢,可以把秒数写入 STM32F407 的备份寄存器,需要时再读回来;备份域由 VBAT 供电,主电源掉了也能维持。这是软 RTC 和内部 RTC 之间的折中方案。

5. 串起来之后:main 函数轮询框架与三点现场调试技巧

把 DS18B20 读取、OLED 刷新、报警判断、日期累加放进同一个 main,最难的是节奏控制,因为 DS18B20 每次转换要 750ms,OLED 刷新又不能用阻塞延时拖住温度采集。

5.1 2 秒刷新节奏的 main 逻辑

int main(void) { HAL_Init(); SystemClock_Config(); // 168MHz DWT_Delay_Init(); DS18B20_GPIO_Init(); OLED_Init(); OLED_Clear(); SoftRTC_t rtc = {2025, 1, 7, 12, 0, 0}; Alarm_t alarm = {30.0f, 5.0f, 1.0f, 0}; uint32_t next_read = HAL_GetTick(); uint32_t next_rtc = HAL_GetTick(); while (1) { if (HAL_GetTick() >= next_read) { float temp = DS18B20_ReadTemperature(); // 内部阻塞750ms if (temp > -55.0f && temp < 125.0f) { Alarm_Update(&alarm, temp); Alarm_Execute(&alarm); OLED_ShowTemperature(temp); } else { OLED_ShowString(0, 4, "Sensor Err"); } next_read += 2000; // 固定2秒周期 } if (HAL_GetTick() >= next_rtc) { SoftRTC_Tick(&rtc); OLED_ShowDate(&rtc); next_rtc += 1000; } } }

时间轴很清晰:温度读取周期是 2 秒,因为读函数内部已经等了 750ms,按 2 秒一轮感官上很舒服。日期每秒刷一次,温度刷新和日期刷新互不阻塞。OLED 刷新时先把内容画到内存缓存,再整体刷一次显存,可以避免屏上出现半行残影。

5.2 三个调试技巧:从时序到阈值验证

第一招,DS18B20 读不到数据时别急着改代码,用逻辑分析仪抓数据脚。复位后能不能看到一个明显的存在脉冲,写时序里每个时隙是否保持 60us,一眼就能定位是连接问题还是延时问题。没有逻辑分析仪时,可以先用 GPIO 翻转法:把 DS18B20 的上拉脚接到一个空闲引脚,然后点灯看状态。

第二招,OLED 不亮时不要只查接线。先看 SDA 地址对不对,SSD1306 的 I2C 地址是 0x3C,左移一位后是 0x78;再确认发送控制字节时用的到底是 0x00 还是 0x40,命令和数据混了屏幕会花。把初始化命令逐条发进串口打印,配合示波器看 SCL 上有没有波形,很快能判断是初始化序列问题还是时序太慢。

第三招,验证报警逻辑用“反向调阈值”。运行状态下把high_threshold调成当前温度减 1 度,蜂鸣器应该立刻响;再把阈值调回当前温度加 2 度,确认报警解除。接着测试滞回:让温度缓慢穿过阈值,看报警翻转是否干脆。这个测试应该放在温度稳定时做,不要在空调出风口旁边测,否则会被气流干扰。

5.3 把 OLED 刷新率压下去的功耗技巧

系统稳定之后,OLED 的刷新率是可以优化的。温度显示小数点后一位,每秒刷两次就够了;日期只在变化时刷新,秒钟显示可以只更新最后两位,不要每次都整屏重写。把 OLED 刷新的目标区域缩小到变化行,发送的数据量会少一半以上。

如果整机要省电,还可以在不需要显示时让 OLED 进入休眠模式,发送0xAE关掉显示,再送0x8D0x10关闭电荷泵,需要看时再按初始化序列恢复。加上 DS18B20 的读取周期从 2 秒拉长到 30 秒,整机静态工作电流能从十几毫安降到个位数毫安,这在电池供电的温度记录场景里足够撑一个晚上。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 17:42:34

JMeter性能测试入门:从安装到实战全指南

1. JMeter入门&#xff1a;从零开始掌握性能测试利器第一次接触JMeter时&#xff0c;我被它强大的功能和略显复杂的界面弄得晕头转向。作为Apache基金会旗下的开源性能测试工具&#xff0c;JMeter确实能帮我们解决很多实际问题——比如模拟高并发用户访问、测量系统响应时间、分…

作者头像 李华
网站建设 2026/9/10 17:40:05

JAVA毕业设计-基于 SpringBoot+Vue 的高校课程质量评价系统设计与实现 基于 SpringBoot 的课程评价管理系统(源码+LW+部署文档+全bao+远程调试+代码讲解等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/9/10 17:37:10

PyTorch CUDA版本不匹配报错全解析:从原理到修复实战

跑深度学习的人&#xff0c;十有八九都撞见过这条报错&#xff1a;RuntimeError: The detected CUDA version (12.2) mismatches the version that was used to compile the PyTorch binary (12.1).第一次看到这个提示的时候&#xff0c;我愣了好一会儿。明明是同一台机器&…

作者头像 李华
网站建设 2026/9/10 17:34:06

rnnoise 静态库集成实战:从 C 到 Python 的实时语音降噪方案

简介&#xff1a;编译好的 rnnoise 音频降噪库&#xff0c;面向需要为语音通话、语音识别、在线会议或直播等场景加入背景噪声消除能力的开发者。基于 RNN 的降噪模型经过预训练&#xff0c;解压后即可通过 API 集成到工程&#xff0c;省去自行编译源代码的流程。压缩包为 7z 格…

作者头像 李华
网站建设 2026/9/10 17:31:55

ITIL 4落地实践选择三步法:从34个实践到精准落地

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华