基于STM32F1的舵机控制

一、SG90舵机介绍

SG90是有三个版本的,90度版、180度版和360度版,前两个只是舵机旋转角度的范围不一样,可以在这个范围内任意的控制舵机所转的角度,而360版本的是一直旋转的,我们不能控制它旋转的角度,只能控制它旋转的速度,这里我们在买的时候就要注意一点,根据自己的需求选取不同的版本,以免买错。这里我们介绍180度版本的。三个控制原理基本相同。

单片机系统实现对舵机输出转角的控制,必须首先完成两个任务:首先是产生基本的PWM周期信号,本设计是产生20ms的周期信号;其次是脉宽的调整,即单片机模拟PWM信号的输出,并且调整占空比。

脉冲的高电平部分一般为0.5ms~2.5ms范围内的角度控制脉冲部分,所以是利用一个占空比来控制舵机转动的角度。PWM占空比是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比。占空比 = t / T 相关参数如下:

t = 0.5ms——————-舵机会转动 0 °

t = 1.0ms——————-舵机会转动 45°

t = 1.5ms——————-舵机会转动 90°

t = 2.0ms——————-舵机会转动 135°

t = 2.5ms——————-舵机会转动180°

当你需要转动135°时,他的占空比就是2.0ms/20ms=10%,所以 TIMx 捕获比较寄存器值就为200-200*10% = 180。

二、与单片机的连接:

SG90分别有三根线。棕色,红色,橙色

棕色接地(GND)

红色接电源(+5V)

橙色接输出PWM信号的引脚

三、PWM

因为舵机的控制主要用到的就是定时器的pwm功能,所以我们先聊一聊pwm

PWM的输出其实就是对外输出脉宽可调(即占空比调节)的方波信号,信号频率是由自动重装寄存器 ARR 的值决定,占空比由比较寄存器CCR的值决定。

  当TIMx_CR1寄存器中的 DIR 位为低时执行递增计数,计数器CNT从0计数到自动重载值(TIMx_ARR 寄存器的内容),然后重新从 0 开始数并生成计数器上溢事件。

 以PWM 模式 1 为例。只要TIMx_CNT < TIMx_CCRx, PWM 参考信号OCxREF 便为有高电平,否则为无效的低电平。如果 TIMx_CCRx 中的比较值大于自动重载值(TIMx_ARR 中),则 OCxREF 保持为“ 1”。果比较值为 0, 则 OCxREF 保持为“ 0”。

  我们控制舵机主要是产生一个以20ms为周期的pwm信号,然后通过改变pwm的占空比就可以控制舵机的转角。

四、程序设计

主函数如下:

int main() 

{

u8 i;

SysTick_Init(72);

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组

LED_Init();

Sg90_Init();

USART1_Init();

while(1)

   {

   i++;

// TIM_SetCompare2(TIM3, 195);  // 0度    t = 0.5ms           修改TIMx_CCRx的值控制占空比

// delay_ms(1000);

// TIM_SetCompare2(TIM3, 190);  //45度   t = 1.0ms——————-舵机会转动 45°  占空比就应该为1ms/20ms = 5%,所以TIM_SetCompare1的 TIMx 捕获比较 1 寄存器值就为200-200*5% = 190

// delay_ms(1000);

// TIM_SetCompare2(TIM3, 185);  //90度      t = 1.5ms

// delay_ms(1000);

// TIM_SetCompare2(TIM3, 180);  //135度        t = 2.0ms

// delay_ms(1000);

// TIM_SetCompare2(TIM3, 175);  //180度         t = 2.5ms

// delay_ms(1000);

// Sg90_Return(0);

// delay_ms(1000);

//    Sg90_Return(45);

// delay_ms(1000);

//    Sg90_Return(90);

// delay_ms(1000);

//    Sg90_Return(135);

// delay_ms(1000);

//    Sg90_Return(180);

// delay_ms(1000);

   

   if(i%20==0)

   {

   led1=!led1;

   }

   delay_ms(10);

   

   }

}

在主函数中我们控制舵机以此转过45、90、135、180度,这里之所以会注销掉这些,是因为我在工程文件中增添了通过串口控制舵机的功能,我们可以直接在串口中向单片机发送控制数据,舵机就会转过相应的角度。

  先看看sg90.c文件:

void Sg90_Init()

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;

TIM_OCInitTypeDef TIM_OCInitStructure;     //输出比较结构体

GPIO_InitTypeDef GPIO_InitStructure; 

/* 开启时钟 */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//初始化GPIOB端口使能

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//开启定时器3的时钟

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

/*  配置GPIO的模式和IO口 */

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;                   // 选择你要设置的IO口

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;          //选择输出模式(复用推挽输出)

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_Init(GPIOC,&GPIO_InitStructure);

GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);  //设置管脚复用映射(部分重映射)

TIM_TimeBaseInitStructure.TIM_Period=199;    //自动装载值      定时器定时时间计算公式

TIM_TimeBaseInitStructure.TIM_Prescaler=7199; //分频系数      ((per)*(psc+1))/Tclk

TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//时钟分频

TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //计数模式(向上计数模式)

TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);

TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;

TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low; //设置输出极性(底)

TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; // 比较输出使能

TIM_OC2Init(TIM3,&TIM_OCInitStructure);   //输出比较通道2初始化

TIM_Cmd(TIM3,ENABLE); //开启定时器

TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器

TIM_ARRPreloadConfig(TIM3,ENABLE); //使能TIM3在ARR上的预装载寄存器允许位

}

void Sg90_Return(u8 angle)

{

u8 per;

if(angle==45)

{

per=190;

TIM_SetCompare2(TIM3, per);

}

else if(angle==90)

{

per=185;

TIM_SetCompare2(TIM3, per);

}

else if(angle==135)

{

per=180;

TIM_SetCompare2(TIM3, per);

}

else if(angle==180)

{

per=175;

TIM_SetCompare2(TIM3, per);

}

else

{

per=195;

TIM_SetCompare2(TIM3, per);

}

}

程序比较简单,就一个定时器初始化和直接输入角度的控制函数,(第二个是函数是我自己写的,比较烂,有能力的可以完善完善一起学习)主要思想还是通过TIM_SetCompare2()设置CCR的数值。

在看看如何通过串口控制:

void USART1_IRQHandler(void)     //中断服务函数

      { 

  

  u8 r;

u16 num;

static char pwm[4];

    static int i=0;

if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)  //检查串口1的接收中断是否发生

{

r=USART_ReceiveData(USART1);      //返回 USART1 最近接收到的数据

if(r!='g'&&r!='m')

{

pwm[i]=r;

i++;

}

else

{

i=0;

num=(atoi(pwm));

TIM_SetCompare2(TIM3, num);

}

USART_SendData(USART1,r);         //通过外设 USART1 发送单个数据

while (USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);   //检查 USART1的 发送完成标志位 设置与否

}

USART_ClearFlag(USART1,USART_FLAG_TC);

       }

这里主要就是数据转化的问题,通过atoi()函数将字符串转化为整数然后再用于控制舵机。串口传输数据的时候要特别注意不同数据格式之间的转化。

 

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: STM32F103步进电机控制推杆,可以通过设置GPIO引脚和定时器来实现。 首先,需要配置GPIO引脚作为控制步进电机的接口。可以选择适当的引脚,例如PA0、PA1、PA2和PA3等作为控制步进电机的四个相位线IN1、IN2、IN3和IN4。使用STM32的GPIO库函数,可以将这些引脚设置为输出模式。 其次,需要使用一个定时器来生成控制步进电机的脉冲信号。可以选择一个合适的定时器,例如TIM2或TIM3等。配置定时器的计数模式为向上计数,并设置合适的计数值和分频系数,以确定生成脉冲的频率。 然后,编写步进电机控制程序。可以使用循环控制语句来不断改变GPIO引脚的输出状态,以产生步进电机的旋转。具体可以依照步进电机的工作原理,按照相应的顺序控制四个相位线的输出状态。 最后,将步进电机控制程序与定时器中断绑定。当定时器计数到一定值时,触发定时器中断,并在中断函数中调用步进电机控制程序,从而实现步进电机的控制推杆的运动。 综上所述,通过配置GPIO引脚和定时器,并编写相应的控制程序,可以实现对STM32F103步进电机控制推杆的功能。 ### 回答2: 为了使用STM32F103控制步进电机推杆,我们需要采用适当的电路连接和编程实现。步进电机是一种用于精确控制位置和速度的设备。 首先,我们需要将STM32F103与步进电机连接起来。我们可以通过一个适当的电路连接步进电机的控制信号引脚(如步进脉冲和方向脉冲)到STM32F103的GPIO引脚。同时,我们还需要将步进电机的电源引脚连接到适当的电源电压。 接下来,我们需要编写相应的程序来控制步进电机推杆的运动。首先,我们需要配置STM32F103的GPIO引脚作为输出,并设置相应的引脚状态和电平。然后,我们可以使用适当的控制算法来生成适当的脉冲序列,以控制步进电机的转动。 控制算法可以根据需求选择,例如可以使用简单的全或无的策略控制步进电机的转动,也可以使用更复杂的微调算法来实现更精准的控制。 最后,我们需要将程序烧录到STM32F103的存储器中,并确保正确运行。我们可以使用适当的开发工具和编程语言(如C或C++)来编写和烧录程序。 总结来说,要使用STM32F103控制步进电机推杆,需要进行适当的电路连接和编程实现。通过配置GPIO引脚和编写相应的控制算法,我们可以实现对步进电机推杆的精确控制。这种控制可以用于许多应用,例如机械臂、数控机床等。 ### 回答3: STM32F103可以用于控制步进电机控制推杆。步进电机是一种特殊的电机,可以按照固定的角度或者步数旋转。推杆是一种直线运动装置,可以通过步进电机的旋转来实现线性推动。 首先,我们需要将步进电机连接到STM32F103的适当引脚上。步进电机通常有两个相位,每个相位有两个线圈。我们将线圈的两端连接到STM32F103的输出引脚,并使用合适的电源和电流限制器为步进电机供电。 接下来,我们需要编写STM32F103的代码来控制步进电机。可以利用STM32F103的GPIO功能来设置输出引脚。通过改变输出引脚的状态(高电平或低电平),我们可以控制步进电机的旋转方向和速度。 为了实现步进电机控制推杆,我们需要采用适当的步进电机驱动方式。最常见的步进电机驱动方式是全步进驱动和半步进驱动。全步进驱动提供更大的扭矩和准确度,而半步进驱动提供更高的分辨率和平滑度。 在代码中,我们可以通过改变输出引脚的状态来控制步进电机的旋转方向和速度。可以使用定时器来生成适当的脉冲信号,从而驱动步进电机旋转。通过控制脉冲数量和频率,可以控制步进电机的旋转角度和速度。 最后,我们可以使用编程语言(如C语言)编写代码来实现步进电机控制推杆的逻辑。我们可以编写一些函数或者类来控制步进电机的旋转和推动。通过调用这些函数或者类的方法,我们可以实现步进电机控制推杆的功能。 总结起来,利用STM32F103可以通过控制步进电机的旋转来实现推杆的线性推动。通过编写适当的代码和配置合适的硬件连接,我们可以灵活地控制步进电机的旋转方向和速度,实现步进电机控制推杆的应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搞机佬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值