大数跨境
0
0

STM32F407基础教程14——PWM之舵机控制

STM32F407基础教程14——PWM之舵机控制 Easy单片机
2025-11-09
0
导读:SG90舵机使用方法和程序控制

1. 引言

舵机,全称为伺服电机(Servo Motor),是一种能够精确控制角度位置的电机。它不仅仅是一个简单的电机,而是集成了电机、传感器和控制电路的完整闭环控制系统。广泛应用于机械臂关节转向控制等。

2. 舵机的基本工作原理

      本文介绍的舵机型号为SG90,转动角度为0~180°(左90°,右90°)。外观和引脚定义如下。尺寸约为22×12×30mm,重量仅9克。虽然体积小巧,但其内部结构却相当精密包括无刷电机、减速齿轮组、编码器和控制电路。

重要提示:舵机工作电流较大(可达100-300mA),切勿直接使用STM32的3.3V引脚供电,必须使用外部电源!

1舵机的工作原理(一个脉宽对应一个转动角度)

舵机的控制信号为周期20ms 的脉宽调制(PWM)信号,其中脉冲宽度从0.5ms~2.5ms,相对应舵机转动角度为0~180度,呈线性变化。也就是说,给它提供一定的脉宽,它的输出轴就会保持在一个相对应的角度上,无论外界转矩怎样改变,直到给它提供一个另外宽度的脉冲信号,它才会改变输出角度到新的对应的位置上。舵机输出转动角度与输入信号脉冲宽度的关系见下图。

3.代码实现

1)硬件连接

单片机+5V----舵机红色线;

单片机GND----舵机棕色线;

单片机PWM输出引脚----舵机橙色线;

(2)编程思路:第一步配置PWM输出,第二步通过函数TIM_SetComparex(TIMx, CCRx)设置脉冲宽度。

3)使用定时器13,通道1(PF8PA6)输出PWM信号 

//PWM输出配置 void TIM13_PWM_Init(){    GPIO_InitTypeDef GPIO_InitStruct; //GPIO口结构体    TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;//时基结构体    TIM_OCInitTypeDef TIM_OCInitStruct;//比较输出结构体    /*1-开定时器和GPIO口时钟*/    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13,ENABLE);    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);    /*2-配置定时器输入引脚*/    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;//选择F8引脚    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//复用功能模式    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;//输出速度    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;//推挽输出    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;    GPIO_Init(GPIOF, &GPIO_InitStruct);
    GPIO_PinAFConfig(GPIOF,GPIO_PinSource8,GPIO_AF_TIM13);//复用功能配置    /*3-时基配置*/    TIM_TimeBaseStruct.TIM_Period =200-1;//自动重装载ARR值,周期20ms    TIM_TimeBaseStruct.TIM_Prescaler =8400-1;//预分频PSC值10KHz    TIM_TimeBaseStruct.TIM_ClockDivision=TIM_CKD_DIV1;//1分频    TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式    TIM_TimeBaseInit(TIM13, &TIM_TimeBaseStruct);//完成初始化    /*4-比较输出配置*/    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//PWM模式1    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性高电平     TIM_OC1Init(TIM13, &TIM_OCInitStruct); //初始化TIM5比较输出通道3    /*5-使能预装载寄存器*/    TIM_OC1PreloadConfig(TIM13, TIM_OCPreload_Enable);    /*6-使能自动重装载寄存器*/    TIM_ARRPreloadConfig(TIM13, ENABLE);    /*7-使能定时器*/    TIM_Cmd(TIM13,ENABLE);}
//角度控制函数void Set_Servo_Angle(float angle){    uint16_t pulse;    // 角度限幅    if(angle < 0) angle = 0;    if(angle > 180) angle = 180;    // 角度到脉冲宽度的线性转换    // 角度: 0° ~ 180° → 脉宽(CCR值): 5 ~ 25    //0°~5,45°~10,90°~15,135°~20,180°~25    pulse = (uint16_t)(5 + (angle / 180.0f) * 20);    TIM_SetCompare1(TIM13, pulse);}
int main(void){    int angle = 0;    TIM13_PWM_Init();    while(1)    {        Set_Servo_Angle(0);        delay_ms(1000);        Set_Servo_Angle(90);        delay_ms(1000);        Set_Servo_Angle(180);        delay_ms(1000);        for(angle = 0; angle <= 180; angle += 5)        {            Set_Servo_Angle(angle);            delay_ms(100);        }        for(angle = 180; angle >= 0; angle -= 5)        {            Set_Servo_Angle(angle);            delay_ms(100);        }    }}
//延时函数 #define SYSTEM_CORE_CLOCK 168000000void delay_ms(uint32_t ms){    // 计算重装载值    uint32_t reload = (SYSTEM_CORE_CLOCK / 1000) - 1;    uint32_t i;    for(i = 0; i < ms; i++)    {        // 设置重装载值并清空计数器        SysTick->LOAD = reload;        SysTick->VAL = 0;        // 使能计数器(使用处理器时钟,不使能中断)        SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;        // 等待计数完成        while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk))        {            // 空循环等待        }        // 禁用计数器        SysTick->CTRL = 0;    }}

【声明】内容源于网络
0
0
Easy单片机
本公众号专注于单片机技术开发领域。用于记录和分享单片机开发相关技术知识,学习笔记,设计示例和基础教程。包括C/C++、51单片机、STM32单片机、PCB设计等。
内容 62
粉丝 0
Easy单片机 本公众号专注于单片机技术开发领域。用于记录和分享单片机开发相关技术知识,学习笔记,设计示例和基础教程。包括C/C++、51单片机、STM32单片机、PCB设计等。
总阅读1
粉丝0
内容62