STM32 标准外设库 PID 示例

面向 STM32F103C8 的标准外设库 PID 教学模板,以及定时器、编码器和 PWM 的接入方法。

本页面是 PID 第一课配套的 STM32 标准外设库示例,面向 STM32F103C8 和 STM32 标准外设库。它参考了课程资料中的综合测试程序,但没有复制或移动原始 Keil 工程。

文件说明

  • PID.h:PID 状态结构体和函数声明;
  • PID.c:带显式采样周期、积分限幅、条件积分和测量值微分的 PID 核心;
  • ControlLoop_SPL.h:控制循环接口声明;
  • ControlLoop_SPL.c:展示 TIM1 节拍、编码器反馈和带方向 PWM 的控制循环。

与参考工程的对应关系

参考工程中 TIM1 的计数频率为 1 kHz,因此更新中断周期为 1 msMode21_Tick() 每 40 次中断执行一次 PID,实际控制周期约为 40 ms。参考工程的 PID_Update() 使用误差累加和误差差分,代码短小,适合作为入门版本。

本示例加入了显式采样周期 sample_time,并默认使用测量值微分,从而减少目标值阶跃引起的微分冲击。参数需要根据电机、编码器分辨率、减速比、驱动器限幅和实际采样周期重新整定。

接入现有标准库工程

  1. PID.hPID.cControlLoop_SPL.hControlLoop_SPL.c 加入 Keil 工程。
  2. 保留原工程的 Encoder.cMotor.cPWM.cTimer.c,确认定时器时钟、编码器接线和 PWM 范围一致。
  3. main.c 初始化外设后调用 ControlLoop_Init()
  4. TIM1_UP_IRQHandler() 清除中断标志后调用 ControlLoop_On1msTick()
  5. 在主循环中反复调用 ControlLoop_Run(),不要在中断里调用阻塞式 ADC、串口打印或复杂显示函数。

调用关系

TIM1 更新中断(1 ms)
        │
        ├─ 每 40 次产生一次控制更新请求
        │
        ├─ TIM3 编码器计数 → 位置差分 → 速度反馈
        │
        ├─ PID_Update() → 带限幅的控制输出
        │
        └─ Motor_SetPWM() → 方向 GPIO + TIM2 PWM → 电机

使用边界

这个示例是教学模板,不保证不修改引脚和外设配置就能直接烧录到所有 STM32F103 板卡。使用前需要确认芯片型号、定时器时钟、编码器接口、PWM 周期、电机驱动逻辑和反馈单位。