基于STM32F4的舵机控制

编程随笔 专栏收录该内容
14 篇文章 0 订阅

舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms-2.5ms范围内的角度控制脉冲部分,总间隔为2ms。以180度角度伺服为例,那么对应的控制关系是这样的:
   0.5ms--------------0度;
   1.0ms------------45度;
   1.5ms------------90度;
   2.0ms-----------135度;

   2.5ms-----------180度;

对于stm32来说,我们可以使用定时器PWM输出来控制舵机。

下面给出封装的舵机控制程序:

 

 

 

第一步:初始化定时器

void initServoPWM(TIM_TypeDef* TIMx,uint32_t RCC_APB1Periph_TIMx)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;


//开启TIMx时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIMx, ENABLE);

//配置TIMx
TIM_DeInit(TIMx); 
TIM_TimeBaseStructure.TIM_Period = 2000;//20ms 50频率
TIM_TimeBaseStructure.TIM_Prescaler =819;//定时器分频系数,定时器时钟为82MHz,分频后得0.01MHz,即10kHz,0.1ms定时器加1
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);
}

 

 

 

第二步:初始化PWM输出通道

void initServoChannel(GPIO_TypeDef* GPIOx,uint32_t RCC_AHB1Periph_GPIOx,u16 GPIO_Pin_x,uint16_t GPIO_PinSourcex,uint8_t GPIO_AF_TIMx,TIM_TypeDef* TIMx,u8 ch,u16 servoInitAngle)
{
servo_angle=servoInitAngle;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE);
//配置复用功能,AGPIO1复用位TIMx
GPIO_PinAFConfig(GPIOx,GPIO_PinSourcex,GPIO_AF_TIMx);

//配置PWM输出管脚 初始化
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//设置为复用模式
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//复用推挽输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOx, &GPIO_InitStructure);

//PWM模式设置 与通道设置TIMx_CHx,每个定时器只有一个频率,每个通道可以设置不同的占空比
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//模式PWM1,无论定时器是向上计数还是向下计数,计数值>有效值时为有效电平。PWM2模式相反        
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出比较使能
TIM_OCInitStructure.TIM_Pulse = servoInitAngle*200/180+50;//设置比较值,写CCRx,当计数器到达100时,电平发送跳变,即设置CCRx的值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//设输出极性为高,即有效值为高电平,当计数器<200时,PWM为高电平

switch(ch)//选择pwm通道
{
case 1:
TIM_OC1Init(TIMx, &TIM_OCInitStructure);//通道2初始化
TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Enable);//使能输出比较预装载
break;
case 2:
TIM_OC2Init(TIMx, &TIM_OCInitStructure);//通道初始化
TIM_OC2PreloadConfig(TIMx, TIM_OCPreload_Enable);//使能输出比较预装载
break;
case 3:
TIM_OC3Init(TIMx, &TIM_OCInitStructure);//通道初始化
TIM_OC3PreloadConfig(TIMx, TIM_OCPreload_Enable);//使能输出比较预装载
break;
case 4:
TIM_OC4Init(TIMx, &TIM_OCInitStructure);//通道初始化
TIM_OC4PreloadConfig(TIMx, TIM_OCPreload_Enable);//使能输出比较预装载
break;
}
TIM_ARRPreloadConfig(TIMx, ENABLE);//使能自动重装载寄存器允许位
//开启TIMx
TIM_Cmd(TIMx, ENABLE); 
}

 

 

 

第三步:通道改变占空比控制舵机转动的角度:

void setServoAngle(int angle,TIM_TypeDef* TIMx,u8 ch)
{

if(angle>180)
angle=180;
else if(angle<0)
angle=0;

servo_temp=angle*200/180+50;//计算占空比
switch(ch)//选择pwm通道
{
case 1:
TIM_SetCompare1(TIMx,servo_temp);
break;
case 2:
TIM_SetCompare2(TIMx,servo_temp);
break;
case 3:
TIM_SetCompare3(TIMx,servo_temp);
break;
case 4:
TIM_SetCompare4(TIMx,servo_temp);
break;
}
//计算延迟时间
servo_temp=servo_angle-angle;
if(servo_temp<0)
servo_temp=-servo_temp;
servo_temp=servo_temp*3+10;

USART_SendNumber(USART1,angle);
delay_ms(servo_temp);

servo_angle=angle;

}

 

  • 13
    点赞
  • 7
    评论
  • 80
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值