STM32--SG90舵机


目录

前言

一、工作原理

二、接线方式

三、软件程序

sg90.h

sg90.c

main.c

关键说明(避坑重点)!!!!

总结

前言

最近用到了STM32驱动HX711称重传感器模块,我这里用的STM32是STM32F103C8T6,这个模块的扭矩力能达到1.6KG/CM,所以记录一下

一、工作原理

  1. 核心逻辑:STM32 定时器生成 50Hz(20ms 周期)PWM,通过 CCR 值控制 0.5~2.5ms 高电平脉宽,SG90 内部解析脉宽实现角度控制
  2. 关键链路:系统时钟→定时器 PSC/ARR(定周期)→定时器 CCR(定脉宽)→PWM 输出→SG90 内部闭环执行→稳定角度;
  3. 核心映射:角度→CCR 值→脉宽→舵机角度,三者为线性对应关系。

PWM信号控制

  • 信号周期:20ms(50Hz)。

  • 脉冲宽度:0.5ms - 2.5ms,对应角度0° - 180°。

二、接线方式

|-----|-----|
| VIN | 5V |
| GND | GND |
| PWM | PA0 |


三、软件程序

sg90.h

复制代码
#ifndef __SG90_H
#define __SG90_H

#include "stm32f10x.h"

// 函数声明
void SG90_Init(void);                // 舵机初始化(GPIO+定时器PWM配置)
void SG90_Set_Angle(u16 angle);      // 舵机角度设置(0~180°)

#endif

sg90.c

复制代码
#include "sg90.h"
#include "delay.h"  // 需自行提供延时函数(用于舵机稳定转动)

/************************* 核心参数说明 *************************
SG90要求:
1. PWM周期:20ms(50Hz)
2. 脉宽范围:0.5ms(0°)~ 2.5ms(180°)
STM32F103系统时钟:72MHz(默认配置)
TIM2时钟:APB1总线时钟(最大36MHz,此处72MHz分频后为36MHz)
定时器配置:
- 预分频器(PSC):7199 → 计数频率=36MHz/(7199+1)=5kHz
- 自动重装值(ARR):99 →  PWM周期=(7199+1)*(99+1)/36MHz=20ms
- 脉宽对应值:0.5ms→2.5(5kHz*0.5ms)、2.5ms→12.5(5kHz*2.5ms)
  为避免浮点运算,放大2倍:0.5ms→5、2.5ms→25,对应0°→180°
****************************************************************/

// 舵机初始化:配置GPIO+TIM2_CH1 PWM输出
void SG90_Init(void)
{
    // 1. 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  // GPIOA时钟使能
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);   // TIM2时钟使能
    
    // 2. 配置GPIO引脚(PA0 → TIM2_CH1 复用推挽输出)
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        // 复用推挽输出(定时器PWM专用)
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 3. 配置定时器时基参数
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_TimeBaseStructure.TIM_Period = 99;                 // 自动重装值ARR=99,配合PSC=7199实现20ms周期
    TIM_TimeBaseStructure.TIM_Prescaler = 7199;            // 预分频器PSC=7199
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;// 时钟分频=1
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    
    // 4. 配置定时器PWM输出通道(CH1)
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;       // PWM模式1:计数<CCR时输出有效电平
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 使能输出
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 有效电平为高电平(SG90高电平脉宽有效)
    TIM_OCInitStructure.TIM_Pulse = 5;                      // 初始脉宽对应0°(0.5ms)
    TIM_OC1Init(TIM2, &TIM_OCInitStructure);
    
    // 5. 使能通道预装载和定时器
    TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);       // 使能CCR1预装载(保证脉宽稳定)
    TIM_ARRPreloadConfig(TIM2, ENABLE);                     // 使能ARR预装载
    TIM_Cmd(TIM2, ENABLE);                                  // 启动TIM2
}

// 舵机角度设置:输入0~180°,超出范围自动修正
void SG90_Set_Angle(u16 angle)
{
    u16 ccr_val;
    
    // 1. 角度边界修正
    if(angle > 180) angle = 180;
    if(angle < 0) angle = 0;
    
    // 2. 计算对应CCR1值(线性映射:0°→5,180°→25)
    // 公式:ccr_val = 5 + (25-5)*angle/180 = 5 + angle/9
    ccr_val = 5 + (angle * 20) / 180;
    
    // 3. 更新CCR1值,改变PWM脉宽
    TIM_SetCompare1(TIM2, ccr_val);
    
    // 4. 延时等待舵机稳定转动(SG90转动全程约200ms)
    delay_ms(250);
}

main.c

复制代码
#include "stm32f10x.h"
#include "sg90.h"
#include "delay.h"

int main(void)
{
    // 系统初始化
    SystemInit();          // STM32系统时钟初始化(默认72MHz)
    delay_init();          // 延时函数初始化(需自行实现)
    SG90_Init();           // 舵机初始化
    
    while(1)
    {
        // 测试:0° → 90° → 180° → 90° 循环转动
        SG90_Set_Angle(0);
        delay_ms(1000);
        
        SG90_Set_Angle(90);
        delay_ms(1000);
        
        SG90_Set_Angle(180);
        delay_ms(1000);
        
        SG90_Set_Angle(90);
        delay_ms(1000);
    }
}

关键说明(避坑重点)!!!!

  1. 延时函数:delay.hdelay.c需自行实现(可通过 SysTick 定时器实现毫秒 / 微秒延时),舵机转动需要一定时间,不可省略delay_ms(250)
  2. 供电问题:SG90 在转动时电流较大,若直接由 STM32 的 5V 引脚供电,可能导致单片机复位,建议使用外部电源模块(如 3.7V 锂电池 + 升压模块至 5V)。
  3. 角度精度:SG90 为模拟舵机,存在 ±5° 左右的误差,且不可超过 180° 转动(否则会烧毁内部齿轮)。
  4. 定时器替换:若需更换其他定时器 / 通道(如 TIM3_CH2、PA1),只需修改对应时钟、GPIO 引脚和定时器通道配置即可。

总结

本文介绍了STM32F103C8T6驱动SG90舵机的实现方法。通过定时器生成50Hz(20ms周期)PWM信号,调节0.5-2.5ms脉宽对应0-180°角度控制。详细说明了硬件接线(VIN-5V、GND-GND、PWM-PA0)和软件实现,包括定时器配置、PWM参数计算及角度控制函数。特别强调需注意延时函数实现、外部供电要求、角度精度限制和定时器替换方法。提供完整的工程文件结构(sg90.h/c、main.c)及避坑重点,为舵机控制提供了实用参考方案。

相关推荐
Lxinccode1 天前
ESP32(1) : 安装开发环境Arduino IDE
单片机·嵌入式硬件·esp32·arduinoide
EVERSPIN1 天前
灵动代理mcu单片机机器人解决方案
单片机·嵌入式硬件·机器人
Nautiluss1 天前
一起调试XVF3800麦克风阵列(六)
人工智能·单片机·音频·语音识别·dsp开发·智能硬件
A9better1 天前
嵌入式开发学习日志47——任务创建与就绪列表
单片机·嵌入式硬件·学习
Molesidy1 天前
【FreeRTOS】【MCU】【APM32】基于APM32标准库+FreeRTOS的APM32工程搭建
单片机·嵌入式硬件
先知后行。1 天前
FreeModbus
单片机·嵌入式硬件
cchjyq1 天前
嵌入式按键调参:简洁接口轻松调参(ADC FLASH 按键 屏幕参数显示)
c语言·c++·单片机·mcu·开源·开源软件
xyd陈宇阳1 天前
C 语言宏定义(#define)语法与用法大全
c语言·嵌入式硬件
Jason_zhao_MR1 天前
米尔T113核心板的农机中控屏显方案解析
linux·嵌入式硬件·嵌入式·交互