本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:STM32是基于ARM Cortex-M内核的主流嵌入式微控制器,广泛用于电子设备与机器人开发。SG90舵机是一种低成本、高精度的小型伺服电机,适用于模型飞机、机器人手臂等角度控制项目。本文档提供完整的STM32控制SG90舵机的代码实现,涵盖PWM信号生成、GPIO配置、定时器设置、HAL库使用、Keil5开发环境搭建等核心内容。通过本项目实战,初学者可快速掌握嵌入式系统中舵机控制的关键技术,并具备拓展多舵机控制与反馈系统的能力。
嵌入式初学者STM32控制SG90舵机相关代码

1. 嵌入式系统与STM32控制SG90舵机概述

嵌入式系统是以应用为中心,以计算机技术为基础,具备高度专业化与实时性的软硬件结合系统,广泛应用于工业控制、智能家居、机器人等领域。随着自动化需求的不断提升,嵌入式平台对执行机构(如SG90舵机)的精准控制能力成为关键。

STM32系列微控制器基于ARM Cortex-M内核,凭借高性能、低功耗、丰富的外设资源及良好的生态支持,成为嵌入式开发的热门选择。在控制SG90舵机时,STM32可通过定时器输出精确的PWM信号,实现舵机角度的稳定调节。

本章将为读者建立嵌入式系统与舵机控制的基本认知,引出STM32在该场景下的核心优势,并为后续章节的技术实现打下理论基础。

2. STM32微控制器基础与SG90舵机工作原理

2.1 STM32微控制器的体系结构

2.1.1 Cortex-M内核与STM32芯片选型

STM32系列微控制器基于ARM Cortex-M内核架构,具有高性能、低功耗、实时性强等特点,广泛应用于工业控制、消费电子和物联网等领域。Cortex-M系列包括M0、M3、M4、M7等多个子系列,分别适用于不同性能需求的场景。

在控制SG90舵机的项目中,我们通常选用STM32F1系列(基于Cortex-M3)或STM32F4系列(基于Cortex-M4),它们具备丰富的定时器资源和GPIO接口,能够高效生成PWM信号,适合舵机控制任务。

芯片系列 内核架构 主频(MHz) 定时器资源 适用场景
STM32F1 Cortex-M3 72 通用定时器(TIMx) 基础控制、教学项目
STM32F4 Cortex-M4 168 高级定时器(TIM1/TIM8) 多舵机、高性能控制
STM32L4 Cortex-M4 80 低功耗定时器 电池供电系统

在实际选型中,还需考虑引脚数量、外设集成度、开发环境支持等因素。例如,若需控制多个SG90舵机,建议选择具有多路PWM输出功能的芯片,如STM32F407VGT6。

2.1.2 内存映射与寄存器配置基础

STM32的内存映射结构清晰,分为代码区(Flash)、SRAM、外设寄存器区等。开发者可通过访问寄存器地址来配置GPIO、定时器等外设。

以GPIO配置为例,STM32的GPIO寄存器主要包括:

  • GPIOx_MODER :模式寄存器,用于设置引脚为输入、输出、复用等功能。
  • GPIOx_OTYPER :输出类型寄存器,设置为推挽或开漏。
  • GPIOx_OSPEEDR :输出速度寄存器,影响引脚的响应频率。
  • GPIOx_PUPDR :上下拉寄存器,用于内部上拉或下拉电阻设置。
  • GPIOx_IDR :输入数据寄存器。
  • GPIOx_ODR :输出数据寄存器。

以下是一个GPIO配置示例,设置PA5为推挽输出,控制LED闪烁:

// 启用GPIOA时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;

// 设置PA5为通用推挽输出,速度为50MHz
GPIOA->CRL &= ~(0xF << (5 * 4));   // 清除原有配置
GPIOA->CRL |= (0x1 << (5 * 4));    // 设置为推挽输出
GPIOA->CRL |= (0x3 << ((5 * 4) + 2)); // 设置速度为50MHz

// 控制PA5输出高电平
GPIOA->BSRR = GPIO_BSRR_BS5;

// 延时
for(volatile uint32_t i = 0; i < 1000000; i++);

// 控制PA5输出低电平
GPIOA->BSRR = GPIO_BSRR_BR5;

逐行解读分析:

  1. RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
    启用GPIOA的时钟,确保后续配置生效。

  2. GPIOA->CRL &= ~(0xF << (5 * 4));
    清除PA5对应的4位配置位,准备重新设置。

  3. GPIOA->CRL |= (0x1 << (5 * 4));
    设置PA5为通用输出模式。

  4. GPIOA->CRL |= (0x3 << ((5 * 4) + 2));
    设置输出速度为50MHz,以适应高频PWM信号。

  5. GPIOA->BSRR = GPIO_BSRR_BS5;
    设置PA5为高电平,点亮LED。

  6. for(volatile uint32_t i = 0; i < 1000000; i++);
    简单的软件延时循环,用于观察LED闪烁。

  7. GPIOA->BSRR = GPIO_BSRR_BR5;
    设置PA5为低电平,熄灭LED。

通过直接操作寄存器,可以实现高效、灵活的外设控制。在舵机控制中,这种方式常用于初始化PWM输出通道。

2.2 SG90舵机的基本工作原理

2.2.1 舵机内部结构与反馈机制

SG90是一种微型模拟舵机,广泛用于机器人、遥控模型等小型设备中。其核心结构包括直流电机、减速齿轮组、位置传感器(电位器)和控制电路。

其工作原理如下:

graph TD
    A[PWM输入信号] --> B{控制电路}
    B --> C[电机驱动]
    C --> D[减速齿轮]
    D --> E[电位器反馈]
    E --> B
    B --> F[角度输出]
  1. 控制电路 接收来自STM32的PWM信号,将其与电位器反馈的电压进行比较。
  2. 若两者不一致, 电机驱动 部分将启动电机,带动 减速齿轮组 旋转。
  3. 电位器 作为角度反馈元件,将当前角度转化为电压信号返回给控制电路。
  4. 当反馈电压与PWM信号对应的期望电压一致时,电机停止,舵机角度稳定。

这种闭环反馈机制保证了SG90舵机的高精度角度控制。

2.2.2 PWM信号对角度控制的影响

SG90舵机通过接收标准的PWM信号实现角度控制。其标准控制参数如下:

参数 值范围
PWM频率 50Hz(周期20ms)
高电平宽度 0.5ms ~ 2.5ms
对应角度 0° ~ 180°

例如:
- 0.5ms → 0°
- 1.5ms → 90°
- 2.5ms → 180°

以下是生成50Hz PWM信号的代码示例(基于STM32 HAL库):

// 初始化定时器通道
htim3.Instance = TIM3;
htim3.Init.Prescaler = 83;            // 预分频值,系统时钟84MHz / (83+1) = 1MHz
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 19999;            // 自动重载值,对应周期20ms
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

// 设置占空比为7.5%(对应1.5ms脉宽)
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 1500);

逐行解读分析:

  1. htim3.Instance = TIM3;
    指定使用TIM3定时器。

  2. htim3.Init.Prescaler = 83;
    系统时钟为84MHz,设置预分频为83,则定时器时钟为1MHz(即1us/计数)。

  3. htim3.Init.Period = 19999;
    自动重载值为19999,对应20ms周期(20ms = 20000 × 1us)。

  4. HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
    启动PWM输出通道1。

  5. __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 1500);
    设置比较值为1500,即高电平持续1.5ms,对应舵机角度90°。

通过改变比较值,可以实现舵机角度的精确控制。

2.3 STM32与SG90舵机的连接方式

2.3.1 引脚定义与电源要求

SG90舵机通常采用3线接口:

颜色 功能 推荐连接
棕色 GND 开发板GND
红色 VCC 5V电源(注意最大电流)
橙色 PWM信号 STM32的PWM输出引脚

在实际连接中,需注意以下几点:

  1. 电源供电 :SG90的工作电压为4.8V ~ 6V,通常使用5V供电。建议使用稳压电源或USB电源,避免电压波动。
  2. 电流需求 :空载电流约10mA,堵转电流可达500mA以上。若控制多个舵机,应考虑使用外部电源或稳压模块。
  3. 信号引脚 :选择STM32具有PWM功能的引脚,如PA6(TIM3_CH1)、PB5(TIM3_CH2)等。

2.3.2 接口电路设计中的注意事项

在设计接口电路时,建议加入以下元件以提高稳定性和安全性:

  • 限流电阻 :在信号线中加入100Ω电阻,防止过流损坏MCU。
  • 滤波电容 :在VCC与GND之间加入100nF陶瓷电容,滤除高频噪声。
  • 稳压模块 :若使用电池供电,建议使用LM1117或AMS1117稳压模块提供稳定5V电压。
  • 反向保护二极管 :防止电源接反烧毁舵机。

以下是一个推荐的接口电路设计表格:

元件 作用
R1 100Ω 信号线限流
C1 100nF 电源滤波
U1 AMS1117-5.0 稳压模块
D1 1N4001 反向保护二极管

连接示意图如下:

graph LR
    A[STM32] -->|PWM| B[SG90舵机]
    C[5V电源] -->|VCC| B
    D[GND] -->|GND| B
    C --> E[AMS1117稳压]
    E --> F[STM32 VDD]

在实际布线中,建议将舵机电源与MCU电源分开供电,避免电流波动影响系统稳定性。

通过以上电路设计和连接方式,可以安全可靠地实现STM32对SG90舵机的控制,为后续的PWM信号生成和角度控制打下坚实基础。

3. STM32 GPIO配置与PWM信号生成机制

3.1 GPIO端口的基本配置流程

3.1.1 端口模式设置与时钟使能

STM32微控制器的GPIO端口配置是嵌入式系统开发中的基础环节,它决定了引脚的功能和行为。GPIO端口配置的第一步是 使能对应的时钟 ,因为STM32采用外设时钟门控机制,未使能时钟的外设将无法操作。

以STM32F4系列为例,若要配置GPIOA的某个引脚(例如PA8)为输出功能,首先需要在RCC寄存器中使能GPIOA的时钟:

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;

此代码行的作用是向AHB1ENR寄存器写入GPIOA的使能位(RCC_AHB1ENR_GPIOAEN),从而激活GPIOA模块的时钟。这是所有GPIO操作的前提。

接下来是 模式设置 ,即定义引脚的功能。GPIO的模式包括输入模式、通用输出模式、复用功能模式和模拟模式四种。例如,将PA8配置为复用推挽输出模式,以便连接定时器输出PWM信号:

GPIOA->MODER &= ~(3U << (8 * 2));     // 清除原有模式设置
GPIOA->MODER |= (2U << (8 * 2));      // 设置为复用模式

上述代码中, MODER 寄存器用于设置每个引脚的模式,每个引脚占两个位。通过位掩码操作清空原有设置,再写入模式值(2代表复用模式)。

3.1.2 推挽输出与复用功能配置

GPIO端口的输出类型决定了信号的驱动能力和电气特性。常见的输出类型有 推挽输出 (Push-Pull)和 开漏输出 (Open-Drain)。推挽输出具有较强的驱动能力,适用于高速信号输出;而开漏输出常用于需要上拉电阻的场合,如I²C通信。

继续以PA8为例,将其配置为推挽输出:

GPIOA->OTYPER &= ~(1U << 8);   // 设置为推挽输出

OTYPER 寄存器控制输出类型,写0表示推挽,写1表示开漏。

此外,还需要设置 输出速度 (OSPEEDR)和 上拉/下拉电阻 (PUPDR)。例如:

GPIOA->OSPEEDR |= (3U << (8 * 2));    // 设置为高速输出
GPIOA->PUPDR &= ~(3U << (8 * 2));     // 禁用上拉/下拉
  • OSPEEDR 用于设置引脚的输出速度,值越大驱动能力越强,但功耗也越高。
  • PUPDR 用于设置上拉、下拉或无上拉下拉状态。

最后,若该引脚用于复用功能(如PWM输出),还需配置 复用功能寄存器 (AFR):

GPIOA->AFR[1] &= ~(0xFU << ((8 - 8) * 4));  // 清除AFR高寄存器中PA8的复用设置
GPIOA->AFR[1] |= (1U << ((8 - 8) * 4));     // 设置为AF1(对应TIM1_CH1)

这里使用的是 AFR[1] 寄存器,因为PA8属于高寄存器位(8~15)。每个引脚占4位,因此通过位移计算定位到对应位置。AF1对应的是定时器1通道1的复用功能。

3.2 PWM信号生成原理

3.2.1 定时器的基本结构与工作模式

STM32的PWM信号生成依赖于其 通用定时器 (如TIM2、TIM3、TIM4等)或 高级定时器 (如TIM1、TIM8)。这些定时器通过计数器、自动重载寄存器(ARR)和捕获/比较寄存器(CCR)来实现PWM波形的生成。

定时器的基本工作流程如下:

  1. 时钟源输入 :定时器接收系统时钟(如84MHz)作为输入。
  2. 预分频器 (TIMx_PSC):对输入时钟进行分频,降低计数频率。
  3. 计数器 (TIMx_CNT):根据预分频后的频率进行递增或递减计数。
  4. 自动重载寄存器 (TIMx_ARR):当计数器达到ARR值时,产生溢出并重置计数器。
  5. 比较寄存器 (TIMx_CCRx):在计数过程中与当前计数值比较,决定PWM的占空比。

PWM的工作模式主要分为 边沿对齐模式 (Edge-Aligned)和 中心对齐模式 (Center-Aligned)。边沿对齐模式用于大多数应用,而中心对齐模式常用于电机控制,以减少谐波干扰。

以下是一个边沿对齐模式下的PWM波形生成流程图(使用Mermaid语法):

graph TD
    A[时钟输入] --> B[预分频器]
    B --> C[计数器递增]
    C --> D{是否等于ARR?}
    D -->|是| E[重置计数器]
    D -->|否| F{是否等于CCR?}
    F -->|是| G[电平翻转]
    F -->|否| H[继续计数]
    E --> C
    G --> H

3.2.2 预分频与自动重载值的计算方法

PWM信号的频率由以下公式决定:

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

其中:

  • $f_{TIMxCLK}$:定时器的输入时钟频率(如84MHz)
  • $PSC$:预分频系数
  • $ARR$:自动重载寄存器值

例如,若希望生成50Hz的PWM信号,且$f_{TIMxCLK} = 84MHz$,可以设定:

  • $PSC = 83$(即分频84)
  • $ARR = 19999$(即周期为20000)

代入公式验证:

f_{PWM} = \frac{84000000}{(83 + 1) \times (19999 + 1)} = \frac{84000000}{84 \times 20000} = 50Hz

占空比则由比较寄存器$CCR$控制:

Duty = \frac{CCR}{ARR + 1}

例如,若$CCR = 500$,则占空比为:

\frac{500}{20000} = 2.5\%

这正好对应SG90舵机的0度控制信号。

3.3 STM32实现标准50Hz PWM信号

3.3.1 定时器参数配置实例

在STM32中,使用HAL库或直接寄存器操作都可以实现PWM信号的生成。下面以TIM3通道1为例,展示如何配置定时器生成50Hz的PWM信号:

// 1. 使能时钟
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;

// 2. 配置定时器基本参数
TIM3->PSC = 83;              // 预分频为84
TIM3->ARR = 19999;           // 自动重载值为20000,周期为50Hz

// 3. 配置PWM模式1(边沿对齐,向上计数)
TIM3->CCMR1 &= ~TIM_CCMR1_OC1M;
TIM3->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;  // PWM Mode 1
TIM3->CCMR1 |= TIM_CCMR1_OC1PE;  // 使能预装载寄存器

// 4. 设置比较值(占空比)
TIM3->CCR1 = 500;  // 初始占空比为2.5%

// 5. 启动定时器
TIM3->CR1 |= TIM_CR1_CEN;

// 6. 启动PWM输出
TIM3->CCER |= TIM_CCER_CC1E;

逐行解释如下:

  • 第1行 :使能TIM3的APB1总线时钟。
  • 第2行 :设置预分频器和自动重载寄存器,确定PWM频率。
  • 第3行 :配置PWM模式为Mode1(边沿对齐,向上计数),并启用预装载寄存器以确保更新平滑。
  • 第4行 :设置比较寄存器值,决定初始占空比。
  • 第5行 :启动定时器开始计数。
  • 第6行 :启用通道1的PWM输出。

3.3.2 PWM占空比与舵机角度的初步映射

SG90舵机的标准控制信号为周期20ms(50Hz),脉宽范围为0.5ms(0°)至2.5ms(180°)。对应占空比范围为2.5%至12.5%。

我们可以建立一个线性映射函数,将角度转换为CCR值:

CCR = \left(\frac{angle}{180}\right) \times (12.5 - 2.5) \times (ARR + 1) / 100 + 2.5 \times (ARR + 1) / 100

简化后:

CCR = \left(500 + \frac{angle \times 1000}{180}\right)

例如:

  • 0°: 500
  • 90°: 1000
  • 180°: 1500

我们可以编写一个函数实现角度到CCR的映射:

void set_servo_angle(uint16_t angle) {
    uint16_t ccr = 500 + (angle * 1000) / 180;
    TIM3->CCR1 = ccr;
}

此函数接受角度参数,并将其转换为合适的CCR值,实现对SG90舵机的角度控制。

总结

本章深入讲解了STM32 GPIO的配置流程,包括时钟使能、模式设置、输出类型与复用功能配置,并详细分析了PWM信号的生成原理,涵盖定时器结构、预分频与自动重载值的计算方法。最后通过实际代码演示了如何在STM32上实现标准50Hz的PWM信号输出,并初步建立了角度与占空比之间的映射关系,为后续章节中SG90舵机的精确控制打下坚实基础。

4. SG90舵机控制的软件实现与调试

在嵌入式系统中,控制SG90舵机的关键在于将角度指令准确转换为对应的PWM脉冲宽度,并通过STM32微控制器生成精确的PWM信号。本章将从角度到脉宽的映射函数设计开始,逐步介绍Keil5开发环境的搭建与配置,以及在调试过程中如何利用示波器、中断控制和延时函数等工具进行波形分析与优化。通过本章内容,读者将掌握从理论模型到实际工程实现的完整流程。

4.1 舵机角度到脉宽的映射函数设计

SG90舵机的控制依赖于PWM信号的占空比,通常其控制信号为50Hz频率(即周期20ms),脉冲宽度在0.5ms到2.5ms之间,对应0°到180°的角度控制。因此,如何将角度值精确映射为对应的脉宽值是实现控制的核心。

4.1.1 数学建模与线性映射方法

SG90的标准控制信号参数如下:

角度(°) 脉冲宽度(ms)
0 0.5
90 1.5
180 2.5

由此可建立线性映射模型:

\text{pulse_width} = \frac{2.0}{180} \times angle + 0.5

其中, angle 的取值范围为[0, 180]。为了适应STM32的定时器配置,需将 pulse_width 转换为定时器的计数值。假设定时器的时钟频率为 TIMx_CLK ,预分频系数为 TIMx_Prescaler ,则计数周期为:

\text{cnt_period} = \frac{TIMx_CLK}{Prescaler \times 50} - 1

而脉冲宽度对应的计数值为:

\text{pulse_cnt} = \left( \frac{pulse_width}{20} \right) \times cnt_period

4.1.2 角度转换函数的C语言实现

以下是一个基于上述模型的C语言函数实现,用于将角度转换为定时器的比较值(CCR值):

#include "stm32f4xx_hal.h"

#define PWM_PERIOD_MS 20.0f       // PWM周期为20ms
#define MIN_PULSE_MS 0.5f         // 0度对应的脉冲宽度
#define MAX_PULSE_MS 2.5f         // 180度对应的脉冲宽度

uint32_t map_angle_to_pulse(TIM_HandleTypeDef *htim, float angle) {
    // 限制角度范围
    if (angle < 0) angle = 0;
    if (angle > 180) angle = 180;

    // 计算脉冲宽度(ms)
    float pulse_width = (MAX_PULSE_MS - MIN_PULSE_MS) * (angle / 180.0f) + MIN_PULSE_MS;

    // 获取定时器的时钟频率
    uint32_t timer_clock = HAL_RCC_GetPCLK1Freq();
    uint32_t prescaler = htim->Instance->PSC;
    uint32_t period = htim->Instance->ARR;

    // 计算对应脉冲宽度的计数值(CCR值)
    uint32_t pulse_cnt = (uint32_t)((pulse_width / PWM_PERIOD_MS) * (period + 1));

    return pulse_cnt;
}
代码逻辑分析:
  • 第1~5行 :定义常量,包括PWM周期、最小与最大脉冲宽度。
  • 第7~13行 :函数接收角度值,将其限制在0~180之间。
  • 第16行 :根据线性关系计算对应角度的脉冲宽度。
  • 第19~21行 :获取定时器的时钟频率、预分频值和自动重载值。
  • 第24行 :计算脉冲宽度对应的计数值,用于设置比较寄存器(CCR)。

此函数可在主程序中调用,配合HAL库设置定时器的通道比较值,实现舵机角度控制。

4.2 Keil5开发环境搭建与工程配置

Keil5是STM32开发中广泛使用的集成开发环境(IDE),支持项目管理、代码编译、调试等功能。本节将介绍如何在Keil5中搭建基于STM32 HAL库的开发环境。

4.2.1 工程创建与STM32 HAL库引入

  1. 安装Keil MDK-ARM
    下载并安装Keil MDK-ARM V5版本,并安装对应芯片的器件支持包(如STM32F4系列)。

  2. 使用STM32CubeMX生成初始化代码
    使用STM32CubeMX配置GPIO、定时器等外设,选择PWM输出模式,并生成Keil5项目。

  3. 导入工程至Keil5
    打开Keil5,选择 Project -> Open Project ,加载生成的 .uvprojx 文件。

  4. HAL库引入与配置
    STM32CubeMX生成的代码中已包含HAL库初始化函数,如 HAL_Init() SystemClock_Config() 等。用户需在 main.c 中添加自己的逻辑代码。

4.2.2 编译选项与调试接口设置

  1. 编译器配置
    在Keil5中,点击 Options for Target -> C/C++ ,设置宏定义如 USE_HAL_DRIVER STM32F407xx 等,确保HAL库正确启用。

  2. 调试接口配置
    Options for Target -> Debug 中,选择调试器(如ST-Link),并启用SW调试模式。

  3. 烧录与调试
    点击 Download 按钮将程序烧录至STM32,点击 Debug 进入调试模式,可设置断点、查看寄存器、变量值等。

工程结构示意图(mermaid流程图):
graph TD
    A[STM32CubeMX配置] --> B[生成Keil工程]
    B --> C[Keil5导入工程]
    C --> D[配置编译器选项]
    D --> E[设置调试接口]
    E --> F[编译与调试]

4.3 调试技术与波形分析

在实际调试中,确保生成的PWM波形符合预期是关键。本节将介绍如何使用示波器查看波形、中断控制与延时函数的使用技巧。

4.3.1 示波器辅助查看PWM波形

实验步骤:
  1. 连接示波器探头
    将示波器探头连接到STM32输出PWM信号的引脚(如PA0)。

  2. 配置定时器输出通道
    在CubeMX中配置TIM2_CH1为PWM输出模式,频率为50Hz,占空比可变。

  3. 运行程序并观察波形
    使用以下代码启动PWM输出:

// 启动定时器PWM输出
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

// 设置初始角度为90度
uint32_t pulse = map_angle_to_pulse(&htim2, 90.0f);
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pulse);
波形分析要点:
  • 频率验证 :周期应为20ms,对应50Hz。
  • 脉冲宽度验证 :90度时应为1.5ms,对应约7.5%占空比。
  • 稳定性验证 :观察波形是否抖动或失真,确保定时器配置无误。

4.3.2 中断控制与延时函数的使用技巧

在控制舵机时,常需要等待一段时间让舵机完成转动。此时可使用延时函数或中断方式实现。

示例:使用HAL_Delay实现延时
// 设置角度为0度
pulse = map_angle_to_pulse(&htim2, 0.0f);
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pulse);
HAL_Delay(1000);  // 等待1秒

// 设置角度为180度
pulse = map_angle_to_pulse(&htim2, 180.0f);
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pulse);
HAL_Delay(1000);  // 再等待1秒
使用中断实现精确控制

若需响应外部事件(如按钮按下改变角度),可使用外部中断方式:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if (GPIO_Pin == BUTTON_PIN) {
        static float angle = 0.0f;
        angle += 10.0f;
        if (angle > 180.0f) angle = 0.0f;
        uint32_t pulse = map_angle_to_pulse(&htim2, angle);
        __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pulse);
    }
}
参数说明:
  • HAL_Delay() :基于SysTick定时器实现的毫秒级延时。
  • HAL_GPIO_EXTI_Callback() :外部中断回调函数,响应按钮事件。
  • __HAL_TIM_SET_COMPARE() :设置比较寄存器值,改变PWM占空比。
调试技巧总结:
技术手段 优点 缺点
示波器观测 直观验证波形 需要硬件设备
HAL_Delay 简单易用 会阻塞主程序运行
中断控制 实时响应外部事件 需处理中断优先级与嵌套

本章详细介绍了SG90舵机控制的软件实现流程,包括角度到脉宽的映射函数设计、Keil5工程搭建与配置,以及PWM波形调试与中断控制等关键技术。下一章将在此基础上,深入探讨HAL库与LL库的性能对比、电源管理设计、多舵机控制等进阶内容。

5. 嵌入式系统控制SG90的进阶实践与扩展应用

5.1 HAL库与LL库控制方式对比

STM32微控制器的开发中,开发者通常面临HAL(Hardware Abstraction Layer)库与LL(Low Layer)库之间的选择。这两种库在使用方式、性能表现和可移植性方面有显著差异。

5.1.1 抽象层与底层操作的性能差异

HAL库封装了大部分寄存器级操作,提供了面向对象的API接口,极大提升了开发效率和代码可移植性。例如,使用HAL库启动PWM信号可以简单如下:

// 使用HAL库启动PWM通道
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

而LL库则更贴近硬件寄存器,允许开发者直接配置定时器和GPIO寄存器,从而获得更高的执行效率。例如,使用LL库配置PWM如下:

// 使用LL库启动PWM通道
LL_TIM_CC_EnableChannel(TIM3, LL_TIM_CHANNEL_CH1);
LL_TIM_EnableCounter(TIM3);
特性 HAL库 LL库
开发效率 高,API封装完整 低,需手动配置寄存器
性能 稍低,存在抽象层开销 高,直接操作硬件
可移植性 高,适用于多种STM32系列 低,需针对芯片修改配置
学习曲线 平缓 陡峭

5.1.2 选择适合项目的开发方式

对于快速原型开发或跨平台移植需求,推荐使用HAL库;而对于对性能敏感、资源受限或需极致优化的项目,LL库是更优选择。

5.2 电源管理与硬件安全设计

在嵌入式系统中,SG90舵机的驱动离不开稳定的电源支持。不当的电源设计可能导致舵机失控、烧毁甚至影响整个系统运行。

5.2.1 电压稳定与过流保护方案

SG90舵机典型工作电压为4.8V~6V,建议使用稳压模块(如AMS1117-5V)为舵机供电。此外,应在电源输入端加入保险电阻或自恢复保险丝,防止过流损坏系统:

graph TD
    A[外部电源] --> B(稳压模块)
    B --> C[舵机供电]
    C --> D{过流检测}
    D -- 正常 --> E[正常工作]
    D -- 异常 --> F[切断电源]

5.2.2 多舵机电流分配与散热考虑

多个SG90同时运行时,总电流可能超过500mA,建议使用独立的电源管理模块(如DC-DC降压模块)为舵机组供电。同时,应在PCB布局中为电源部分预留散热区域,必要时加装散热片。

5.3 多舵机扩展控制与机器人应用

5.3.1 多路PWM信号同步生成

STM32具备多个定时器,可同时输出多路PWM信号。例如,使用TIM3和TIM4分别控制两个舵机:

// 初始化TIM3和TIM4
MX_TIM3_Init();  // 舵机1控制
MX_TIM4_Init();  // 舵机2控制

// 启动PWM输出
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1);

通过设置多个定时器通道,可以实现多个舵机角度的独立控制,且互不干扰。

5.3.2 在机器人关节控制中的实践应用

在六足机器人或机械臂项目中,每个关节通常由一个SG90舵机驱动。通过STM32控制各关节角度,可实现如步态行走、抓取等动作。

// 示例:设置机械臂各关节角度
set_servo_angle(0, 90);  // 基座旋转角度
set_servo_angle(1, 45);  // 大臂抬升角度
set_servo_angle(2, 135); // 小臂弯曲角度

其中 set_servo_angle() 函数实现角度到PWM脉宽的映射逻辑,是舵机控制的核心函数之一。

5.4 嵌入式系统未来发展趋势

5.4.1 智能控制与传感器融合的前景

未来嵌入式控制系统将越来越多地引入传感器数据(如IMU、红外、超声等),实现对SG90舵机的闭环控制。例如通过陀螺仪反馈角度,实现自平衡机器人。

graph LR
    A[传感器数据] --> B(控制器)
    B --> C[调整PWM信号]
    C --> D[舵机角度修正]
    D --> A

5.4.2 STM32在IoT与自动化领域的潜在应用

随着STM32系列集成Wi-Fi、蓝牙、CAN等模块,其在IoT远程控制、工业自动化等领域的应用潜力巨大。例如通过MQTT协议远程控制舵机角度:

// 接收来自云端的角度指令
void on_mqtt_message(char* topic, char* payload) {
    int angle = atoi(payload);
    set_servo_angle(0, angle);
}

这将使得基于STM32的SG90舵机控制系统具备远程控制、状态反馈、数据上传等能力,真正实现“智能+控制”的融合。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:STM32是基于ARM Cortex-M内核的主流嵌入式微控制器,广泛用于电子设备与机器人开发。SG90舵机是一种低成本、高精度的小型伺服电机,适用于模型飞机、机器人手臂等角度控制项目。本文档提供完整的STM32控制SG90舵机的代码实现,涵盖PWM信号生成、GPIO配置、定时器设置、HAL库使用、Keil5开发环境搭建等核心内容。通过本项目实战,初学者可快速掌握嵌入式系统中舵机控制的关键技术,并具备拓展多舵机控制与反馈系统的能力。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐