作为一名嵌入式开发工程师,我经常收到初学者的咨询:如何用最基础的硬件实现一个完整的控制项目?今天要分享的这个基于STM32F103C8T6的串口通讯控制舵机项目,正是为嵌入式新手量身定制的入门实战案例。
这个项目看似简单,却涵盖了嵌入式开发的三大核心技能:MCU基础外设使用(GPIO、定时器)、串口通信协议实现、以及PWM信号生成与控制。我特意选择了市面上最常见的"蓝色药丸"开发板(STM32F103C8T6最小系统板),搭配最基础的SG90舵机,总成本不超过50元,但实现的效果却能给初学者带来满满的成就感。
STM32F103C8T6这颗Cortex-M3内核的MCU,虽然属于STM32家族的入门型号,但72MHz主频和丰富的外设资源完全能满足大多数控制场景。我选择它主要基于三点考虑:
舵机方面,SG90堪称"电子积木":
实际接线时要注意几个关键点:
注意:舵机在运动瞬间会产生较大电流,直接接开发板可能导致复位,建议用示波器观察电源波形。
我推荐使用STM32CubeIDE+STM32CubeMX的组合:
对于初学者,这种开发方式可以避免陷入寄存器配置的细节,快速聚焦在应用逻辑上。
在CubeMX中需要重点配置三个外设:
USART1:
TIM1(用于PWM生成):
GPIO:
整个程序运行流程如下:
串口接收采用中断方式,避免阻塞主程序:
c复制// 在stm32f1xx_it.c中修改USART1_IRQHandler
void USART1_IRQHandler(void) {
if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE)) {
uint8_t ch = (uint8_t)(huart1.Instance->DR & 0xFF);
// 简单的指令解析
if(ch == '0') targetAngle = 0;
else if(ch == '1') targetAngle = 90;
else if(ch == '2') targetAngle = 180;
__HAL_UART_CLEAR_FLAG(&huart1, UART_CLEAR_NEF);
}
}
使用TIM1的通道1生成PWM信号:
c复制// 在主程序中初始化PWM
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
// 角度转脉冲宽度函数
void SetServoAngle(uint8_t angle) {
if(angle > 180) angle = 180;
uint16_t pulse = 500 + angle * (2000 / 180);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pulse);
}
主循环中实现平滑运动效果:
c复制while (1) {
// 当前角度逐步接近目标角度
if(currentAngle < targetAngle) {
currentAngle++;
SetServoAngle(currentAngle);
}
else if(currentAngle > targetAngle) {
currentAngle--;
SetServoAngle(currentAngle);
}
HAL_Delay(10); // 控制运动速度
}
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 舵机不动作 | 电源不足 | 检查供电电压,外接电源测试 |
| 舵机抖动 | 信号干扰 | 加滤波电容,缩短信号线长度 |
| 角度不准 | 脉冲计算错误 | 用逻辑分析仪检查PWM波形 |
| 串口无响应 | 波特率不匹配 | 检查两端波特率设置 |
逻辑分析仪:
STM32CubeMonitor:
串口调试助手:
这个基础项目可以衍生出多个进阶玩法:
多舵机控制:
无线控制:
闭环控制:
上位机开发:
在实际教学中,我发现初学者最容易在三个地方卡壳:PWM参数计算、串口中断配置、以及电源干扰问题。建议先用示波器验证PWM波形正确性,再逐步添加其他功能。这个项目虽然简单,但完整走下来,你对嵌入式开发的基本流程就会有清晰的认识了。