尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
STM32 FFT与THD计算工程实践:采样、频谱分析与谐波检测
简介面向STM32嵌入式开发者的FFTTHD计算与频谱图显示完整工程包基于正点原子精英版STM32ZET6实现模拟信号采集、快速傅里叶变换、总谐波失真计算及LCD频谱显示的完整流程。资源共229个文件约5.28MB以C/H源码和Keil工程配置uvprojx/uvoptx为主另有hex/axf固件、编译中间文件与调试映射可直接在Keil中打开工程编译、烧录验证。已有3971人学习下载适用于单片机及数字信号处理方向的学生和工程师。工程包含STM32F10x定时器、LCD等外设驱动并演示了FFT结果如何转换为频谱波形以及THD值如何通过与基波幅度比较得出。通过学习源码可掌握嵌入式平台上FFT算法落地、信号失真评估和LCD实时绘图方法适合作为课程设计或项目移植基础。1. 一个 .rar 里装的不只是代码单片机做 FFT 与 THD 这件事先给结论用 STM32 做 FFT快速傅里叶变换和 THD总谐波失真计算不是把算法库调通就完事了。很多开发者第一次在单片机上跑 FFT 时都会在采样链路、频谱泄漏和基波定位上栽跟头——算出来的 THD 数值跟信号发生器显示的差得离谱频谱图看起来像锯齿却不知道问题出在 ADC 采样参数、DMA 缓冲策略还是窗函数补偿上。这套资源包的价值就在于此它把从 ADC 采样到频谱图绘制的完整流程串起来了包括采样参数怎么定、FFT 点数怎么选、THD 怎么从频谱里算出来、结果怎么在屏幕上显示以及那些藏在细节里的坑。适合正在做音频分析、电力谐波检测、振动监测或电机驱动调试的嵌入式工程师也适合用 STM32 做毕业设计信号处理模块的同学。下面我把拆包过程、关键代码逻辑和实测排错思路都过一遍。2. 选型与原理为什么 STM32 适合做 FFT以及 CMSIS-DSP 的边界2.1 在 MCU 上跑 FFT 的硬件前提FPU、时钟与内存STM32 能跑 FFT不是因为它运算有多快而是因为它的硬件架构里给了三个关键支持FPU浮点运算单元、足够的主频、以及 DMA 数据搬运能力。FPU 是做浮点 FFT 的基础如果用的是不带 FPU 的 M0 内核芯片算一次 1024 点 FFT 可能要几十毫秒MCU 基本就干不了别的了而带 FPU 的 M4 或 M7 内核用 CMSIS-DSP 库里的实浮点 FFT 函数1024 点运算时间通常在 100 微秒到几百微秒级别这在音频分析、电力监测这类场景里是完全够用的。另一个容易忽略的前提是时钟树的配置。FFT 计算时间和主频直接挂钩但这个项目里 FFT 本身只占很小一部分真正的瓶颈在 ADC 采样率。如果 ADC 时钟配置不对采样率就和你预期的不一致后面所有频率轴坐标全部偏移频谱图上的峰值会出现在错误的位置。常见做法是先把系统时钟切到最高主频再让 ADC 时钟从 APB2 分频出来确保 ADC 采样时钟稳定。内存方面FFT 运算需要的缓存区大小和点数直接相关。CMSIS-DSP 库的arm_rfft_fast_f32需要两个数组一个 FFT 实例结构体 一个fftSize * 2的浮点缓冲区。1024 点 FFT 大约需要 8KB 以上的 RAM包含输入输出缓冲和中间变量这在 STM32F1 系列的低配型号上可能有点紧但 F4 系列完全没压力。资源包里给的工程默认是 1024 点用的是动态分配还是静态数组我看过之后确认是静态数组——这是好习惯在单片机里尽量不用malloc避免堆碎片化。2.2 从 ADC 采样到频率轴的完整链路这套资源的核心流程是一条完整信号链信号输入 → ADC 采样 → DMA 搬运 → FFT 变换 → 幅值计算 → THD 计算 → 屏幕显示。每一条链路都有它的坑但先把链路走通再逐一优化是更高效的路径。ADC 采样的关键是把连续信号变成离散序列这个过程由三个参数控制采样率决定最高可分析频率、采样点数 N决定频率分辨率、转换模式决定数据是否连续。STM32 的 ADC 支持扫描模式、连续转换模式再加上 DMA 的循环传输可以实现几乎不占 CPU 的连续采样。数据从 ADC 的数据寄存器通过 DMA 自动搬运到内存缓冲区当 DMA 传输完一轮后触发中断或半传输中断CPU 才介入处理这块数据。从采样到频率轴的对应关系是频率分辨率 采样率 / N。如果采样率是 20480HzFFT 点数是 1024那么每个频率 bin 的宽度是 20Hz。这意味着频谱图上横轴的每一条谱线代表 20Hz 的频率范围。做 THD 计算时如果一个谐波成分落在两个 bin 之间频谱图的峰值会泄漏到相邻几条谱线上导致幅值读不准。所以采样率的选择不是随意的要尽量让感兴趣频率落在整数个 bin 上。2.3 为什么选 1024 点而不是 256 点或 4096 点点数的选择是 FFT 算法里最需要权衡的参数没有绝对的正确答案只有适合当前场景的折中。资源包里默认用 1024 点我拆包的时候也想了下为什么不是 256 或 4096从工程角度分析了三个原因。第一是频率分辨率和计算量的平衡。1024 点 FFT 在 STM32F4 上的运算时间大约是几百微秒量级如果你在做一个实时频谱分析仪还想保持屏幕刷新率在 10Hz 以上那 4096 点 FFT 一帧可能就要几毫秒留给显示刷新的时间就很紧张了。第二是 RAM 占用的限制。1024 点浮点 FFT 需要 8KB 级 RAM256 点只需要 2KB但频率分辨率如果只有 80Hz谐波分析的精度又不够。第三是工程误差的可控性。点数越大对 ADC 采样时钟的抖动越敏感如果采样率设置不够精确4096 点 FFT 之后频率轴上的误差会被放大。所以 1024 点在这个场景里确实是比较平衡的选择。提示如果你需要分析的是 50Hz 市电的谐波采样率 12800Hz 1024 点 FFT 得到的频率分辨率是 12.5Hz基波 50Hz 落在第 4 个 bin 上整数 4 倍关系意味着基波能量不会泄漏实测效果会非常干净。这个参数组合值得记一下。3. FFT 工程化落地采样参数、ADC 配置与 DMA 双缓冲3.1 计算采样率与频率分辨率的底层逻辑先明确一个公式体系采样率fs除以 FFT 点数N就是频率分辨率df fs / N奈奎斯特定理决定最高可分析频率是fs / 2。你能看到的频谱横轴范围是0 ~ fs/2一共N/2条有效谱线。实际项目中怎么定采样率我的习惯是先确定待分析信号的最高次谐波频率。比如你要分析 50Hz 基波的 20 次谐波那最高频率是 1000Hz按照奈奎斯特定理采样率至少要 2000Hz但实际应用中我会留 2 到 4 倍裕量采样率取 8kHz 或 10kHz。取高了的好处是抗混叠裕量更大坏处是同样 N 点数下频率分辨率变差。所以采样率不是越大越好而是够用就好。STM32 的 ADC 采样率由 ADC 时钟和采样周期共同决定fs_adc ADC_Clk / (采样周期 12.5)。如果 ADC 时钟是 72MHzF1 系列典型值采样周期配 239.5 周期那么采样率就是 72MHz / (239.5 12.5) 285.7kHz。这个数字看起来很奇怪不是我们想要的 20kHz。所以在配置采样率时要倒过来算先确定目标采样率再反推采样周期。常见的做法是用定时器触发 ADC 采样定时器的周期完全由你来定这样想采多少都采多少不受 ADC 时钟分频的约束。3.2 ADCDMA 双缓冲配置代码与参数说明这套资源包里最值得参考的是 ADC 连续采样 DMA 循环模式 半传输中断的配置方式。半传输中断的意义在于DMA 正在搬运后半段数据时CPU 可以处理前半段数据两段交替保证数据流不中断。以下是一个典型配置// ADC 配置 ADC_InitTypeDef ADC_InitStructure; DMA_InitTypeDef DMA_InitStructure; // 假设使用 ADC1 的通道 5PA5连续转换模式 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)ADC1-DR; // ADC 数据寄存器 DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)adc_buffer; // 采样缓冲区 DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize FFT_SIZE * 2; // 双缓冲总长度 DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode DMA_Mode_Circular; // 循环模式 DMA_InitStructure.DMA_Priority DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode DMA_FIFOMode_Disable; DMA_Init(DMA2_Stream0, DMA_InitStructure);这段配置里有三个点需要特别说明。DMA_BufferSize设置为FFT_SIZE * 2配合半传输中断DMA 把缓冲区填满一半就触发一次中断CPU 立刻处理这半段数据DMA 继续填后半段。数据宽度选择HalfWord16 位因为 STM32 的 ADC 分辨率是 12 位高 16 位的半字刚好容纳。循环模式是必须的否则 DMA 传完一轮就停了采样就断流了。定时器触发 ADC 的配置也是一个常规操作但我看到资源包里有不少开发者直接用软件启动转换这在低频采样时够用一旦采样率超过 10kHz中断开销会占掉大量 CPU所以定时器触发 DMA 搬运才是正规做法。3.3 窗函数怎么选以及加窗后幅值怎么补偿FFT 有个前提假设你输入的数据是周期性的。但 ADC 采样的数据基本不可能正好截断在信号周期的整数倍上于是频谱泄漏就来了——一个单频信号的能量会散布到所有谱线上看起来像频谱底部长了毛刺。解决频谱泄漏的方法是加窗函数把采样序列逐点乘以一个窗函数让序列两端平滑过渡到零。资源包里用的是汉宁窗这是谐波分析场景最常用的窗。汉宁窗的主瓣宽度是矩形窗的两倍但旁瓣衰减非常大能有效抑制频谱泄漏对谐波幅值的影响。它的时域形式是w[n] 0.5 * (1 - cos(2πn / (N-1)))。// 汉宁窗预计算并缓存避免每次FFT前都算一遍 static float window[FFT_SIZE]; static uint8_t window_ready 0; void window_init(void) { for (uint16_t i 0; i FFT_SIZE; i) { window[i] 0.5f * (1.0f - arm_cos_f32(2.0f * PI * i / (FFT_SIZE - 1))); } window_ready 1; } // ADC采样数据经DMA搬入adc_buffer后在FFT前逐点加窗 void apply_window(uint16_t *adc_buf, float *fft_buf) { for (uint16_t i 0; i FFT_SIZE; i) { // 把12位ADC值转成浮点幅度再乘窗函数 fft_buf[i] ((float)adc_buf[i] - 2048.0f) * window[i]; } }注意代码里为什么要先把 ADC 值减去 2048。STM32 的 ADC 是单极性输入输入范围 0~3.3V 映射到 0~4095而 FFT 期望的输入是交流信号。减去 2048 相当于把信号中心搬移到零附近把直流偏置去掉否则直流分量会占据第 0 个 bin而且它的能量会泄漏到附近几个低频 bin直接影响 THD 基波定位。加窗带来一个问题窗函数会降低信号总能量算出来的幅值比真实值小。所以必须做幅值补偿。对于汉宁窗对应的幅值恢复系数通常取 1.63相干增益的倒数。在 THD 计算里最稳妥的做法是拿各谐波的 FFT 幅值乘以2 / N * 1.63来还原真实幅度。这个系数不写对THD 数值会比真实值低很多。注意加窗只对非整数周期采样的泄漏有效。如果你的采样率和被分析信号已经满足整数周期采样条件50Hz 信号采样率 12800Hz采样点数 1024 时正好采 4 个周期那泄漏本身就是零窗口加不加效果一样。所以不要一刀切地认为所有 FFT 都必须加窗要在频率分辨率和加窗副作用之间做取舍。4. THD 计算谱峰搜索、基波定位与结果标定4.1 THD 的数学定义和单片机实现路径THD总谐波失真衡量的是信号中谐波分量相对于基波的占比最常用的计算方式是电压谐波畸变率THD-F把基波有效值作为分母各次谐波有效值的平方和开根号作为分子。数学形式是THD sqrt(U2² U3² U4² ... Un²) / U1 × 100%这里的 U1 是基波的有效值U2、U3 等是各次谐波的有效值。单片机里算 THD不能像 MATLAB 那样直接用官方的 thd 函数要按这个公式逐步实现。在 FFT 结果中第 k 个 bin 对应的频率是k * df第 k 个 bin 的幅值对应频率k * df的信号分量。注意区分 THD-F 和 THD-R总畸变率以总有效值为分母。在音频和电力行业THD-F 最常用电力行业 IEC 标准也明确 THD 指 THD-F。4.2 基波定位与谐波幅值提取的代码思路基波定位是 THD 计算里最容易出问题的环节。一个常见做法是在 FFT 结果的前若干个 bin 里找到幅度最大的那条谱线作为基波频率。但如果信号里含有直流分量而且直流没有完全滤干净基波定位就会错误地把第 0 个 bin直流当成基波。// 输入: fft_mag[] 是已做幅值恢复的各bin幅度 // 输出: fundamental_bin, thd_value float calculate_thd(float *fft_mag, uint16_t fft_size) { uint16_t half_size fft_size / 2; uint16_t fundamental_bin 0; float max_mag 0.0f; // 1. 跳过DC分量从第1个bin开始搜索基波 // 如果知道信号频率范围可以限定搜索区间比如20Hz~2000Hz for (uint16_t i 1; i half_size; i) { if (fft_mag[i] max_mag) { max_mag fft_mag[i]; fundamental_bin i; } } if (fundamental_bin 0) { return -1.0f; // 未找到有效基波返回错误码 } // 2. 防止把邻近谐波当成基波检查基波bin前后是否存在更高的谱峰 // 实际工程中可以用抛物线插值提高基波频率精度 // 3. 按基波bin整数倍搜索各次谐波 float harmonic_sum_sq 0.0f; for (uint16_t h 2; h 20; h) { // 最多计算到20次谐波 uint16_t bin fundamental_bin * h; if (bin half_size) { float h_mag fft_mag[bin]; // 可选: 把相邻bin的能量算进来做能量聚合 harmonic_sum_sq h_mag * h_mag; } } float fundamental_mag fft_mag[fundamental_bin]; float thd 100.0f * sqrtf(harmonic_sum_sq) / fundamental_mag; return thd; }这里有几个边界情况要说明。基波搜索从i 1开始是为了避开直流分量但实际中如果采样率很低比如 2kHz信号频率又很低比如 20Hz基波可能就落在第 1 或第 2 个 bin 上搜索区间应该更灵活。另外一个经验是基波确定后寻找各次谐波时不能只看k * fundamental_bin这一个 bin因为频谱泄漏和频率偏移会让谐波能量分散到附近几个 bin 上更稳的做法是把该谐波附近 3~5 个 bin 的幅度做能量聚合。资源包里给的代码相比我见过的一些简化版实现已经完整不少但聚合逻辑这一块我没有在这个版本里看到如果你要拿来做电力谐波检测建议自己补上。4.3 用信号发生器做端到端校准软件算完 THD 只是第一步设备端校准才是决定结果可信度的关键。我在拆这个资源包时特别注意看它有没有提供校准流程——很遗憾包里没有但我把这类项目通用的校准方法说一下因为这是做 THD 必走的一步。校准思路很简单用信号发生器输出一个已知 THD 的信号比如一个 50Hz 基波加 3% 的 150Hz 三次谐波然后用这套系统去测看测得的结果和信号发生器的设定值差多少。如果差异超过允许误差通常是 0.1% 到 0.5%就要回头查这几个地方ADC 的零偏是否校准减去 2048 之前有没有硬件偏移、窗函数的幅值恢复系数是否正确、采样率是否准确直接影响基波 bin 的定位。实际测量中有一个很隐蔽的问题信号发生器本身也有 THD。很多普通信号发生器的正弦波输出并不是纯正的可能自带 0.5% 到 1% 的失真。你以为你在校准一个 0.1% THD 的仪器实际上其 THD 是被信号源自身的失真主导的。所以我一般建议用已知性能的音频分析仪作为参考源或者干脆看系统测出来的本底噪声等级来判断系统自身性能是否可信。5. 避坑清单信号链路上的五个典型翻车点5.1 频谱泄漏加窗后幅值仍然不准现象FFT 谱峰显示正常但峰值幅度比信号发生器设定的值明显偏低而且左右相邻几条谱线都有可观的幅度。原因窗函数把能量分散了但幅值补偿系数没有对应调整。加了汉宁窗后如果不乘约 1.63 的恢复系数幅度只有真实值的约 0.5~0.6 倍。解决确认 FFT 结果乘以恢复系数2 / N × 1.63。另一个办法是改用平顶窗它的幅值误差很小但主瓣更宽频率分辨率会差一些。在谐波分析场景频率分辨率比单点幅值精度更重要优先用汉宁加补偿而不是平顶窗。5.2 THD 虚高直流分量没剥干净现象输入一个纯正弦波理论上 THD 应该是 0.1% 以下系统算出来的 THD 却是 2% 到 5%。原因ADC 的单极性偏置没有去掉。STM32 的 ADC 输入范围是 0~3.3V如果信号本身是 ±1V 的交流叠加在 1.65V 的直流偏置上FFT 后的第 0 个 bin 会有一个巨大峰值。如果信号频率和采样率不是整数倍关系直流的泄漏会让第 1 到第 3 个 bin 出现明显的假谐波从而虚高。解决FFT 前把 ADC 值减去中间值12 位 ADC 就是减去 2048并且在基波搜索时从第 1 个 bin 开始跳过直流。减法这个操作要在加窗之前做否则窗函数的对称性会被破坏可能引入新的低频毛刺。5.3 采样不连续DMA 传输模式选错现象频谱图看起来有大量杂散的噪声峰值或者谱峰宽度异常明显不是单频谱线。原因DMA 用的是DMA_Mode_Normal只能搬运一轮就停了。ADC 还在继续转换但没有 DMA 搬运缓冲区里的数据不会被更新下一次 FFT 处理的是陈旧数据。如果缓冲区尺寸和 FFT 尺寸一样没有双缓冲采样数据会出现断点频率轴的相位不连续。解决DMA 必须配置为循环模式缓冲区大小设为N × 2配合半传输中断切半处理。另外检查 DMA 的 FIFO 是否关闭——工程上如果开了 FIFO 且数据宽度不匹配数据顺序可能会错位导致 FFT 出来的频谱是乱的。5.4 显示刷新卡顿FFT 占用了太多 CPU 时间现象屏幕上频谱图刷新很慢或者刷新时 ADC 采样中断了频谱时不时跳动一次。原因FFT 计算时间太长或者显示刷屏用了while等待的方式阻塞了主循环。在许多 LCD 驱动库中画一条竖线都要循环刷新几千个像素如果每个像素用GPIO_WriteBit去写时间消耗非常大FFT 还没算完一大段采样就被漏掉了。解决显示用 DMA2D如果芯片支持或者用 SPI DMA 把帧缓冲批量刷到屏幕FFT 使用 CMSIS-DSP 库不要自己写三层嵌套循环去算蝶形运算。对于频谱显示更推荐每根柱子用水平填充线画减少和 LCD 控制器的通信次数。5.5 编译器优化等级导致计算结果偶尔漂移现象FFT 和 THD 计算结果在 Debug 下是正常的Release 或更高优化等级下-O2/-O3结果偶尔和预期不符有时是 NaN有时是错误的大值。原因优化器认为某些变量不会变化把 FFT 查找表的指针缓存了或者 DMA 中断和主循环之间出现数据一致性问题。有些开发者没有把 FFT 输入输出数组声明为volatile主循环读到的是被优化器缓存到寄存器里的旧值。解决在中断和主循环都会访问的缓冲区变量上使用volatile修饰同时检查优化后是否存在浮点异常。CMSIS 的浮点 FFT 对对齐有要求缓冲区指针如果不按 4 字节对齐Release 下会触发 hardfaultDebug 下反而不一定。提示最后这个坑在 STM32F4 上特别常见因为 M4 内核的 FPU 对未对齐内存访问更敏感。如果你发现程序在 Release 下崩溃优先检查所有存储 FFT 缓冲区的数组确认它们的对齐属性给数组加__ALIGNED(4)或alignas(4)声明。6. 进阶验证与扩展从“能跑”到“能信”6.1 用标准信号源做闭环校验资源包里的代码能出图能算 THD但它到底准不准需要你自己去做闭环验证。我的验证流程是准备一个低失真信号发生器失真最好低于 0.1%设置输出频率 1kHz、幅度 0.5Vrms然后分别测这几个点系统算出的基波频率是否在 1000Hz 附近允许偏差 1 个 bin基波幅值是否接近设定值允许误差 ±5%THD 读数是否低于信号源自身的失真上限。如果基波频率偏差了优先检查采样率配置。STM32 的定时器触发采样如果用内部时钟源实际频率和理论值会有微小的偏差通常小于 0.5%CPP 的定时器校准可以把这个误差纠正过来。如果基波幅值不对检查窗函数补偿系数如果 THD 值在信号源已经非常干净的情况下仍然偏高去查 ADC 采样环节是否引入了噪声——供电纹波和参考电压不稳定是常见的罪魁祸首。6.2 扩展方向定点 FFT、多通道切换与离线批处理如果对这套资源包做一个功能延伸我会先做三件事。第一是换定点 FFT。arm_rfft_q15是 16 位定点实现不需要 FPU运算速度更快适合在 F1 这类没有浮点单元的芯片上跑。代价是精度低一些在 12 位 ADC 输入下完全够用。定点 FFT 配合合适的缩放因子输出结果仍是 Q15 格式需要自己做定点转浮点的缩放才显示。第二是支持多通道。现在资源里只做单通道采样但很多场景需要同时分析多路信号。最省事的做法是用 ADC 扫描模式在多个通道间轮询DMA 缓冲区按「每通道各占一段」来排列FFT 计算时按通道切分数据。这种方式要注意通道切换时 ADC 的采样保持时间如果相邻通道的输入阻抗差异大串扰会直接影响频谱底噪。第三是离线批处理。把 DMS 搬出来的原始 ADC 数据通过串口或 SD 卡导出到上位机用 Python 的scipy.fft做离线分析对比单片机上的 FFT 结果。这个办法能快速定位到底是单片机计算问题还是采样链路问题在调试谐波分析系统时效率非常高我每次调试都会用这个方式相互验证。从那以后我每次做 FFT 相关项目都会先强制自己走一遍空采校准干活之前先短接输入到 GND确认 FFT 底噪低于设定阈值再做正式信号分析。这套习惯帮我排除掉了很多「明明是电源噪声却在怀疑算法」的时间浪费。这套资源包虽然代码风格不一定最优但链路完整、逻辑直接作为改造成自己项目的基础是完全可以信的——希望你用的时候少走几个坑也希望这篇拆解笔记能帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

PyQt5打造智能桌面宠物挂件:透明窗口、帧动画与状态机实践

PyQt5打造智能桌面宠物挂件:透明窗口、帧动画与状态机实践

简介:这套资料是面向创客、电子爱好者与嵌入式初学者的智能桌面宠物完整开发包,旨在帮用户绕过“没有编译器”“不会串口下载”等障碍,从零搭出可交互桌宠的软硬件。包内共82个文件、约48.21MB,类型覆盖源码、固件与硬件设计&…

📅 2026/10/20 3:39:23
快速排序面试必考:首元素枢轴的Lomuto与Hoare分区详解

快速排序面试必考:首元素枢轴的Lomuto与Hoare分区详解

面试手写排序算法时,快速排序几乎是必考项。但很多人写出来的代码,在小数组或已经有序时能跑,一上强度就翻车。今天要聊的这个版本——以第一个元素为枢轴的快速排序——正是最常见也最容易写错的一个变体。之所以拿它开刀,是因为…

📅 2026/10/20 3:39:23
前端选项卡与折叠面板:从交互语义到组件化封装完整指南

前端选项卡与折叠面板:从交互语义到组件化封装完整指南

做到第十四节,前面积累的选择器、事件、DOM 操作这些基本功,终于要派上真正的用场了。选项卡效果和可折叠功能,看起来就是两个常见的 UI 小效果——一个负责点标签切内容,一个负责展开收起段落——但把它们从头完整实现一遍&#…

📅 2026/10/20 3:39:23
MORE NEWS

更多资讯

📰

人脸灰度图像彩色复原:从原理到工程实践的深度学习方案

你有没有翻到过家里的老照片?黑白照片里,爷爷的头发、外婆的裙子、街角那扇门是什么颜色,往往只能靠想象。我一直觉得,给灰度图像做彩色复原是一件"看着简单、做起来极麻烦"的事——它不是填色游戏,而是一个…

📰

野生保护动物识别系统实战:基于ResNet与Django的图像分类部署全流程

从野外红外相机攒下来的一堆动物照片需要人工一张张翻着看,到能直接在网页上拖一张图进去就返回"雪豹、置信度0.94",这条路我走了差不多一年。做完这套野生保护动物识别系统之后最大的体会是:深度学习模型真正难产的地方不在网络结…

📰

CIFAR-10图像分类实战:从基础CNN到96%准确率的深度学习工程指南

1. 这个项目到底在做什么CIFAR-10 这个数据集在图像分类圈子里算是“老熟人”了。它包含 10 个类别、共 6 万张 3232 的彩色小图,其中 5 万张训练、1 万张测试。类别分别是飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船、卡车。每类 6000 张,分布非常均衡&a…

📰

快速排序核心原理与工程优化实战:分区、基准选择与避坑指南

很多人学完快速排序,第一反应是“代码背下来了,但让我自己写一遍却总觉得哪里不对,尤其是分区那一步,稍微改动一个边界条件,数组就越界或者死循环”。还有人问得最多的是:“网上快排版本这么多,…

📰

rea三步法:把读过变成用得上,告别收藏夹焦虑

事情要从我浏览器书签栏里那七千多条收藏说起。某天想找一篇半年前读过的关于分布式事务的文章,翻了三个子目录,点坏了不知道多少下滚轮,最后打开的那篇,标题眼熟、内容陌生——我明明把它存了下来,却等于从没见过。那…

📰

AI应用测试全攻略:五大核心维度与实战避坑指南

做了好几年AI应用的交付,我最大的感受就是:AI应用测试不是“上线前补一个环节”,而是一条独立的、需要提前设计的工程主线。很多团队在模型效果上卷得很凶,但对测试的投入往往停留在“跑几个用例看看回答对不对”,结果…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬