news 2026/9/3 4:48:09

STM32单片机PID控制算法详解:从原理到直流电机调速实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32单片机PID控制算法详解:从原理到直流电机调速实战

你是不是也遇到过这种情况:实验室里,有的同学已经能用PID算法让智能车平稳过弯、让机械臂精准定位,甚至拿了国赛一等奖;而自己还在对着开发板,一遍遍调试流水灯和按键消抖,感觉单片机学了半年,还在原地踏步?

这其实不是天赋问题,而是学习路径和认知深度的差异。很多人把单片机等同于“点灯、按键、数码管”三板斧,却忽略了它作为微型计算机的核心价值——实现自动控制。而PID,正是连接单片机基础与高级控制应用的那座最关键桥梁。

本文不会只讲PID的理论公式,那会让你望而生畏。我们将从一个最经典的场景——用单片机控制直流电机转速——出发,手把手带你从零实现一个完整的PID控制器。你会看到,PID不是数学竞赛题,而是一套可以直接嵌入你代码的实用逻辑。学完本文,你将能:

  1. 彻底理解PID(比例、积分、微分)每个环节的物理意义和代码对应。
  2. 亲手编写并调试一个能在单片机上运行的PID控制程序。
  3. 掌握PID参数整定的核心方法论,告别盲目“试凑”。
  4. 了解PID在平衡车、无人机、温控等前沿项目中的应用思路。

别再让流水灯限制了你的想象力。接下来,我们直接进入核心。

1. PID到底解决了什么问题?从“手动驾驶”到“定速巡航”

想象一下开车。如果让你保持车速恒定在60km/h,你会怎么做?

  1. 你看一眼仪表盘,发现车速是50km/h(当前值低于目标值)。
  2. 于是你踩下油门(执行操作)。
  3. 车速开始上升,到55km/h时,你发现快接近60了,就松一点油门(减少操作量)。
  4. 车速冲到62km/h,超了!你赶紧轻点刹车(反向操作)。
  5. 经过这样反复的“看表-纠偏”操作,车速最终稳定在60km/h附近。

这个过程,你就是一个人肉控制器。你的眼睛是传感器,大脑是控制器,脚是执行器。PID要做的,就是把你大脑里的那套“踩油门/刹车的经验法则”写成数学公式和代码,让单片机自动完成这个过程。

PID的核心价值:它让单片机系统具备了“根据误差动态调整输出”的能力,从而自动、快速、平稳地将一个物理量(如速度、温度、位置)维持在设定的目标值上。没有PID,很多自动控制系统根本无法实现。

2. 拆解PID:比例(P)、积分(I)、微分(D)的通俗解读

PID是三个环节的缩写,我们结合上面开车的例子来理解:

2.1 比例(P)控制 —— “差多少,补多少”

  • 思想:误差(目标值-当前值)越大,控制力度就越大。
  • 开车类比:车速离60km/h差得越远,油门踩得越深。
  • 问题:纯比例控制就像一根弹簧,离目标越近,力度越小。最终会停在目标值附近,但永远存在一个固定的微小差距(静差)。比如,可能最终只能稳定在59.5km/h。

2.2 积分(I)控制 —— “旧账新账一起算”

  • 思想:不仅看当前的误差,还把历史上所有的误差累积起来。只要误差存在,累积量就会越来越大,从而不断增强控制力度,直到消除误差。
  • 开车类比:如果比例控制让你一直停在59.5km/h,积分控制就会说:“这0.5km/h的误差已经持续10秒了,累积误差很大了,我得再深踩一点油门。”
  • 作用消除静差,让系统最终能精确达到目标值。
  • 风险:积分作用太强,会导致系统反应过度,产生超调甚至震荡。

2.3 微分(D)控制 —— “预测未来,刹车防抖”

  • 思想:关注误差变化的趋势(变化率)。如果误差正在快速减小,说明系统正在快速接近目标,此时要提前减小控制力度,防止冲过头。
  • 开车类比:车速从50km/h飞快上升到58km/h,虽然还没到60,但你看这个势头很猛,预测马上要超速,于是提前松油门。这就是微分在“刹车”。
  • 作用抑制超调,减小震荡,提高系统稳定性
  • 风险:对信号噪声非常敏感,噪声会被放大,导致系统抖动。

三者关系总结

  • P是主体,决定反应速度。
  • I是辅助,消除残余误差。
  • D是稳定器,抑制过程震荡。 一个优秀的PID控制器,就是巧妙调和这三者矛盾的结果。

3. 环境准备:从理论到代码的桥梁

在动手写代码前,我们需要明确实验平台和核心组件。本文以最广泛使用的STM32系列单片机直流电机调速为例。你需要准备:

  1. 硬件平台

    • STM32开发板(如STM32F103C8T6核心板)
    • 直流电机(带减速箱) + 电机驱动模块(如L298N、TB6612)
    • 编码器(用于测量电机转速,如霍尔编码器、光电编码器)
    • 电源(为单片机和电机驱动供电)
    • 杜邦线若干
  2. 软件环境

    • IDE: Keil MDK 或 STM32CubeIDE
    • 固件库: HAL库或标准库均可
    • 调试工具: 串口助手(用于打印数据)、VOFA+(可选,用于图形化观察PID调试过程,这是网络热词中提到的利器)
  3. 系统框图(理解信号流)

    目标转速 (SetPoint) -> | | -> PWM控制信号 -> 电机驱动 -> 电机 | PID控制器 | 当前转速 (Feedback) -> | (你的代码) | -> 实际转速 |_______________| | 编码器读数

    你的核心任务,就是在单片机中实现那个“PID控制器”的算法框。

4. PID算法的两种代码实现:位置式与增量式

PID在单片机中有两种主流实现方式,理解它们的区别至关重要。

4.1 位置式PID

位置式PID直接计算控制量的绝对输出值

// 位置式PID结构体定义 typedef struct { float Target; // 目标值 float Current; // 当前值 float Err; // 当前误差 float Err_Last; // 上一次误差 float Err_Sum; // 误差积分项 float Kp, Ki, Kd; // PID参数 float Output; // 控制器输出 float Output_Max; // 输出限幅 float Output_Min; float Integral_Max; // 积分限幅(防止积分饱和) } PID_TypeDef; // 位置式PID计算函数 float PID_Calculate(PID_TypeDef *pid) { pid->Err = pid->Target - pid->Current; // 计算当前误差 pid->Err_Sum += pid->Err; // 误差积分 // 积分限幅 if (pid->Err_Sum > pid->Integral_Max) pid->Err_Sum = pid->Integral_Max; if (pid->Err_Sum < -pid->Integral_Max) pid->Err_Sum = -pid->Integral_Max; // PID公式: Output = Kp*Err + Ki*Err_Sum + Kd*(Err - Err_Last) pid->Output = pid->Kp * pid->Err + pid->Ki * pid->Err_Sum + pid->Kd * (pid->Err - pid->Err_Last); pid->Err_Last = pid->Err; // 更新上次误差 // 输出限幅 if (pid->Output > pid->Output_Max) pid->Output = pid->Output_Max; if (pid->Output < pid->Output_Min) pid->Output = pid->Output_Min; return pid->Output; }

特点与适用场景

  • 输出是执行机构(如PWM占空比)的绝对位置
  • 积分项Err_Sum会不断累积,需要做积分限幅,否则系统启动或设定值突变时容易“饱和”,导致控制失灵。
  • 常用于执行机构不带记忆的系统,如阀门的开度控制、平衡车的角度控制。

4.2 增量式PID

增量式PID计算的是控制量的变化量(增量)

// 增量式PID结构体定义 typedef struct { float Target; float Current; float Err, Err_Last, Err_LastLast; // 当前、上次、上上次误差 float Kp, Ki, Kd; float Output; // 本次输出增量 float Output_Max, Output_Min; // 增量限幅 } PID_Inc_TypeDef; // 增量式PID计算函数 float PID_Inc_Calculate(PID_Inc_TypeDef *pid) { float delta_output; pid->Err = pid->Target - pid->Current; // 增量式PID公式: ΔOutput = Kp*(Err-Err_Last) + Ki*Err + Kd*(Err - 2*Err_Last + Err_LastLast) delta_output = pid->Kp * (pid->Err - pid->Err_Last) + pid->Ki * pid->Err + pid->Kd * (pid->Err - 2 * pid->Err_Last + pid->Err_LastLast); // 增量限幅 if (delta_output > pid->Output_Max) delta_output = pid->Output_Max; if (delta_output < pid->Output_Min) delta_output = pid->Output_Min; pid->Err_LastLast = pid->Err_Last; pid->Err_Last = pid->Err; pid->Output = delta_output; // 注意:这个Output是增量,需要累加到实际控制量上 return pid->Output; }

特点与适用场景

  • 输出是执行机构所需改变的增量。在实际应用中,需要有一个全局变量来累加这个增量,得到最终控制量。
  • 优点
    • 算式中不需要累加误差,算法本身不易发生积分饱和
    • 输出的是增量,对执行机构的影响柔和。当单片机出错或断电时,由于执行机构(如步进电机)只记得位置变化量,影响较小。
    • 手动/自动切换时冲击小。
  • 缺点:存在静态误差,需要靠Ki来消除。
  • 常用于执行机构带记忆的系统,如步进电机的位置控制、变频调速等。

如何选择?对于电机速度控制这种需要快速响应且执行机构(PWM)无记忆的场景,位置式PID更为直观和常用。下文我们将以位置式PID为例进行整合。

5. 项目实战:STM32单片机PID控制直流电机转速

现在,我们将PID算法嵌入到一个完整的电机控制项目中。假设我们使用TIM定时器产生PWM,使用另一个TIM的编码器接口模式读取编码器脉冲。

5.1 系统初始化与PID参数定义

// pid.c #include "pid.h" // 初始化PID结构体 void PID_Init(PID_TypeDef *pid, float target, float kp, float ki, float kd, float out_max, float out_min, float integral_max) { pid->Target = target; pid->Current = 0.0; pid->Err = 0.0; pid->Err_Last = 0.0; pid->Err_Sum = 0.0; pid->Kp = kp; pid->Ki = ki; pid->Kd = kd; pid->Output = 0.0; pid->Output_Max = out_max; pid->Output_Min = out_min; pid->Integral_Max = integral_max; } // PID计算函数(同上文位置式PID_Calculate,此处省略) float PID_Calculate(PID_TypeDef *pid) { // ... 实现代码同上 ... }
// main.c 主循环示例 #include "stm32f1xx_hal.h" #include "pid.h" #include "motor.h" // 假设有电机PWM设置和编码器读取的函数 PID_TypeDef speed_pid; // 声明一个速度PID控制器 float target_speed_rpm = 300.0; // 目标转速:300转/分钟 float current_speed_rpm; // 当前转速 uint32_t encoder_count; // 编码器计数值 uint32_t last_encoder_count = 0; uint32_t last_time_ms = 0; int main(void) { // HAL初始化、时钟配置、外设初始化等 HAL_Init(); SystemClock_Config(); MX_TIM1_Init(); // PWM定时器初始化 MX_TIM2_Init(); // 编码器定时器初始化 MX_USART1_UART_Init(); // 串口初始化,用于调试 // 初始化PID控制器 // 参数需要调试:Kp=0.5, Ki=0.01, Kd=0.05, 输出限幅对应PWM占空比0-100%,积分限幅1000 PID_Init(&speed_pid, target_speed_rpm, 0.5, 0.01, 0.05, 100.0, 0.0, 1000.0); while (1) { // 1. 周期性地计算当前转速 (例如每50ms计算一次) uint32_t current_time_ms = HAL_GetTick(); if (current_time_ms - last_time_ms >= 50) { uint32_t dt_ms = current_time_ms - last_time_ms; // 读取编码器值 (假设编码器一圈产生N个脉冲) encoder_count = TIM2->CNT; // 直接读计数器 TIM2->CNT = 0; // 读完清零,或采用差值法 // 计算转速:转速 = (脉冲数 / 每圈脉冲数) / 时间 * 60000 (转/分钟) // 假设电机减速比为1:30,编码器一圈13线,四倍频后为13*4=52脉冲/圈 // 则电机轴转一圈,编码器产生 52 * 30 = 1560 个脉冲 #define PULSE_PER_REV 1560.0 float delta_pulse = (float)(encoder_count - last_encoder_count); current_speed_rpm = (delta_pulse / PULSE_PER_REV) / (dt_ms / 60000.0); last_encoder_count = encoder_count; last_time_ms = current_time_ms; // 2. 更新PID控制器的当前值并计算 speed_pid.Current = current_speed_rpm; float pwm_output = PID_Calculate(&speed_pid); // 3. 将PID输出(PWM占空比)应用到电机 // 假设pwm_output范围是0-100,映射到PWM比较寄存器值 uint16_t ccr_val = (uint16_t)((pwm_output / 100.0) * MOTOR_PWM_PERIOD); __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, ccr_val); // 4. (调试用)通过串口打印数据 printf("Target:%.1f, Current:%.1f, Err:%.1f, Output:%.1f\r\n", speed_pid.Target, speed_pid.Current, speed_pid.Err, pwm_output); } // 其他任务... } }

5.2 编码器测速的关键细节

上面的代码中,测速是关键且易错的一环。

  • M法测速:在固定时间间隔内统计编码器脉冲数。代码示例采用的就是此法。dt_ms要选择合适,太短则脉冲数少,误差大;太长则系统响应慢。
  • T法测速:测量相邻两个脉冲之间的时间。适用于低速场合。
  • 四倍频:大多数32位单片机TIM的编码器接口模式可以自动实现四倍频,即编码器物理线数乘以4。计算PULSE_PER_REV时必须考虑这一点。
  • 计数器溢出:对于高速电机,计数器可能溢出或反转,需要处理计数器的差值计算,使用int32_t类型来保存差值。

6. PID参数整定:从“玄学”到“方法论”

调参是PID应用的灵魂,但绝非盲目“试凑”。遵循科学的步骤,可以极大提高效率。推荐使用“先P,后I,再D”的经典调试法,并借助VOFA+等上位机软件观察曲线。

6.1 调试步骤

  1. 准备工作

    • 将Ki和Kd设为0。
    • 设定一个合理的目标值(如电机转速200RPM)。
    • 确保系统安全(输出限幅),防止参数过大导致电机飞转。
  2. 整定比例系数 Kp

    • 从小到大地增加Kp(如从0.1开始)。
    • 观察现象:Kp太小时,电机响应慢,转速达不到目标(静差大)。Kp增大,响应变快,静差减小。
    • 找到临界值:继续增大Kp,直到系统出现持续等幅振荡。记录下此时的Kp值,记为Ku(临界增益)。
    • 设定Kp:将Kp设置为0.5 * Ku左右。此时系统响应较快,且没有振荡。
  3. 整定积分系数 Ki

    • 保持Kd=0,逐步增加Ki(如从0.001开始)。
    • 观察现象:Ki的作用是消除静差。加入Ki后,系统最终应能稳定在目标值上。
    • 注意风险:Ki过大,积分作用过强,会导致系统超调增大,甚至出现振荡。表现为达到目标值后“冲过头”,再回来,又冲过去。
    • 设定Ki:在消除静差的前提下,选择一个使系统稳定且超调量可接受的Ki。通常Ki的值远小于Kp。
  4. 整定微分系数 Kd

    • 最后加入Kd。
    • 观察现象:Kd能抑制超调和振荡。合适的Kd能让响应曲线平滑地接近目标值,没有“抖动”。
    • 注意风险:Kd对噪声极其敏感。如果编码器信号有毛刺,过大的Kd会放大噪声,导致输出剧烈抖动。务必确保反馈信号干净
    • 设定Kd:从小开始增加,直到系统响应平稳,超调明显减小。Kd的值通常也较小。

6.2 借助上位机调试(VOFA+)

网络热词中提到了VOFA+,这是一个强大的串口数据可视化工具,堪称PID调试的“眼睛”。

  1. 在单片机代码中,以特定格式(如printf(“%.2f,%.2f\r\n”, target, current);)通过串口发送目标值和实际值。
  2. 在VOFA+中配置相同的串口参数,并添加波形图控件。
  3. 运行系统,你将看到实时的响应曲线。通过观察曲线,可以非常直观地判断Kp、Ki、Kd的影响,大幅提升调试效率。

7. 常见问题与排查思路(PID调试避坑指南)

问题现象可能原因排查方式解决方案
电机完全不动1. PWM输出通道或极性错误。
2. 电机驱动模块未使能或供电不足。
3. PID输出始终为0或负值(限幅在0)。
1. 用示波器或LED检查PWM信号是否生成。
2. 检查驱动模块逻辑电压和电机供电电压。
3. 打印PID输出值,检查目标值是否远小于当前值。
1. 检查定时器和GPIO配置。
2. 确保驱动模块使能引脚拉高,供电电压足够。
3. 检查PID初始化参数,确保目标值设置正确。
电机疯转,不受控1. 编码器接线错误,反馈信号为0或恒定值。
2. PID参数中Kp过大。
3. 误差计算符号反了 (Current - Target)。
1. 旋转电机,打印编码器计数值,看是否变化。
2. 将Kp设为0,看电机是否停止。
3. 检查PID计算中的误差公式。
1. 检查编码器A/B相接线,确认定时器编码器模式配置正确。
2. 大幅降低Kp,从很小值开始调。
3. 确保误差 = Target - Current。
转速震荡(忽快忽慢)1. Kp或Ki过大。
2. 微分系数Kd为0或太小。
3. 测速周期不稳定或太慢。
1. 观察震荡周期,长周期可能是Ki过大,短周期可能是Kp过大。
2. 加入适当的Kd观察效果。
3. 检查定时中断优先级,确保测速周期准确。
1. 遵循“先P后I再D”原则重新调参,适当减小引起震荡的参数。
2. 引入滤波算法(如一阶低通滤波)处理编码器信号。
存在静差,达不到目标1. 纯比例控制(Ki=0)固有缺陷。
2. Ki太小或积分限幅太小。
3. 系统存在无法克服的阻力(如摩擦力)。
1. 检查Ki是否为0。
2. 观察积分项Err_Sum是否在增长。
3. 增大目标值,看是否能达到更高转速。
1. 适当增加Ki值。
2. 检查并增大积分限幅Integral_Max
3. 检查机械结构,或增大输出限幅(需在安全范围内)。
响应迟钝,加速慢1. Kp太小。
2. 输出限幅Output_Max设置过低。
3. 电机/驱动本身功率不足。
1. 观察误差很大时,输出是否也很大。
2. 检查PID输出的最大值是否被限制得很低。
3. 直接给最大PWM,看电机最大转速是否达标。
1. 增大Kp。
2. 合理提高输出限幅,但不要超过执行器(电机/PWM)承受范围。
3. 更换更大功率的电机和驱动。

8. 进阶与最佳实践:从“能用”到“用好”

当你调通一个基本的PID后,可以关注以下进阶内容,这往往是比赛和项目中的加分项。

8.1 抗积分饱和(Integral Anti-Windup)

问题:当误差长期存在(如电机卡住),积分项会累积到巨大值。一旦误差反向,需要很长时间“消化”这个巨大的积分项,导致控制失灵,反应迟钝。解决:在位置式PID中,我们已通过Integral_Max进行了积分限幅。更优的方法是积分分离遇限削弱积分:当输出达到限幅时,停止积分或只累积与输出方向相反的误差。

8.2 微分先行与输入滤波

微分先行:只对反馈值(测量值)微分,而不对设定值微分。这样可以避免设定值突变时,微分项产生巨大的冲击(设定值突变时,误差变化率极大)。输入滤波:对反馈信号(如编码器速度)进行低通滤波,平滑噪声,避免微分项将噪声放大。常用一阶RC滤波或滑动平均滤波。

// 一阶低通滤波示例 float LowPass_Filter(float new_value, float old_value, float alpha) { // alpha = dt / (dt + RC), dt为采样周期,RC为滤波时间常数 return alpha * new_value + (1 - alpha) * old_value; } // 在更新 current_speed_rpm 后调用 current_speed_rpm = LowPass_Filter(raw_speed_rpm, current_speed_rpm, 0.2);

8.3 变参数PID与模糊PID

  • 变参数PID:在不同的误差范围内使用不同的PID参数。例如,误差大时用大Kp快速响应,误差小时用小Kp和加入微分防止震荡。这需要根据系统特性设计一个参数切换逻辑。
  • 模糊PID:用模糊规则(如果误差大且误差变化率大,则输出大)来代替固定的PID公式,对于非线性、模型不精确的系统有更好效果。这是AI技术在PID上的一种应用(对应网络热词)。

8.4 串级PID(Cascade PID)

对于复杂对象,如无人机姿态控制、平衡车,单环PID往往不够。串级PID将系统分解为内外两个环。

  • 内环(快环):通常控制电机电流、扭矩或角速度,响应快。
  • 外环(慢环):控制最终目标,如无人机角度、平衡车倾角。 外环PID的输出,作为内环PID的目标值。例如,平衡车角度环(外环)的输出是角速度目标,送给电机速度环(内环)作为输入。这种结构抗干扰能力更强,控制更精细。

9. 总结:PID是你从单片机新手到项目高手的必经之路

回过头看,PID的本质是一种思想,一种用“过去、现在、未来”的误差信息来决策的控制思想。单片机是它的身体,编码器、电机等传感器和执行器是它的手脚。

掌握PID,意味着你不再仅仅是在操作单片机的IO口,而是在设计一个能够自主应对环境变化的智能系统。这正是智能车、机器人、无人机等众多精彩项目的核心技术基础。

你的下一步可以是什么?

  1. 巩固基础:在本文的电机调速例程上,尝试控制不同的对象,如通过加热棒和温度传感器实现恒温控制。
  2. 挑战进阶:研究串级PID,尝试用两个PID环控制一个平衡小车站立。
  3. 探索优化:了解模糊PID神经网络PID等智能PID算法,思考它们如何解决传统PID的局限性。
  4. 工程化:将你的PID控制器模块化、参数可在线调整(通过串口命令)、加入运行状态监测,使其更容易移植到其他项目。

不要再让单片机学习停留在外设驱动。从理解并实现一个PID控制器开始,真正踏入嵌入式控制系统的世界。当你调通的电机平稳地达到预设转速时,你会明白,那种对系统施加精确控制的成就感,远非点亮一排流水灯可比。

建议收藏本文,在未来的每个控制类项目中,它都可能成为你快速复现和调试的参考手册。

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

从美景内容到旅行规划:高效提取实用信息与创作指南

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

作者头像 李华
网站建设 2026/9/3 4:39:48

SP200SE编程器实战:BIOS芯片读写、烧录与故障排查指南

简介&#xff1a;SP200SE编程器资料包定位清晰&#xff0c;主要面向电子工程师、单片机爱好者及硬件维修人员&#xff0c;解决通用串行总线接口编程器的制作、固件升级、驱动安装与多器件烧录调试等实际需求。全套资源共38个文件&#xff0c;压缩包约9.02MB&#xff0c;包含原理…

作者头像 李华
网站建设 2026/9/3 4:39:05

基于OpenCascade的轻量级CAD开发实战解析

简介&#xff1a;基于OpenCascade 6.2.0编写的简易CAD实现程序&#xff0c;由作者astrosky整理发布&#xff0c;面向初次接触几何内核开发的图形学与CAD方向学习者。程序覆盖曲线绘制与编辑、曲面创建与编辑、实体创建与编辑等典型功能&#xff0c;并借助NURBS接口演示了基础造…

作者头像 李华
网站建设 2026/9/3 4:39:01

HyperMesh官方教程hm.zip使用指南:从解压到复合材料建模

简介&#xff1a;hypermesh官方教程的配套模型文件hm.zip&#xff0c;面向正在学习Hypermesh 13.0/14.0的初学者与工程技术人员&#xff0c;用途是配合官方教程完成几何编辑、网格生成与求解设置的实战练习。压缩包共173个文件&#xff0c;约71.76MB&#xff0c;以120个hm格式源…

作者头像 李华
网站建设 2026/9/3 4:38:57

Hyper Pop与Glitch音乐制作全解析:从数字音色到节奏破碎

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

作者头像 李华
网站建设 2026/9/3 4:38:18

SPIFS:面向w25qXX SPI NOR Flash的精简文件系统设计

简介&#xff1a;SPIFS是一套为W25Q32、W25Q64、W25Q128等SPI Flash器件设计的极简文件系统&#xff0c;核心代码约500行&#xff0c;面向资源有限的嵌入式场景&#xff0c;目标是让开发者以低成本获得基础的文件管理能力&#xff0c;可用于日志存储、参数保存、设备配置读写等…

作者头像 李华