STM32 使用PWM控制舵机角度(按键调节 + OLED显示

演示视频:https://www.bilibili.com/video/BV1Sq93YRENm/?share_source=copy_web\&vd_source=0e4269581b0bc60d57a80c9a27c98905

一、项目简介

本项目基于 STM32F103 实现通过 PWM 控制舵机角度,每次按键按下,舵机角度增加 30°,并在 OLED 屏幕上显示当前角度数值。适合作为 STM32 PWM 控制舵机的入门实践。

二、硬件准备

硬件模块 用途
STM32F103C8T6 主控芯片
SG90/MG995 舵机 控制角度旋转
0.96寸 OLED(I2C) 实时显示角度
按键模块 控制角度变化
外部电源(推荐) 给舵机供电

三、核心原理

  • 使用 TIM3 输出 PWM 控制舵机

  • 舵机一般使用 50Hz(周期20ms)PWM

    • 0.5ms ≈ 0°,1.5ms ≈ 90°,2.5ms ≈ 180°
  • 通过控制 PWM 的占空比,控制舵机的角度

  • 使用按键触发角度增加,每次 +30°

  • OLED 实时显示当前角度

四、主函数代码

cpp 复制代码
#include "stm32f10x.h"
#include "Delay.h"
#include "OLED.h"
#include "Servo.h"
#include "Key.h"

uint8_t KeyNum;
float Angle;

int main(){
    OLED_Init();          // OLED初始化
    Servo_Init();         // PWM舵机初始化
    Key_Init();           // 按键初始化
    OLED_ShowString(1,1,"Angle:");

    while(1){
        KeyNum = Key_GetNum();         // 获取按键值
        if(KeyNum == 1){               // 按键1被按下
            Angle += 30;               // 增加30°
            if(Angle > 180){
                Angle = 0;             // 超过180°重置
            }
        }
        Servo_SetAngle(Angle);         // 设置舵机角度
        OLED_ShowNum(1,7,Angle,3);     // OLED显示角度
    }
}

五、舵机驱动代码

cpp 复制代码
#include "stm32f10x.h"                  // Device header
#include "PWM.h"

void Servo_Init(void)
{
	PWM_Init();
}

void Servo_SetAngle(float Angle)
{
	PWM_SetCompare2(Angle/180*2000 + 500);

}

六、PWM驱动代码

cpp 复制代码
#include "stm32f10x.h"                  // Device header

void PWM_Init(void){
	//开启RCC时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	//初始化GPIO
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;  
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	
	TIM_InternalClockConfig(TIM2);//定时器上电后默认开启的内部时钟
	//初始化时基单元
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruncture;
	TIM_TimeBaseInitStruncture.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStruncture.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInitStruncture.TIM_Period=20000-1;  //ARR
	TIM_TimeBaseInitStruncture.TIM_Prescaler=72-1;  //PSC
	TIM_TimeBaseInitStruncture.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruncture);
	
	//OC输出比较初始化
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse=0;  //CCR
	TIM_OC2Init(TIM2,&TIM_OCInitStructure);
	
	//启动定时控制器
	TIM_Cmd(TIM2,ENABLE);
	
}

void PWM_SetCompare2(uint16_t Compare){
	TIM_SetCompare2(TIM2,Compare);
}

七、总结

本项目通过 PWM 控制舵机,结合 OLED 显示和按键交互,实现了一个经典的嵌入式入门项目,适用于机器人、机械臂、舵机教学等场景。

相关推荐
君王的羔羊3 小时前
STM32CUBEMX安装离线库
stm32·cubemx
DIY机器人工房7 小时前
要解决 ESP32 与 STM32 之间 LoRa 通信无应答的问题,可从以下硬件、软件、参数匹配三个维度逐一排查:
stm32·单片机·嵌入式硬件·lora·嵌入式·diy机器人工房
qq_401700417 小时前
STM32的存储起始地址和运行起始地址为什么一样
stm32·单片机·嵌入式硬件
-Excalibur-9 小时前
形象解释关于TCP/IP模型——层层封装MAC数据帧的过程
linux·c语言·网络·笔记·单片机·网络协议·tcp/ip
点灯小铭10 小时前
基于单片机的楼道声光人体红外智能控制灯设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
hazy1k10 小时前
51单片机基础-红外遥控(NEC协议)
stm32·单片机·嵌入式硬件·51单片机·1024程序员节
子不语18011 小时前
STM32——按钮实验
stm32·单片机·嵌入式硬件
牛马大师兄12 小时前
STM32实现低功耗管理使用配置知识梳理笔记
笔记·stm32·单片机·嵌入式硬件·物联网·低功耗
大志若愚YYZ13 小时前
STM32——使用定时器+按键中断来实现长按事件检测触发
stm32·单片机·嵌入式硬件
朱嘉鼎14 小时前
ARM内部寄存器
arm开发·单片机·嵌入式硬件