STM32——PWM控制舵机

定时器PWM

一、STM32 定时器 PWM 基础理论

1. 什么是 PWM

PWM 全称:脉冲宽度调制 简单说:周期固定,高电平时间可调的方波信号 不靠改变电压大小,靠高电平占整个周期的比例,实现调压、调速、舵机角度控制。

2. 三个核心参数

  • 周期 T:一个高低电平完整循环的时间
  • 频率 f:f = 1 / T,每秒循环多少次
  • 占空比:高电平时间 ÷ 整个周期时间

举例:周期 20ms,高电平 0.5ms → 占空比很小周期 20ms,高电平 2.5ms → 占空比很大

二、STM32 定时器怎么产生 PWM

1. 定时器内部三大关键寄存器

  1. 预分频器 PSC:把 72MHz 系统时钟降频
  2. 自动重装载寄存器 ARR :决定 PWM周期
  3. 捕获比较寄存器 CCR :决定 PWM高电平宽度

2. PWM 周期计算公式

\(T_{PWM} = \frac{(PSC+1)\times(ARR+1)}{f_{TIM}}\)

  • \(f_{TIM}\) 定时器时钟(F103 一般 72MHz)
  • PSC:预分频值
  • ARR:自动重装载值

3. 高电平时间由 CCR 决定

计数器从 0 往上数:

  • 数到 CCR → 电平翻转
  • 数到 ARR → 计数器清零,重新开始

所以:改 ARR → 改 PWM 频率 / 周期 改 CCR → 改占空比、改高电平时间

三、STM32 PWM 两种工作模式

模式 1(最常用,舵机必用)

向上计数

  • 计数器 0 → ARR
  • 当计数器 < CCR:输出高电平
  • 当计数器 > CCR:输出低电平

模式 2

  • 刚好相反:小于 CCR 低电平,大于 CCR 高电平

控制 SG90 一律用:PWM 模式 1

SG90舵机

一、SG90 9g 舵机纯理论原理

1. 内部结构

  • 直流小电机
  • 减速齿轮组(减速增扭)
  • 电位器(角度位置反馈)
  • 控制电路板

2. 工作逻辑

  1. 外部给 固定周期 PWM 信号
  2. 舵机内部检测高电平持续时间
  3. 对比内部电位器当前角度
  4. 自动正转 / 反转,直到角度匹配 PWM 设定值
  5. 到达角度后自锁,保持位置不动

3. 供电与接线

  • 红线:5V 供电
  • 棕线:GND
  • 橙 / 黄线:PWM 信号控制线

二、SG90 标准控制时序

1. 固定周期

SG90 要求 PWM 周期必须严格 20ms对应频率:\(f = 1/20ms = 50Hz\)

2. 高电平时间对应角度(标准 180° 舵机)

高电平时间 对应角度
0.5ms
1.5ms 90°
2.5ms 180°

规律:

  • 高电平越长 → 角度越大
  • 高电平越短 → 角度越小

三、PWM 参数配置理论(适配 SG90)

目标:生成 50Hz 周期 20ms 的 PWMSTM32F103 主频 72MHz

配置思路:

  1. 定时器时钟 72MHz
  2. 分频 + ARR 算出 20ms 周期
  3. 调节 CCR 值,改变高电平 0.5~2.5ms

计算公式对应关系

  • ARR、PSC 固定死 → 保证周期 20ms
  • 只改 CCR → 控制 0°~180° 角度

四、角度与 CCR 值线性关系理论

180° 对应高电平区间:0.5ms ~ 2.5ms差值:\(2.5 - 0.5 = 2ms\)

每 1° 对应时间:\(2ms / 180° \approx 0.0111ms/°\)

可以写出公式:\(高电平时间(ms) = 0.5 + \frac{角度}{180} \times 2.0\)再把时间换算成 CCR 数值,就能直接用代码赋值控制角度。

TIM3 PWM 控制 SG90 舵机

一、工程功能

使用 STM32F103 的 TIM3 通道 2(PB5) 输出 50Hz PWM 信号,控制 SG90 舵机在 0°、90° 之间来回旋转。

二、硬件接线

  • SG90 信号线 → PB5
  • VCC → 5V
  • GND → GND

三、main.c

复制代码
#include "stm32f10x.h"
#include "main.h"
#include "stdio.h"
#include "sg90.h"

// 软件毫秒延时(粗略)
void delay(uint16_t time)
{
	uint16_t i = 0;
	while(time--)
	{
		i = 12000;
		while(i--);
	}
}

int main()
{
	// 中断分组(整个系统只配置一次)
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	// 初始化 PWM + GPIO + 定时器
	SG90_Init();
	
	while(1)
    {
		// 舵机转到 90°,延时1秒
		SG90_Angle(90);
		delay(1000);
		
		// 舵机转到 0°,延时1秒
		SG90_Angle(0);
		delay(1000);
    }
}

主函数逻辑

  1. 配置中断分组
  2. 初始化舵机 PWM 输出
  3. 死循环:
    • 90° → 等待 1 秒
    • 0° → 等待 1 秒
    • 循环往复

四、sg90.c

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

void SG90_Init(void)
{
	// 1. 定义结构体
	GPIO_InitTypeDef GPIO_InitStruct;
	TIM_TimeBaseInitTypeDef TIM_InitStruct;
	TIM_OCInitTypeDef TIMOC_InitStruct;
	
	// 2. 开时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);    // GPIOB时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);    // TIM3时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);     // 复用功能时钟
	
	// 3. 开启 TIM3 部分重映射 → CH2 从 PA7 → PB5
	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
	
	// 4. 配置 PB5 为复用推挽输出(PWM 输出引脚)
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	
	// ==========================
	// 5. 定时器配置:50Hz / 20ms
	// ==========================
	TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	
	// 自动重装载值
	TIM_InitStruct.TIM_Period = 200-1;
	// 预分频
	TIM_InitStruct.TIM_Prescaler = 7200-1;
	
	TIM_TimeBaseInit(TIM3, &TIM_InitStruct);
	
	// ==========================
	// 6. PWM 模式配置
	// ==========================
	TIMOC_InitStruct.TIM_OCMode = TIM_OCMode_PWM1;        // PWM模式1
	TIMOC_InitStruct.TIM_OCPolarity = TIM_OCPolarity_Low;  // 低电平有效
	TIMOC_InitStruct.TIM_OutputState = TIM_OutputState_Enable;
	
	TIM_OC2Init(TIM3, &TIMOC_InitStruct);                  // 通道2
	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);      // 使能预装载

	// 7. 启动定时器
	TIM_Cmd(TIM3, ENABLE);
}

// ==========================
// 角度设置函数
// ==========================
void SG90_Angle(uint16_t angle)
{
	switch(angle)
	{
		case 180: TIM_SetCompare2(TIM3, 175); break;
		case 135: TIM_SetCompare2(TIM3, 180); break;
		case 90 : TIM_SetCompare2(TIM3, 185); break;
		case 45 : TIM_SetCompare2(TIM3, 190); break;
		case 0  : TIM_SetCompare2(TIM3, 195); break;
	}
}

五、核心知识点

1. 定时器 PWM 周期计算(20ms / 50Hz)

你的配置:

  • 预分频:7200-1
  • 重装载:200-1

计算公式:

复制代码
周期 = (7200 × 200) / 72M = 0.02s = 20ms

刚好满足 SG90 舵机要求!

2. PWM 模式 1 作用

  • 计数器从 0 往上数
  • 小于 CCR:低电平
  • 大于 CCR:高电平
  • 配置了 低极性有效 ,所以:CCR 值越小 → 高电平时间越长 → 角度越大

3. 角度与 CCR 对应关系

代码里的实测值:

  • 0° → CCR = 195
  • 90° → CCR = 185
  • 180° → CCR = 175

规律:CCR 越小 → 角度越大

4. 为什么用 PB5?

因为开启了:

复制代码
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);

TIM3_CH2 从 PA7 重映射到 PB5

六、sg90.h 代码

复制代码
#ifndef SG90_H_
#define SG90_H_

#include "stm32f10x.h"

void SG90_Init(void);
void SG90_Angle(uint16_t angle);

#endif

七、程序整体运行流程

  1. 初始化 GPIO、TIM3、PWM
  2. 定时器开始输出 20ms 周期的 PWM
  3. 主循环不断设置 0° / 90°
  4. 舵机根据 PWM 信号旋转角度
相关推荐
菜鸟的日志2 小时前
【嵌入系统】嵌入式学习笔记(一)
windows·笔记·嵌入式硬件·学习·ubuntu·操作系统
电子科技圈3 小时前
四大“门派”围攻边缘及端侧AI SoC市场“光明顶”
人工智能·嵌入式硬件·mcu·物联网·网络安全·音视频·语音识别
CHINA红旗下3 小时前
串口的使用
stm32·单片机·嵌入式硬件
踏着七彩祥云的小丑4 小时前
嵌入式测试学习第2天:欧姆定律 + 功率计算 + 电路单位换算
单片机·嵌入式硬件
BT-BOX4 小时前
Multisim 14.3 安装与汉化指南(附下载链接)
嵌入式硬件·物联网
Hello_Embed4 小时前
串口硬件结构与三种编程方式
笔记·stm32·学习·ai编程
不断提高5 小时前
别再写 while(1) 死循环了,嵌入式开发该换个活法
c语言·嵌入式硬件·嵌入式·状态模式
LCG元5 小时前
STM32实战:基于STM32F103的智能停车场车位引导系统
stm32·单片机·嵌入式硬件
WYH2875 小时前
【STM32 串口完全指南】从轮询到中断再到 DMA,一步步教你搞定串口收发!
stm32·单片机·嵌入式硬件