舵机的控制一般需要一个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;
}
上一篇:STM32-PWM波-控制舵机
下一篇:STM32控制舵机转动
推荐阅读最新更新时间:2024-03-16 16:05