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)及避坑重点,为舵机控制提供了实用参考方案。

相关推荐
SundayBear10 小时前
零基础入门MQTT协议
c语言·单片机
嗯嗯=11 小时前
STM32单片机学习篇9
stm32·单片机·学习
小范馆15 小时前
ESP各模组的引脚图-小智接线图
stm32
松涛和鸣16 小时前
DAY63 IMX6ULL ADC Driver Development
linux·运维·arm开发·单片机·嵌入式硬件·ubuntu
想放学的刺客19 小时前
单片机嵌入式试题(第23期)嵌入式系统电源管理策略设计、嵌入式系统通信协议栈实现要点两个全新主题。
c语言·stm32·单片机·嵌入式硬件·物联网
猫猫的小茶馆19 小时前
【Linux 驱动开发】五. 设备树
linux·arm开发·驱动开发·stm32·嵌入式硬件·mcu·硬件工程
YouEmbedded20 小时前
解码内部集成电路(IIC)与OLED屏
stm32·0.96寸oled·硬件iic·软件模拟iic·图片取模·汉字取模
jghhh0120 小时前
基于上海钜泉科技HT7017单相计量芯片的参考例程实现
科技·单片机·嵌入式硬件
恶魔泡泡糖21 小时前
51单片机外部中断
c语言·单片机·嵌入式硬件·51单片机
意法半导体STM3221 小时前
【官方原创】如何基于DevelopPackage开启安全启动(MP15x) LAT6036
javascript·stm32·单片机·嵌入式硬件·mcu·安全·stm32开发