news 2026/9/1 1:41:59

STM32输入捕获测频实战:定时器原理与CubeMX配置

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32输入捕获测频实战:定时器原理与CubeMX配置

之前在调试一块基于 STM32 的采集板时,遇到一个很实际的需求:传感器输出的是一路脉冲信号,频率从几十 Hz 到几十 kHz 变化,单片机需要实时测量出频率并上报。最开始想用外部计数器方案,后来发现直接利用定时器的输入捕获功能就能解决,而且精度完全够用。本文基于 STM32C5A3R,从输入捕获的原理讲起,完整演示如何通过 STM32CubeMX 配置定时器输入捕获,并使用 HAL 库完成频率测量。如果你是刚接触定时器捕获功能的新手,或者想把“测频”这个功能快速落地到项目中,这篇文章应该能帮你少走不少弯路。

1. 背景与核心概念

1.1 为什么需要测量频率

频率测量是嵌入式开发里非常常见的需求。比如无刷电机调速时需要读取霍尔传感器的频率来计算转速,流量计输出脉冲信号时需要通过脉冲频率换算流量,红外避障模块、超声波模块、PPM 遥控接收机等很多传感器也都是以脉冲频率作为输出形式。

对于这类场景,单片机的定时器输入捕获是最直接、成本最低的解决方案。不需要额外增加专用测频芯片,只需要一个定时器通道和一个 GPIO 引脚,就能实现从几 Hz 到几百 kHz 甚至更高范围的频率测量。

1.2 输入捕获的工作原理

输入捕获(Input Capture)是定时器的一种工作模式。它的核心能力是:当外部信号出现指定的跳变沿(上升沿或下降沿)时,定时器硬件会立刻把当前计数器的值锁存到捕获/比较寄存器 CCRx 中,同时可以触发捕获中断。整个过程由硬件自动完成,CPU 不需要参与捕获动作。

这一点非常关键:输入捕获是硬件保存计数值,不是 CPU 在中断里去读。所以即使 CPU 正在处理其他中断,或者主循环很忙,只要捕获中断的响应没有慢到丢失下一次捕获,测量值本身依然是准确的。这保证了频率测量的时间精度很高。

1.3 频率测量常用方法对比

在嵌入式系统中,测量频率主要有三种思路:

测量方法基本原理适合频率范围精度特点典型实现
测频法(M 法)在固定闸门时间内记录脉冲个数,f = N / T高频信号频率越高精度越好,低频时误差大外部计数模式或定时器门控
测周法(T 法)测量一个信号周期对应的定时器计数次数,f = F_cnt / N中低频信号频率越低精度越好,高频时计数太少误差大输入捕获上升沿
等精度测量同时测量频率和周期,并用同步闸门处理宽频率范围综合最优但实现复杂两个计数器配合

本文重点讲解测周法,也就是通过定时器输入捕获来实现。这种方式实现简单,代码量小,适合绝大多数传感器信号测量场景。

2. 环境准备与开发工具

2.1 硬件环境

  • STM32C5A3R 开发板一块。
  • 信号源:可以使用另一块单片机开发板输出 PWM,也可以使用信号发生器。
  • USB 转串口模块:用于把测量结果打印到电脑上观察。
  • 杜邦线若干。

STM32C5 系列是 ST 新一代基于 Cortex-M33 内核的 MCU 系列,在定时器资源和 HAL 库接口上保持了良好的通用性。具体的引脚分配和定时器资源,建议以你手中的芯片数据手册和 CubeMX 生成的代码为准。

2.2 软件环境

  • STM32CubeMX:用于图形化配置芯片引脚、时钟、定时器和中断。
  • STM32CubeIDE 或其他支持 HAL 库的 IDE。
  • 串口调试助手。

版本说明:STM32CubeMX 的版本以及 HAL 库版本不同,界面细节可能略有差异,但配置思路和 HAL 库 API 基本一致。本文以常见配置环境为例,重点演示配置思路。

2.3 测量方案概览

本文的测量方案是:

  1. 使用 TIM1 的通道 1 作为输入捕获通道。
  2. 外部脉冲信号接到对应的捕获引脚。
  3. 定时器以固定计数频率运行,每次捕获到上升沿时,硬件自动保存当前计数值。
  4. 在捕获中断中读取捕获值,计算相邻两次上升沿之间的计数差值。
  5. 用定时器计数频率除以计数差值,得到信号频率。

3. 输入捕获测量频率的核心原理

3.1 测周法频率计算的完整过程

先来看一个最简单的例子。

假设定时器的计数时钟是 1MHz,也就是每个计数周期为 1us。如果外部信号是 1kHz 的方波,周期就是 1ms,那么定时器在相邻两个上升沿之间会计数 1000 次。

第一次捕获上升沿时的计数值是 X,第二次捕获上升沿时的计数值是 Y,则:

周期计数值 D = Y - X 信号周期 T = D / F_cnt 信号频率 f = F_cnt / D

带入数字就是:

f = 1,000,000 / 1000 = 1000 Hz

这就是输入捕获测频的核心算式。

3.2 计数器溢出问题

上面的例子信号频率比较高,两次捕获之间计数器没有发生溢出,计算很简单。但如果信号频率很低,比如要测量 1Hz 的信号,一个周期是 1 秒,在 1MHz 计数时钟下,需要计数 1,000,000 次。

而 STM32 的通用定时器大部分是 16 位计数器,最大计数值是 65535。也就是说,计数器从 0 计到 65535 之后会溢出回 0,重新开始计数。一个 1Hz 的信号周期内,计数器会溢出 15 次左右。

如果只读捕获值,不处理溢出,计算结果就会完全错误。所以测低频信号时必须配合定时器的更新中断(Update Interrupt),每溢出一次就让一个溢出计数变量加一。

这样两次捕获之间的总计数增量就是:

总计数增量 = (当前捕获值 - 上次捕获值) + 溢出次数 × (ARR + 1)

然后在捕获中断中,读取并清零溢出计数,避免溢出计数累积到下一次周期。

3.3 测量范围与精度分析

测量范围和精度主要由定时器计数时钟频率、定时器位宽和信号频率共同决定。以计数时钟 1MHz、16 位定时器 ARR=65535 为例:

信号频率每周期计数次数是否溢出理论精度
100 Hz10000±0.01% 量级
1 kHz1000±0.1% 量级
100 kHz10误差较大
1 Hz1000000是(约 15 次)仍然可测

高频信号的问题是:每个周期内的计数次数太少,输入捕获的 ±1 个计数误差占比重变大。比如 100kHz 信号,每个周期只有 10 个计数,如果误差 1 个计数,频率误差就是 10%。

低频信号的问题可以通过溢出计数解决,计数总量很大,所以相对精度很高。如果需要测量很高的频率,建议改用测频法(M 法),即用外部信号本身作为计数时钟,在固定时间内统计脉冲个数。

4. STM32CubeMX 配置定时器输入捕获

4.1 新建工程与时钟配置

打开 STM32CubeMX,选择 STM32C5A3R 芯片,新建工程。

进入 Clock Configuration 页面,根据开发板实际情况配置时钟源和系统主频。这里需要注意一个重点:定时器挂在 APB 总线上,定时器时钟频率不一定等于系统主频。在 CubeMX 的时钟树页面中,可以直接看到 APB1 Timer Clocks 和 APB2 Timer Clocks 的频率数值。

以本文示例为例,假设 APB2 定时器时钟为 100MHz,后续配置参数都基于这个数值。如果你的实际配置不同,需要同步调整预分频参数。

4.2 TIM1 输入捕获参数配置

在 Pinout & Configuration 页面,找到 Timers,选择 TIM1:

  • Clock Source 选择 Internal Clock。
  • Channel1 选择 Input Capture direct mode。
  • 配置参数如下:
    • Prescaler(预分频):设置为 99。
    • Counter Mode:选择 Up 向上计数模式。
    • Counter Period(自动重装载值 ARR):设置为 65535。
    • Auto-reload preload:Enable。
    • Input Capture Channel 参数:
      • Polarity:Rising Edge(上升沿捕获)
      • IC Selection:Direct TI
      • Prescaler:1(不分频)
      • Filter:0(不滤波)

这里解释一下:Prescaler 设置为 99,实际分频系数是 PSC+1,等于 100。如果定时器输入时钟是 100MHz,那么计数时钟就是 100MHz / 100 = 1MHz,每个计数周期为 1us。这个数值方便计算频率,但这只是示例,实际工程中要根据被测信号的频率范围调整。

Counter Period 设置为 65535 是因为 TIM1 是 16 位定时器,最大自动重装载值就是 65535。

4.3 NVIC 中断配置

在 NVIC Settings 页面中,需要使能两个中断:

  • TIM1 capture compare interrupt:用于捕获中断,读取捕获值。
  • TIM1 update interrupt:用于计数器溢出中断,统计溢出次数。

分别勾选 Enabled,并可以设置优先级。通常捕获中断优先级应高于更新中断,这样在捕获发生时能优先处理捕获值,避免丢失边沿信息。

4.4 生成工程代码

配置完成后,点击 Generate Code,选择目标 IDE 工具链,生成初始化工程。CubeMX 会自动生成 GPIO 复用配置、时钟初始化、定时器初始化和中断服务函数的框架代码。

到这里,CubeMX 的配置工作就完成了。接下来要做的,就是在生成的 HAL 库工程中编写业务代码,实现频率计算逻辑。

5. HAL 库输入捕获代码实现

5.1 频率测量数据结构设计

为了方便管理测量状态,建议定义一个结构体来保存频率测量的中间变量:

/* 文件路径:Core/Inc/freq_measure.h */ #ifndef FREQ_MEASURE_H #define FREQ_MEASURE_H #include "main.h" typedef struct { volatile uint32_t overflow_cnt; /* 定时器溢出次数 */ volatile uint32_t last_ccr; /* 上一次捕获值 */ volatile uint32_t period_counts; /* 一个信号周期对应的计数次数 */ volatile uint32_t freq_hz; /* 测量得到的频率(Hz) */ volatile uint8_t first_capture; /* 是否第一次捕获标志 */ } freq_measure_t; extern freq_measure_t g_freq; #endif

在 main.c 中定义这个全局变量:

/* 文件路径:Core/Src/main.c */ freq_measure_t g_freq;

5.2 启动输入捕获与更新中断

在 main 函数中,完成定时器初始化之后,启动输入捕获:

int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM1_Init(); /* 启动 TIM1 输入捕获,并使能捕获中断 */ HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1); /* 额外使能更新中断,用于统计计数器溢出次数 */ __HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE); while (1) { /* 主循环中读取频率值即可 */ if (g_freq.freq_hz > 0) { printf("Freq = %lu Hz\r\n", (unsigned long)g_freq.freq_hz); } HAL_Delay(500); } }

注意:HAL_TIM_IC_Start_IT只会使能捕获比较中断,更新中断需要单独使能。

5.3 捕获中断回调实现

在 HAL 库中,定时器捕获中断最终会回调到HAL_TIM_IC_CaptureCallback函数。我们需要在这个函数中实现频率计算的逻辑:

/* 文件路径:Core/Src/stm32c5xx_it.c 或用户回调文件 */ void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM1) { uint32_t current_ccr = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); uint32_t overflow_cnt = 0; /* 在读取溢出计数前关闭更新中断,防止读取过程中溢出计数被修改 */ __HAL_TIM_DISABLE_IT(htim, TIM_IT_UPDATE); overflow_cnt = g_freq.overflow_cnt; g_freq.overflow_cnt = 0; __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE); if (g_freq.first_capture == 0) { /* 第一次捕获,只记录基准值 */ g_freq.first_capture = 1; } else { /* 两次捕获之间的总计数增量 */ g_freq.period_counts = (current_ccr - g_freq.last_ccr) + overflow_cnt * (htim->Init.Period + 1); /* 频率 = 定时器计数时钟 / 周期计数值 */ /* 注意:这里的 1000000 要和 CubeMX 中配置的计数时钟保持一致 */ if (g_freq.period_counts > 0) { g_freq.freq_hz = 1000000UL / g_freq.period_counts; } } /* 记录本次捕获值,作为下一次计算的基准 */ g_freq.last_ccr = current_ccr; } }

这里有一个关键点需要解释:current_ccr - g_freq.last_ccr使用的是无符号整数减法。即使两次捕获之间计数器发生过回绕,也就是当前捕获值小于上次捕获值,无符号减法的结果依然能正确表示两者之间的差值。因为计数器的回绕本质上是模运算,而无符号减法和模运算的规则是一致的。

5.4 更新中断回调实现

定时器的更新中断最终会回调到HAL_TIM_PeriodElapsedCallback。在这个函数中只需要做一件事:让溢出计数器加一。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM1) { g_freq.overflow_cnt++; } }

这段代码体现了测周法的核心思想:利用硬件中断,把 16 位定时器的计数能力扩展到任意长度。即使信号频率低到 0.1Hz,只要溢出计数变量足够大,依然可以准确测量。

5.5 完整代码整理

为了方便理解整个逻辑,把核心代码整理到一起。注意,这只是一个汇总展示,实际项目中这些代码分布在不同的源文件中:

/* ========== CubeMX 生成的定时器初始化 ========== */ void MX_TIM1_Init(void) { TIM_IC_InitTypeDef sConfigIC = {0}; htim1.Instance = TIM1; htim1.Init.Prescaler = 99; /* 100MHz / 100 = 1MHz 计数时钟 */ htim1.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.Period = 65535; htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim1.Init.RepetitionCounter = 0; htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; HAL_TIM_IC_Init(&htim1); sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; sConfigIC.ICFilter = 0; HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1); } /* ========== 频率计算回调 ========== */ void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM1) { uint32_t current_ccr = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); uint32_t overflow_cnt = 0; __HAL_TIM_DISABLE_IT(htim, TIM_IT_UPDATE); overflow_cnt = g_freq.overflow_cnt; g_freq.overflow_cnt = 0; __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE); if (g_freq.first_capture) { g_freq.first_capture = 0; } else { g_freq.period_counts = (current_ccr - g_freq.last_ccr) + overflow_cnt * (htim->Init.Period + 1); if (g_freq.period_counts > 0) { g_freq.freq_hz = 1000000UL / g_freq.period_counts; } } g_freq.last_ccr = current_ccr; } } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM1) { g_freq.overflow_cnt++; } }

6. 运行验证与误差分析

6.1 输入信号连接

将信号源的输出引脚连接到 TIM1 的捕获输入引脚。具体引脚号需要查看你使用的 STM32C5A3R 芯片的引脚功能表,或者在 CubeMX 中直接观察 TIM1_CH1 被分配到哪个引脚。

需要注意的是,被测信号的电压范围必须在芯片 GPIO 的允许输入电压范围内。如果信号来自 5V 传感器,需要做电平转换或串联限流电阻,不能直接接到 MCU 引脚。

6.2 验证结果与计算过程

假设信号源输出 1kHz 方波,计数时钟为 1MHz,即每个计数周期为 1us。

理想情况下,相邻两次上升沿之间的计数差值应该是 1000,那么:

f = 1,000,000 / 1000 = 1000 Hz

但实际输出可能会看到 999Hz 或 1001Hz,这是因为信号源本身存在频率误差,再加上 ±1 个计数周期的量化误差,在 1000Hz 信号上表现为千分之一的偏差,这是完全正常的。

再看一个低频例子。假设信号源输出 10Hz 方波,一个周期为 100ms,在 1MHz 计数时钟下对应 100,000 个计数。TIM1 是 16 位定时器,ARR=65535,所以一个周期内计数器会溢出一次。捕获中断中的计算过程为:

溢出次数 = 1 计数差值 = (当前捕获值 - 上次捕获值) + 1 × 65536

最终计算出的周期计数值约为 100,000,频率约为 10Hz。这说明溢出处理逻辑在低频场景下是必要的。

6.3 误差来源分析

输入捕获测频的误差主要来自三个方面。

第一个是量化误差。定时器计数器每个计数周期加一,捕获时刻不可能刚好落在整数计数边界上,所以存在 ±1 个计数周期的固有误差。信号频率越高,每个周期的计数次数越少,这个误差占比越大。

第二个是时钟源误差。定时器计数时钟来自 HSE 或 HSI,如果晶振本身存在频率偏差,例如 20ppm 的晶振,那么测量结果也会有同等量级的相对误差。

第三个是信号边沿抖动。如果输入信号本身存在抖动或噪声,捕获到的上升沿位置会有微小波动,导致测量结果不稳定。

针对这些误差,实际工程中通常采用多次测量取平均、软件滤波、使用更高精度的计数时钟等手段来优化。

7. 常见问题与排查思路

7.1 捕获不到信号

如果程序运行后,频率值始终为 0,说明捕获中断没有触发。优先检查以下几项:

问题现象常见原因解决思路
始终读不到频率捕获引脚接错对照 CubeMX 的引脚分配,确认信号接到正确引脚
始终读不到频率信号电平不在 GPIO 输入范围用示波器或万用表测量引脚电压
始终读不到频率中断未使能检查 NVIC 配置和HAL_TIM_IC_Start_IT是否调用
始终读不到频率通道配置错误确认使用的是 TIM1_CH1,而不是其他通道

7.2 频率值跳变不稳定

频率值忽高忽低,通常是输入信号边沿抖动造成的。可以在 CubeMX 的 Input Capture Filter 参数中配置数字滤波,这个参数本质上是一个数字信号滤波器的采样次数,能够滤除高频毛刺。

另外,如果信号上升沿比较缓慢,也可能导致捕获时刻不稳定。建议在输入引脚上并联一个 100nF 的小电容,或者使用施密特触发器对信号进行整形。

7.3 溢出计数不更新

低频信号测量结果仍然偏大或偏小,很可能是因为更新中断没有正确工作。

检查一下是否在启动代码中调用了__HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE)。如果只启动了捕获中断而没有使能更新中断,HAL_TIM_PeriodElapsedCallback就不会被调用,溢出计数始终为 0。

另外要注意,HAL_TIM_PeriodElapsedCallback是一个通用回调函数,项目中可能被多个定时器共用,必须在函数内部通过htim->Instance判断是哪个定时器产生的更新事件。

7.4 高频信号丢失

如果被测信号频率很高,比如几百 kHz,捕获中断触发频率就会很高。如果中断处理函数执行时间过长,或者还有其他高优先级中断频繁抢占,就可能导致捕获覆盖。

解决思路是:

  • 缩短捕获中断回调中的处理逻辑,不要在回调中做串口打印、复杂计算等耗时操作。
  • 提高捕获中断的优先级。
  • 如果需要测量非常高频率的信号,改为使用 M 法(外部计数方式)更合适。

8. 最佳实践与工程建议

8.1 输入信号处理

输入到 MCU 捕获引脚的信号必须保证电平兼容和边沿干净。对于传感器输出的脉冲信号,建议在硬件上做一级 RC 滤波,时间常数根据信号频率选择,避免高频噪声干扰触发边沿检测。

如果信号是集电极开路输出,外部必须接上拉电阻。如果信号是差分输出,则需要使用转换芯片转换为单端信号。不要直接在引脚上输入超出芯片供电电压的信号。

8.2 定时器参数选择策略

预分频值 PSC 和自动重装载值 ARR 的选择原则是:让被测信号在一个周期内的计数值尽量大,同时避免计数器溢出过于频繁。

举个例子,如果被测信号范围是 1Hz 到 10kHz:

  • 计数时钟可以选择 1MHz,这样 10kHz 信号每周期有 100 个计数,1Hz 信号有 1,000,000 个计数。
  • 16 位定时器 ARR 设置为 65535,低频时配合溢出计数处理。

如果被测信号范围是 100Hz 到 100kHz:

  • 可以适当提高计数时钟到 10MHz,让高频段的计数分辨率更高。
  • 但要注意,计数时钟越高,低频时溢出越频繁,溢出计数丢失的风险越大。

如果被测信号频率上限很高,超过定时器中断处理能力,就应该改用测频法,而不是继续调大计数时钟。

8.3 消除测量抖动

在实际项目中,直接输出每次捕获计算得到的频率值,显示往往会在一定范围内跳动。可以通过两个方式改善。

一个是在主循环中做滑动平均,取最近 N 次测量结果的均值作为最终输出,能明显平滑波动。

另一个是使用多周期测量法,也就是不是每次捕获上升沿都计算一次频率,而是每累计 N 个上升沿之后,才计算一次总时间的平均值。这样等效于延长了测量闸门,能抑制单周期的量化误差。

8.4 扩展:PWM 输入模式与 DMA 方式

STM32 的定时器除了单通道输入捕获之外,还支持 PWM 输入模式。开启 PWM 输入模式后,定时器可以同时测量输入信号的周期和占空比,并且只需要占用两个捕获通道。这对于需要同时检测频率和占空比的场景非常实用,比如遥控器信号解码、电机 PWM 反馈检测等。

另外,如果系统中已经有 DMA 控制器空闲,可以考虑使用 DMA 方式搬运捕获值到内存数组中,再周期性计算频率。这种方式可以大大降低中断频率,适合高频信号测量。

9. 总结与下一步学习方向

本文从输入捕获的基本原理出发,详细演示了在 STM32C5A3R 上通过定时器输入捕获测量信号频率的完整流程。包括 CubeMX 图形化配置、HAL 库代码实现、溢出处理逻辑、频率计算公式,以及常见问题排查思路。

掌握输入捕获之后,你可以继续学习这几个方向。

第一个是 PWM 输入模式。STM32 定时器可以同时测量周期和占空比,适合遥控器信号解码和电机控制反馈。

第二个是 DMA 配合定时器捕获。用 DMA 把多次捕获值自动搬运到内存,可以降低中断频率,提高高频测频能力。

第三个是等精度测频。当被测信号频率跨度很大时,可以用两个定时器配合,实现从 Hz 到 MHz 的宽范围等精度测量。

如果你在实际配置中遇到问题,建议先回到 CubeMX 确认定时器时钟频率、通道映射和中断配置,再检查回调函数中的计算逻辑。把参数打印出来,对照本文的算式逐步核对,问题基本都能定位。

如果这篇文章对你有帮助,可以收藏备用。后续我也会继续更新 STM32C5A3R 开发系列,包括 PWM 输出、编码器接口、DMA 传输等内容。

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

YOLOv8模型剪枝实战:从稀疏化训练到端侧部署的完整链路

简介:面向目标检测模型部署与压缩需求,YOLOv8模型剪枝源码提供了基于Ultralytics工程的完整剪枝实现,适合希望在资源受限设备上提升推理速度、降低内存占用的开发者与研究者使用。整个压缩包共41个文件,大小仅1.47MB,包…

作者头像 李华
网站建设 2026/9/1 1:36:52

川藏铁路:挑战世界级工程难题的超级基建技术解析

这次我们来看一个关于川藏铁路的技术话题。这不是一个软件项目,而是一项正在进行的超级工程。如果你关心的是本地部署、显存占用或者API调用,这篇文章可能不适合你。但如果你对大型基建工程背后的技术挑战、决策逻辑和实际施工难点感兴趣,那么…

作者头像 李华
网站建设 2026/9/1 1:36:31

基于微信小程序的演唱会售票系统(毕设源码+文档)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

作者头像 李华
网站建设 2026/9/1 1:35:52

用Python和RSS构建个人新闻聚合与质量过滤工具,对抗信息降级

这几年在做技术内容时,我发现自己对“信息”的感知正在变钝。打开手机,推送的新闻好像永远都刷不完;关掉屏幕,却想不起今天真正吸收了哪几条信息。很多文章标题越来越夸张,正文越来越薄,真正经得起推敲的事…

作者头像 李华
网站建设 2026/9/1 1:35:42

计算机毕业设计之基于html的高校二手书交易系统

当下社会,信息技术充斥社会各个领域,已融入人们生活的点滴,日常中人们管理信息、办理业务、购买商品等都可以网络线上进行,快速而又便利,特别是随着移动互联网时代的到来,更是让人们随时享受着网络给带来的…

作者头像 李华
网站建设 2026/9/1 1:33:51

MKVToolNix v100+:无损视频容器编辑与批量处理实战指南

你有没有遇到过这样的场景:从网上下载了一部电影,发现它被封装在一个.mkv文件里,里面包含了多条音轨(比如英语原声、中文配音)、多条字幕(中英双语、特效字幕),甚至还有章节信息。你…

作者头像 李华