stm32如何控制舵机转动到指定角度?

  • 时间:
  • 来源:互联网
  • 文章标签:

推荐两个非常好的参考资料:
舵机工作原理
舵机控制
STM32如何配置PWM

STM32定时器定时计算公式
Tout = ((arr+1)*(psc+1))/Tclk ;
其中:
Tclk:定时器的输入时钟频率(单位MHZ) eg;stm32f103RCT6为72MHz
Tout:定时器溢出时间(单位为us)
.TIM_Period = arr; eg;4999
.TIM_Prescaler = psc; eg:7199

Tout = ((4999+1)×(7199+1))/72 = 500000us = 500ms 。
如何理解这个公式?
Tout = ((arr+1) * (psc+1))/Tclk ;
= (arr+1)* [(psc+1)/Tclk ]
PWM的周期=需要多少节拍数 *多久产生一个节拍
其中:
(arr+1)可以理解为需要多少节拍数
[(psc+1)/Tclk ]可以理解为多久产生一个节拍,这就要设置时钟了
分析:
采用的是stm32f103RCT6起产生节拍的频率为72MHz,也就是1/72000000 秒=1/72微妙 产生一次节拍,对应舵机来说,频率太快也就是周期太短,所有需要分频,也就是降低到适当的频率用来产生PWM信号控制舵机,
Tclk为72MHz
Tclk /(psc+1) 为分频后的频率
(psc+1)/Tclk分频后的周期,也就是这么久产生一个节拍
所以PWM的周期=需要多少节拍数 * 多久产生一个节拍
看资料可知,舵机的周期为20ms,高电平占比跨距2ms(0.5ms——2.5ms),在这个跨距对应舵机的180°
0.5ms----------- 0°
1.0ms----------- 45°
1.5ms----------- 90°
2.0ms-----------135°
2.5ms-----------180°
就变成了一个题目:
当 Tclk=72M时,怎么来选取合适的arr(要求小于65535),psc(要求小于65535),使得PWM的周期为20ms,高电平占比跨距2ms(0.5ms——2.5ms),而且要精细,也就是更多的节拍表示小量程,如果把20ms看作是大量程,跨距2ms是其中一段小量程,那么每个节拍就是精度了,求角度和节拍的对应关系?
解:
20ms={(arr+1) * [(psc+1)/72000000] }s= {(arr+1) *[(psc+1)/7200] }ms
也就是:
20={(arr+1) * [(psc+1)/7200] }
也就是:
(arr+1) * (psc+1)=1440000

1)选取pas+1=1440则arr+1=1000,也就是1000个节拍表示20ms,那50个节拍就是1ms,小量程是2ms,也就是100个节拍
2)选取pas+1=144则arr+1=10000,也就是10000个节拍表示20ms,那500个节拍就是1ms,小量程是2ms,也就是1000个节拍,比第一种取法更精细,所以我采用这种
也就是:pas=144-1;arr=10000-1;500个节拍1ms也就是1000us,对应就是1个节拍2us
当0.5ms时,也就是比较值为250的时候,舵机转动的角度为0°,时间每0.5ms=500us增加对应角度45°的增加,即1us=0.09°2us=0.18°=1个节拍

PWM的比较值(看作节拍)和角度的关系:
1个节拍=0.18°
角度为N时,对应的节拍是(N/0.18)

如下:
时间 ----------------------- 角度——— 节拍(Compare)
0.5ms(500us)----------- 0°————250
1.0ms(1000us)----------- 45°———250+45/0.18
1.5ms(1500us)----------- 90°———250+90/0.18
2.0ms(2000us)-----------135°———250+135/0.18
2.5ms(2500us)-----------180°———250+180/0.18
总结:
每行递增500us,45°即250个节拍
Compare1=250+(N/0.18)

void SetAngle(int N)//0<=N<=180
{
TIM_SetCompare1(TIM3,250+(N/0.18));
}
配置代码如下:

void TIM3_PWM_Init(u16 arr,u16 psc)
{  
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);// 使能定时器3外设时钟使能
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);  //使能GPIO外设时钟使能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO , ENABLE); //使能复用时钟使能
	   
   GPIO_PinRemapConfig(GPIO_FullRemap_TIM3 , ENABLE);	//完全重映射

   //设置该引脚为复用输出功能,输出TIM3 CH1的PWM脉冲波形
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //TIM_CH1
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
//配置定时器,确定周期,周期的节拍数,和产生节拍的频率
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

 //设置TIM3_CH1的PWM模式,使能TIM3的CH1输出,配置输出比较通道,PWM模式,有效电平等:
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC1Init(TIM3, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx

    TIM_CtrlPWMOutputs(TIM3,ENABLE);	//MOE 主输出使能	

	TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  //CH1预装载使能	 
	
	TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIMx在ARR上的预装载寄存器
	
	TIM_Cmd(TIM3, ENABLE);  //使能TIM3
  
}

输入角度,转化成PWM的比较值,控制高电平占空的占比,从而达到想要的角度

void  SetAngle(int N)//N<180 
{
	TIM_SetCompare1(TIM3,250+(N/0.18));	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
}

主函数初始化
采用第二种方式:选取pas=144-1;arr=10000-1;

TIM3_PWM_Init(10000-1,144-1);//计数1次代表2us代表0.18°

本文链接http://www.taodudu.cc/news/show-1944808.html