外设模块学习(一)——sg90数字舵机
SG90 是一款广泛应用的微型伺服舵机,以其小巧、经济和易于控制的特点,成为机器人、航模和各类创意项目中的常客。

一、出厂参数
- 尺寸与重量:约 23×12×29mm,重约 9g。
- 工作电压:推荐 5V,工作范围 4.8V - 6V。
- 扭矩:约 1.8 - 2.5 kg・cm(塑料齿轮版本)。
- 速度:约 0.18 - 0.22 秒 / 60°(无负载)。
- 角度范围:标准为 0° - 180°,也有 360° 连续旋转的特殊版本。
SG90 舵机有两种常见版本:可控角度(0°–180°)和 360° 连续旋转(控速)。两者外观与接线相同,但内部结构、控制逻辑和适用场景不同。
二、核心对比
关于SG90两种版本的舵机,这里给出一张表进行对比:
| 项目 | 可控角度版(0°–180°) | 360° 连续旋转版(控速) |
|---|---|---|
| 内部结构 | 带角度检测电位器,闭环角度控制 | 无角度检测,电机可连续旋转 |
| 控制信号 | 50Hz PWM,周期 20ms | 50Hz PWM,周期 20ms |
| 脉宽 - 功能映射 | 0.5ms≈0°;1.5ms≈90°;2.5ms≈180° | <1.5ms:反向转,脉宽越短速度越快1.5ms:停止>1.5ms:正向转,脉宽越长速度越快 |
| 角度 / 速度能力 | 角度定位,可停在任意目标角度 | 速度控制,无角度定位功能 |
| 适用场景 | 舵面、云台、机械臂关节等需要角度控制的地方 | 轮式机器人驱动、传送带、风扇等需要连续转动和调速的地方 |
| 停止方式 | 保持目标脉宽可锁定角度;断电或停发 PWM 停止 | 发送 1.5ms 脉宽或断电停止 |
| 接线方式 | 三线制:VCC、GND、SIG(信号) | 三线制:VCC、GND、SIG(信号) |
选用建议
- 需要精确定位角度 → 选可控角度版(0°–180°)
- 需要连续旋转并调节速度和方向 → 选 360° 连续旋转版
两种版本外观和引脚定义完全一致,仅控制逻辑不同,使用前需确认版本并调整代码,否则可能出现无法定位或方向相反的情况。本次我们使用的是可控角度的sg90数字舵机。
二、工作原理
SG90 内部是一个完整的闭环控制系统,主要由四部分构成:
- 直流电机:提供原始动力。
- 减速齿轮组:降低电机转速,放大扭矩,驱动输出轴。
- 电位器:与输出轴联动,实时检测当前角度,并将其转化为电信号反馈给控制电路。
- 控制电路:这是舵机的 “大脑”。它接收外部的 PWM 控制信号,与电位器反馈的当前角度进行比较,然后驱动电机正转或反转,直到输出轴达到目标角度。
简单来说,对于我们控制其运行主要在于理解PWM控制信号,通过给SG90舵机输入合适的PWM信号,即可实现对其转动角度的控制或者转速的控制了。
三、控制原理
舵机通过接收特定频率和脉宽的 PWM(脉冲宽度调制)信号来确定目标位置。

- 信号周期:固定为 20ms(即频率 50Hz)。
- 脉宽与角度:在 20ms 的周期内,高电平(ON)的时间(即脉宽)决定了舵机的目标角度。
- 0.5ms 的脉宽 ≈ 0°
- 1.5ms 的脉宽 ≈ 90° (中立位置)
- 2.5ms 的脉宽 ≈ 180°
四、使用场景
由于其体积小、控制简单,SG90 的应用非常广泛:
- 机器人:用于控制关节的转动、机械臂的抓取等。
- 航模 / 车模:控制飞机的升降舵、方向舵,或车辆的转向。
- 云台:调整摄像头的俯仰或水平方向。
- 智能家居:如自动窗帘、小型机械开关。
- 教学与实验:是学习 PWM 控制和闭环系统的经典教具。
五、一般接线方法
SG90 使用标准的三线制接口,线色定义清晰:

- 棕色线 (GND):接地,连接到控制器的 GND。
- 红色线 (VCC):接电源正极,通常为 5V。
- 橙色线 (SIG):信号控制线,连接到控制器(如STM32)的 PWM 输出引脚。
重要提示:接线时务必确认正负极,接反可能会立即烧毁舵机。
六、控制案例:按键控制舵机转动特定角度
6.1 接线方式
| 外设模块 | 引脚连接(STM32F103C8T6) | 接线细节 |
|---|---|---|
| 轻触按键 | PB7 | 按键一端接 PB7,另一端接 GND |
| SG90 舵机 | 信号线 → PA0 | 舵机 GND 接单片机 GND,舵机 5V 接外部 5V 电源(或单片机 5V 引脚) |
| ST-Link V2 | SWDIO → IO 引脚 SWCLK → CLK 引脚 GND → GND 引脚 VCC → 3.3V 引脚 |
严格对应引脚,避免接反电源 |
6.2 案例效果
基于 STM32F103C8T6 微控制器,实现通过按键控制 180 度 SG90 舵机的角度循环切换。
- 初始状态:舵机固定在 90 度
- 按键功能:每按下一次,舵机按 180 度 → 90 度 → 0 度 → 90 度 的顺序循环切换,满足简单机械角度控制场景需求。
6.3 核心代码
6.3.1 PWM信号生成
/*
* @Descripttion: 定时器配置,生成PWM信号
* @Author: JaRyon
* @version:
* @Date: 2025-09-11 10:26:38
*/
// FileName: tim2.c
#include "includes.h"
/**
* @brief TIM2_Init 用于输出PWM信号,提供给SG90舵机
* @param void
* @return void
*/
void TIM2_Init(void)
{
/* 1. 开启时钟 PA0 */
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
/* 2. 配置GPIO工作模式: 复用推挽输出 50MHz */
GPIOA->CRL |= GPIO_CRL_MODE0;
GPIOA->CRL |= GPIO_CRL_CNF0_1;
GPIOA->CRL &= ~GPIO_CRL_CNF0_0;
/* 3. 定时器配置 20ms */
// 3.1 设置预分频值
TIM2->PSC = TIM2_PSC; // 72000000 / 720 = 100000 10^5Hz 1/100000s=1/100ms
// 3.2 设置重装载值
TIM2->ARR = TIM2_ARR; // 20ms / 0.01 = 2000 - 1
TIM2->CR1 |= TIM_CR1_ARPE; // 使能自动重装载预装载
// 3.3 配置计数方向: 向上计数 0,1...
TIM2->CR1 &= ~TIM_CR1_DIR;
// 3.4 设置比较值 0.5~2.5ms中值
TIM2->CCR1 = 150;
// 3.5 配置pwm模式
TIM2->CCMR1 &= ~TIM_CCMR1_CC1S; // 输出模式
TIM2->CCMR1 |= (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1); // PWM模式1
TIM2->CCMR1 &= ~TIM_CCMR1_OC1M_0;
TIM2->CCMR1 |= TIM_CCMR1_OC1PE; // 产生更新事件时写入
// 3.6 配置输出极性和使能
TIM2->CCER &= ~TIM_CCER_CC1P;
TIM2->CCER |= TIM_CCER_CC1E;
}
/**
* @brief TIM2_Start 开启定时器
* @param void
* @return void
*/
void TIM2_Start(void)
{
TIM2->EGR |= TIM_EGR_UG; // 产生更新事件
TIM2->CR1 |= TIM_CR1_CEN; // 使能定时器
}
/**
* @brief TIM2_Close 关闭定时器
* @param void
* @return void
*/
void TIM2_Close(void)
{
TIM2->CR1 &= ~TIM_CR1_CEN; // 使能定时器
TIM2->EGR &= ~TIM_EGR_UG; // 产生更新事件
}
/**
* @brief TIM2_SetCompare 设置pwm占空比
* @param uint16_t compare
* @return void
*/
void TIM2_SetCompare(uint16_t compare)
{
TIM2->CCR1 = compare;
}
6.3.2 舵机角度控制
/*
* @Descripttion: 舵机控制
* @Author: JaRyon
* @version:
* @Date: 2025-09-11 10:28:49
*/
// FileName: servo.c
#include "includes.h"
// 当前舵机角度 默认中值 (内部使用)
static uint8_t current_angle = MID_SERVO_ANGLE;
// 当前角度状态
static uint8_t angle_state = 2; // 1-0° 2-90° 3-180°(初始90°)
/**
* @brief SERVO_Init
* @param void
* @return void
*/
void SERVO_Init(void)
{
TIM2_Init();
TIM2_Start();
SERVO_SetAngle(MID_SERVO_ANGLE);
}
/**
* @brief SERVO_Angle2Compare 角度转换为占空比
* @param uint8_t angle
* @return static uint16_t
* @attention 内部调用
*/
static uint16_t SERVO_Angle2Compare(uint8_t angle)
{
// 角度限幅
if (angle > MAX_SERVO_ANGLE) {angle = MAX_SERVO_ANGLE;}
if (angle < MIN_SERVO_ANGLE) {angle = MIN_SERVO_ANGLE;}
// 90 -> 150 180 -> 250 线性映射y=lx+b
// 0 + delta cycle / delta angle * angle
return (uint16_t)(MIN_TIM2_COMPARE + (uint16_t)(MAX_TIM2_COMPARE - MIN_TIM2_COMPARE) / (uint8_t)(MAX_SERVO_ANGLE - MIN_SERVO_ANGLE) * angle);
}
/**
* @brief SERVO_SetAngle 设置舵机角度
* @param uint8_t angle
* @return void
*/
void SERVO_SetAngle(uint8_t angle)
{
uint16_t compare;
// 角度限幅
if (angle > MAX_SERVO_ANGLE) {angle = MAX_SERVO_ANGLE;}
if (angle < MIN_SERVO_ANGLE) {angle = MIN_SERVO_ANGLE;}
/* 角度更新与转换 */
current_angle = angle;
compare = SERVO_Angle2Compare(angle);
TIM2_SetCompare(compare);
}
/**
* @brief SERVO_GetServoAngle 获取当前舵机角度(0~180)
* @param void
* @return uint8_t
*/
uint8_t SERVO_GetServoAngle(void)
{
return current_angle;
}
/**
* @brief SERVO_NextAngle 切换当前舵机角度(0~180)
* @param void
* @return void
*/
void SERVO_NextAngle(void)
{
// 循环切换角度状态
angle_state++;
if (angle_state > 4)
{
angle_state = 1;
}
// 根据状态设置对应角度
switch (angle_state)
{
case 1:
SERVO_SetAngle(ANGLE_0);
break;
case 2:
SERVO_SetAngle(ANGLE_90);
break;
case 3:
SERVO_SetAngle(ANGLE_180);
break;
case 4:
SERVO_SetAngle(ANGLE_90);
break;
}
}
6.3.3 按键中断处理
void EXTI9_5_IRQHandler(void)
{
// 检查是否是PB7触发的中断
if (EXTI->PR & EXTI_PR_PR7)
{
// 清除中断标志位(必须手动清除)
EXTI->PR |= EXTI_PR_PR7;
// 软件消抖
Delay_ms(10);
// 确认按键按下(PB7接GND,按下时为低电平)
if (!(GPIOB->IDR & GPIO_IDR_IDR7))
{
// 调用舵机角度切换函数(需在其他文件实现)
SERVO_NextAngle();
}
}
}
6.4 完整程序获取
点击链接进入即可查看
七、相关注意事项
- 稳定供电:舵机在启动和承受负载时电流会瞬时增大,建议使用独立、稳定的 5V 电源供电,并确保电源线有足够的电流承载能力。
- 避免堵转:不要强行用手扳动正在工作的舵机输出轴,或让其在到达极限位置后仍长时间通电,这会导致电机堵转、过热,严重时会烧毁舵机。
- 信号频率:严格遵守 50Hz 的控制信号频率(即 20ms 的周期),频率不当会导致舵机抖动、失效或损坏。
- 区分版本:标准的 180° 舵机和 360° 连续旋转舵机的控制逻辑完全不同。360° 版本实际上是将脉宽信号解读为速度和方向(1.5ms 为停止,小于 1.5ms 为一个方向旋转,大于 1.5ms 为另一个方向旋转),它不具备角度定位功能。
稳定供电:舵机在启动和承受负载时电流会瞬时增大,建议使用独立、稳定的 5V 电源供电,并确保电源线有足够的电流承载能力。
2. 避免堵转:不要强行用手扳动正在工作的舵机输出轴,或让其在到达极限位置后仍长时间通电,这会导致电机堵转、过热,严重时会烧毁舵机。
3. 信号频率:严格遵守 50Hz 的控制信号频率(即 20ms 的周期),频率不当会导致舵机抖动、失效或损坏。
4. 区分版本:标准的 180° 舵机和 360° 连续旋转舵机的控制逻辑完全不同。360° 版本实际上是将脉宽信号解读为速度和方向(1.5ms 为停止,小于 1.5ms 为一个方向旋转,大于 1.5ms 为另一个方向旋转),它不具备角度定位功能。
笔者小白,能力有限,以上内容难免存在不足和纰漏,仅供参考,各位阅读时请带着批判性思维学习,遇到问题多查查。同时欢迎各位评论区批评指正。谢谢。
更多推荐

所有评论(0)