
简介本资源是一套面向嵌入式初学者与机器人爱好者设计的四足机器人步态控制实战代码聚焦STM32F103ZGT6平台在真实硬件上的运动控制落地解决多自由度步态规划、遥控指令解析与总线舵机协同驱动等核心问题。压缩包共421个文件含65个C源文件如move.c、stm32f10x_tim.c等关键模块、71个头文件h、81个编译中间文件o/d及Keil工程配置文件uvprojx/uvoptx完整覆盖从底层外设驱动、定时器PWM输出、串口通信协议到高层步态状态机的全链路实现包体大小为15.67MB。已有5548人学习下载代码基于MATLAB生成的步态算法移植而来经实物验证可稳定运行小跑、行走、左右转弯、横移及后退五种基础步态所有函数与参数均附中文注释步态周期、相位偏移、支撑腿逻辑等关键变量清晰标注小白亦可快速理解并二次开发。1. 项目概述从零构建一个灵活的四足机器人最近在整理资料时翻出了几年前做的一个四足机器人项目核心是基于STM32F103ZGT6这颗经典的“大容量”MCU配合Keil MDK-ARM开发环境实现了一套完整的步态控制程序。这套代码包含了遥控接收解析、步态生成、舵机控制等所有核心模块支持小跑、行走、左右转弯和横移四种基本步态。对于想入门足式机器人或者想深入了解底层运动控制的朋友来说这个项目麻雀虽小五脏俱全能帮你把书本上的运动学理论和实际的电机控制串联起来。四足机器人听起来高大上但其核心控制逻辑可以拆解为几个相对独立的部分首先是感知即如何获取控制指令比如通过遥控器其次是决策即根据指令和当前状态决定机器人应该采用哪种步态模式最后是执行也就是将抽象的步态轨迹转化为具体舵机的角度指令并驱动它们精确运动。这个项目就是围绕这三个环节展开的。它不依赖于复杂的操作系统或第三方库所有代码都是裸机状态下的纯C语言实现结构清晰非常适合学习和二次开发。无论你是电子爱好者、机器人专业的学生还是想进行技术验证的工程师都能从中找到可以借鉴和复用的部分。2. 核心硬件平台与开发环境搭建2.1 主控芯片选型为什么是STM32F103ZGT6在项目初期主控芯片的选择至关重要。我最终选择了STM32F103ZGT6这背后有非常实际的工程考量。首先它是STM32F1系列中资源最丰富的型号之一拥有144引脚、1MB的Flash和96KB的RAM。对于四足机器人控制程序来说Flash空间要存储大量的步态数据表、三角函数表以及程序代码1MB的容量绰绰有余。而96KB的RAM则为多路舵机控制产生的中间变量、遥控数据缓冲区以及运行时的堆栈提供了充足的空间避免了频繁的内存瓶颈。其次它拥有多达11个定时器其中高级定时器TIM1, TIM8和通用定时器TIM2-TIM5是生成多路PWM信号的关键。一个典型的12自由度四足机器人需要控制12个舵机每个舵机都需要一路独立的PWM信号。STM32F103ZGT6的定时器资源可以轻松地配置出十几路高精度的PWM输出且互不干扰。最后它的外设接口丰富包括多个USART、SPI和I2C可以方便地连接无线串口模块如HC-05/HC-08用于蓝牙遥控、IMU模块用于未来扩展姿态反馈等为系统的扩展性留足了余地。虽然现在有性能更强的F4、H7系列但对于学习步态控制基础而言F103系列成本更低、资料更全、生态更成熟是性价比极高的入门选择。2.2 开发环境Keil MDK-ARM 5的配置与避坑指南代码开发在Keil MDK-ARM 5常被称为Keil5环境下完成。对于STM32开发正确配置环境是第一步也是最容易踩坑的一步。安装与芯片支持包首先你需要从ARM官网或Keil官网下载并安装MDK-ARM。安装完成后最关键的一步是安装针对STM32F1系列的Device Family PackDFP。你需要通过Keil的Pack Installer菜单栏Pack - Pack Installer在线搜索并安装Keil::STM32F1xx_DFP。很多新手编译时出现No ULINK2/ME Device Found或者找不到芯片型号问题大多出在这里。工程创建与配置新建工程选择芯片型号为STMicroelectronics - STM32F103ZEZGT6和ZE在Keil的Pack里是同一个系列资源一致。管理运行时环境RTE这是一个关键步骤。在Manage Run-Time Environment窗口中你需要至少勾选CMSIS - COREDevice - Startup(用于初始化代码)Device - STM32Cube Framework (API)-Classic这里选择经典的外设库而非HAL库因为我们的代码基于标准外设库开发更贴近底层便于理解。添加用户代码文件将你的.c和.h文件添加到工程目录下的User文件夹并在Keil工程管理器中将其加入对应的组。注意网上有些教程会教你手动复制标准外设库文件到工程里但对于Keil5强烈建议使用RTE方式管理它能自动处理库文件路径和依赖避免很多奇怪的编译错误。调试器设置我使用的是ST-Link V2调试器。在Options for Target - Debug选项卡中选择Use: ST-Link Debugger然后点击旁边的Settings。在Debug选项卡确认SWD接口识别到了芯片IDCODE在Flash Download选项卡确保勾选了Reset and Run并添加了STM32F10x High-density Flash的编程算法。这样就能实现一键下载、运行和调试了。3. 步态控制原理与整体软件架构设计3.1 四足步态基础三角步态与对角步态要让四足机器人走起来首先要理解其步态。我们实现的“行走”和“小跑”分别对应了两种最经典的步态模式。行走步态Walk通常采用三角步态。在这种步态下机器人的四条腿被分为两组对角线组合左前-右后为一组右前-左后为另一组。运动时总有三条腿处于支撑相接触地面支撑身体一条腿处于摆动相抬起向前迈步。这种步态速度慢但稳定性极高重心始终落在支撑三角形内非常适合低速、重载或需要极高稳定性的场景。小跑步态Trot则采用对角步态。此时两条对角线上的腿左前-右后右前-左后分别同步运动。即一组对角线腿支撑时另一组摆动。这种步态只有两条腿同时支撑运动类似马的小跑速度更快动态性能好但稳定性相对较低需要较好的控制来维持平衡。我们的代码实现了这两种步态的平稳生成与切换。转弯和横移则是基于基础步态的衍生。左右转弯通过调整身体两侧腿的步幅来实现向左转时右侧腿的步幅大于左侧腿从而产生旋转力矩。横移则更简单让四条腿同时向侧方迈步即可。所有这些步态的核心都在于为每条腿末端的“足端”规划一条在空间中的运动轨迹。3.2 软件整体架构模块化与实时性保障整个控制程序采用前后台超级循环架构这对于资源有限的单片机且逻辑清晰的中小型系统来说非常高效。软件主要分为以下几个模块硬件抽象层HAL最底层负责初始化系统时钟、GPIO、定时器用于PWM生成、串口用于遥控接收等硬件外设。它将硬件操作封装成统一的接口方便上层调用。舵机驱动层基于定时器PWM提供设置单个舵机角度、批量更新所有舵机角度的函数。这里包含一个重要的“舵机消抖”和“平滑过渡”算法避免舵机因指令突变而产生抖动或过冲。运动学层这是核心算法层。包含正运动学和逆运动学计算。正运动学已知所有舵机角度计算每个足端在“机体坐标系”下的位置。主要用于仿真和调试。逆运动学这是关键。已知我们希望足端到达的目标位置来自步态规划反算出每个舵机需要转动的角度。对于常见的3自由度腿髋关节横滚、髋关节俯仰、膝关节俯仰我们使用几何法进行求解计算量小实时性高。步态生成层根据当前选择的步态模式行走、小跑、转弯、横移生成一个周期内每条腿足端在机体坐标系下的轨迹序列。轨迹通常用参数方程描述例如摆动相足端轨迹可能是一个抛物线支撑相则是水平向后移动的直线。遥控指令解析层通过串口中断接收来自无线模块如蓝牙的遥控数据包解析出目标速度、转向指令、步态切换命令等并设置相应的全局控制标志位。主控制循环在main()函数的while(1)循环中不断执行以下流程检查是否有新的遥控指令更新控制参数。根据当前步态和参数调用步态生成层计算下一时刻所有足端目标位置。调用逆运动学将足端位置转换为12个舵机的目标角度。调用舵机驱动层将目标角度转化为PWM占空比并更新输出。插入精确延时控制整个步态周期的节奏例如一个步行周期2秒则每20ms更新一次足端位置。这种架构清晰地将数学计算、硬件控制和决策逻辑分离便于调试和功能扩展。例如未来想要加入IMU实现姿态平衡只需要在运动学层之前加入一个“姿态补偿”模块根据机体倾斜角度微调足端目标位置即可。4. 遥控系统与指令解析实现4.1 无线通信方案选择与数据协议设计遥控部分采用了最经济可靠的方案一个普通的蓝牙串口模块如HC-05连接到STM32的USART上手机端用一个简单的串口调试助手APP或者自己写的上位机发送指令。为什么不直接用2.4G遥控器接收机因为串口通信更灵活可以传输更复杂的结构化数据方便后期扩展比如传输一整套姿态参数。为了确保通信可靠我们设计了一个简单的帧协议。每一帧数据由帧头、数据长度、指令类型、数据内容、校验和组成。例如0xAA 0x55 0x04 0x01 0x64 0x00 0xC8 0xXX0xAA 0x55固定的帧头用于在数据流中识别一帧的开始。0x04后续数据段的长度。0x01指令类型比如0x01代表速度控制。0x64 0x00数据内容这里可以表示前进速度0x0064 100。0xC8校验和前面所有字节的累加和取低8位。0xXX帧尾可选。在STM32端我们使用串口接收中断。每收到一个字节就进入中断服务函数运行一个状态机来解析这个数据帧。状态机通常有以下几个状态等待帧头1-等待帧头2-等待长度-接收指令和数据-等待校验和。只有完整通过校验的一帧数据才会被确认为有效指令更新到全局变量中供主循环使用。这种方式能有效抵抗无线通信中的偶发干扰和数据错位。4.2 指令映射与控制模式切换解析出的指令需要映射到机器人的控制参数上。我们定义了以下几个核心控制量线速度控制机器人前进/后退的速度。它直接映射为步态生成器中足端在支撑相的后移速度。角速度控制机器人左转/右转的速率。它映射为身体两侧腿的步幅差。横向速度控制机器人横移的速度。步态模式一个枚举值用于在行走(WALK)、小跑(TROT)、横移(SHFFLE)之间切换。急停标志立即停止所有运动所有腿回到初始站立位置。主控制循环会定期比如每50ms检查这些全局控制变量是否被遥控指令更新。如果有更新则平滑地过渡到新的目标值而不是突变以避免机器人动作突兀甚至失稳。例如当从“行走”切换到“小跑”时程序会先完成当前步行周期然后在下一个周期开始时逐步将步态参数调整到小跑模式并在几个周期内完成过渡。5. 逆运动学计算与舵机控制详解5.1 单腿逆运动学从足端位置到舵机角度这是将规划好的空间轨迹转化为实际电机动作的桥梁。我们的机器人每条腿有3个自由度简化模型可以看作两个连杆大腿和小腿在二维平面内运动。我们为每条腿建立一个独立的坐标系原点在髋关节处。已知足端目标点坐标(x, y, z)相对于髋关节坐标系大腿长度L1小腿长度L2。 求解髋关节俯仰角θ_hip膝关节俯仰角θ_knee。计算过程采用几何法首先计算足端在侧视平面内的投影距离d sqrt(y*y z*z)。这里y是前后方向z是垂直方向。然后通过余弦定理可以解出膝关节角度θ_kneecos(θ_knee) (L1*L1 L2*L2 - d*d) / (2*L1*L2)θ_knee acos(cos(θ_knee))注意角度范围我们通常取0~180度接着计算中间角α和βα atan2(z, y)// atan2函数能正确处理象限β acos((L1*L1 d*d - L2*L2) / (2*L1*d))最后得到髋关节俯仰角θ_hip α β。髋关节的横滚角θ_roll通常由另一个单独的舵机控制用于实现腿的侧向摆动横移时用到其计算更简单θ_roll atan2(x, sqrt(y*yz*z))其中x是侧向坐标。在代码中我们需要预先计算好三角函数表或者使用MCU的数学库如arm_math并将计算出的弧度值转换为舵机对应的PWM脉宽值例如0度对应0.5ms180度对应2.5ms中间线性映射。5.2 多路PWM生成与舵机驱动优化STM32F103ZGT6的定时器功能强大我们使用两个通用定时器如TIM2和TIM3来生成12路PWM。每个定时器有4个通道可以产生4路PWM。我们将12个舵机分成3组每组4个分别由TIM2、TIM3、TIM4另一个定时器的4个通道控制。配置定时器为PWM模式1向上计数自动重装载值ARR设置为20000-1对应20ms周期50Hz频率这是标准舵机信号预分频器PSC根据系统时钟频率计算得出。每个通道的比较寄存器CCRx的值就对应了脉宽。例如若ARR19999则CCRx500对应0.5ms0度CCRx2500对应2.5ms180度。实操心得直接更新CCRx寄存器改变PWM占空比时在计数值到达更新事件UEV的瞬间可能会产生毛刺导致舵机抖动。一个优化技巧是使用定时器的“预装载寄存器”。在代码中我们更新的是CCRx的影子寄存器即写入TIMx-CCRx然后设置一个标志位。在一个统一的时间点比如所有计算完成后在定时器更新中断中再通过TIMx-EGR TIM_EGR_UG指令产生一个更新事件让所有影子寄存器的值一次性生效。这样12个舵机的PWM信号是同步更新的动作会更加整齐平滑。此外为了减少总线负载和舵机响应延迟我们采用了“分时更新”策略。不是每次计算完就立刻更新所有舵机而是将更新命令放入一个队列由后台定时器中断服务程序每隔几毫秒取出一个执行。这样避免了CPU时间被长时间占用也给了舵机足够的响应时间。6. 步态轨迹规划与生成器实现6.1 足端轨迹设计摆动相与支撑相步态生成器的任务是在每一个控制周期如20ms为每条腿计算出一个目标足端位置。这个位置随时间变化的序列就是足端轨迹。一条完整的步态周期轨迹分为摆动相和支撑相。对于摆动相腿抬起向前迈步我们希望足端轨迹是平滑的抛物线。这可以通过一个在时间上归一化的参数t(0到1) 来定义x(t) 步长 * t水平方向匀速前进z(t) 抬腿高度 * sin(π * t)垂直方向按正弦曲线先抬后落这种正弦曲线轨迹保证了足端在抬起和落地的瞬间速度为零冲击小动作自然。对于支撑相腿支撑身体向后蹬地足端轨迹相对简单主要是水平向后移动以推动身体前进x(t) -步长 * t水平方向匀速后移z(t) 站立高度保持恒定略低于初始站立高度以提供支撑力在代码中我们为每种步态行走、小跑预定义了一个相位表。这个表定义了在一个完整周期内每条腿相对于周期起点的相位偏移。例如对于对角小跑步态左前腿和右后腿的相位是0右前腿和左后腿的相位是0.5即半个周期。步态生成器根据全局时钟一个不断累加的循环计数器和每条腿的相位计算出它当前处于周期内的哪个位置即参数t然后根据它是处于摆动相还是支撑相调用对应的轨迹方程计算目标位置。6.2 步态切换与参数插值当收到遥控指令要求切换步态或改变速度时不能粗暴地立即改变所有参数。我们需要一个平滑的过渡过程。这通过线性插值或平滑函数如S型曲线来实现。例如当前步态周期参数为P_old目标步态周期参数为P_new。在过渡开始的N个控制周期内我们实际使用的参数P_current是P_current P_old (P_new - P_old) * (i / N)其中i是从过渡开始后的第几个周期。对于步态模式切换情况更复杂一些。我们需要保证在切换瞬间所有腿的足端位置是连续的不能出现“跳跃”。一个稳妥的做法是在接收到切换指令后先让机器人完成当前的步态周期让所有腿都回到支撑相的中段这是一个相对稳定和通用的位置然后在下一个周期开始时无缝切换到新步态的初始相位。同时步长、抬腿高度等参数也按照上述插值方法在几个周期内渐变过去。7. 系统集成、调试与性能优化7.1 代码组织与编译配置一个清晰的项目目录结构至关重要。我的工程目录通常如下/Project_Robot /CMSIS (由RTE自动管理) /Device (由RTE自动管理) /User /inc gait.h (步态定义与函数声明) kinematics.h (运动学函数声明) servo.h (舵机驱动函数声明) remote.h (遥控协议与函数声明) config.h (机器人力学参数、引脚定义等) /src main.c gait.c kinematics.c servo.c remote.c stm32f10x_it.c (中断服务函数) /EWARM (IAR工程文件如果有) /MDK-ARM (Keil工程文件) /Doc (原理图、数据手册等)在config.h中集中定义了所有硬件参数和机器人参数如// 机械参数 #define LENGTH_THIGH 80.0f // 大腿长度单位mm #define LENGTH_CALF 100.0f // 小腿长度单位mm #define STAND_HEIGHT 120.0f // 站立高度单位mm // 步态参数 #define WALK_PERIOD 2000 // 行走周期单位ms #define TROT_PERIOD 800 // 小跑周期单位ms #define LEG_LIFT_HEIGHT 30.0f // 抬腿高度单位mm // 引脚映射 #define SERVO1_PIN GPIO_Pin_0 #define SERVO1_PORT GPIOA // ... 其他11个舵机引脚定义在Keil的Options for Target - C/C中确保包含了正确的头文件路径并且优化等级选择-O1或-O2。对于调试阶段可以选择-O0不优化便于单步跟踪。同时勾选Use MicroLIB可以减小代码体积。7.2 调试技巧与常见问题排查四足机器人调试是一个“机电软”结合的过程问题可能出现在任何一个环节。1. 舵机不动或乱转检查电源这是最常见的问题。12个舵机同时工作电流很大峰值可能超过5A务必使用独立的大电流如5V/10A开关电源供电并与MCU的3.3V电源共地。MCU控制信号的地线必须与舵机电源地可靠连接。检查信号线确认PWM信号线连接正确没有虚焊。用示波器测量PWM波形看周期是否为20ms脉宽是否在0.5ms~2.5ms之间变化。检查代码确认定时器PWM输出通道是否配置正确GPIO是否设置为复用推挽输出模式。在调试时可以写一个简单的测试函数让某个舵机在0度和180度之间缓慢摆动先排除单个舵机驱动的问题。2. 步态不稳机器人摇晃或跌倒检查逆运动学参数反复核对config.h中的大腿和小腿长度是否与实物一致。单位是毫米还是米计算出的角度值在传递给舵机时映射到PWM脉宽的公式是否正确可以先用正运动学验证给一组已知角度计算足端位置看是否符合预期。检查足端轨迹在调试时可以将计算出的足端目标位置通过串口打印出来绘制成曲线图可以用MATLAB或Python的Matplotlib。观察摆动相轨迹是否平滑支撑相轨迹是否水平。轨迹的突变会导致加速度突变引起晃动。检查相位表确认步态的相位关系是否正确。对于行走步态四条腿的相位应依次相差0.25个周期。可以用LED或调试信息指示每条腿当前处于摆动相还是支撑相观察其顺序是否符合预期。机械结构刚性如果机械结构本身松松垮垮再好的控制算法也无济于事。确保所有关节连接紧固舵机舵盘没有打滑。3. 遥控指令响应延迟或丢失检查串口配置波特率是否匹配手机APP和STM32端都设为9600或115200数据位、停止位、校验位是否一致检查数据解析在串口接收中断服务函数里加入超时判断。如果一段时间内没有收到完整帧则重置状态机防止因某个字节丢失而一直等待。增加软件去抖对于遥控指令可以设置一个“死区”。例如只有当速度指令的变化量超过某个阈值如5时才更新避免因遥控器摇杆微动或信号噪声导致的频繁微小变化。降低主循环频率如果主循环计算量太大导致周期远超过20ms也会造成控制响应迟钝。使用定时器中断来严格定时触发控制循环而不是用delay_ms()。4. 代码跑飞或HardFault堆栈溢出四足机器人程序变量多函数调用嵌套可能较深。在Keil的启动文件startup_stm32f10x_hd.s中适当增大堆栈大小Stack_Size 和 Heap_Size。数组越界或指针错误仔细检查所有数组访问特别是步态相位表、舵机角度数组等。使用__align(4)确保关键数据结构对齐。浮点计算如果使用了单精度浮点运算且没有启用FPUF103没有硬件FPU计算会非常慢可能导致定时中断无法及时响应。可以考虑将关键计算如逆运动学改为使用定点数运算Q格式来大幅提升速度。例如将长度和角度乘以一个缩放因子如1000用整数存储和计算最后再转换回来。通过模块化的测试先调通单个舵机再调通单条腿的运动学然后调通两条腿的对角步态最后整合四条腿和遥控可以逐步定位问题。耐心和细致的调试是机器人项目成功的另一半。本文还有配套的精品资源点击获取