使用STM32L TIM PWM控制伺服电机

时间:2017-05-02 06:49:06

标签: c stm32 pwm servo

所以我试图通过PWM使用STM32L1来控制伺服。下面是完整的代码,不需要库。 当我上传并运行此代码时,伺服会多次拨号,而不是实际平滑地移动到所需的位置600(0 *),1100(50 *),1600(100 *)和2100(150 *)。 我相信这与预分频值计算有关,而且我不确定在微秒内提及ARR是否正确,如果没有,我如何将其配置为读取微秒而不是毫秒。 有关详细信息,请参阅代码中的注释。

#include <stdio.h>
#include "stm32l1xx.h"             
 // Keil::Device:Startup

 // initialization of GPIOB
void TIM4_Init(){
RCC->AHBRSTR |= RCC_AHBRSTR_GPIOARST;       /* Reset GPIOB clock         */
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;           /* Enable GPIOB clock         */
GPIOB->MODER   &=   ~(0x03 << (2*6));       /* Clear bit 11 & 12 Alternate mode*/
GPIOB->MODER   |=   0x02 << (2*6);          /* set as Alternate mode*/
GPIOB->OSPEEDR &=   ~(0x03<< (2*6));        /* 40 MHz  speed        */
GPIOB->OSPEEDR |=   0x03<< (2*6);           /* 40 MHz  speed        */
GPIOB->PUPDR &=         ~(1<<6);            /* NO PULL-UP PULL-DOWN        */
GPIOB->OTYPER &=        ~(1<<6);            /* PUSH-PULL        */
GPIOB->AFR[0] |=        0x2 << (4*6);       /* Pin6 set as alternate function 2 (TIM4) */

RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
TIM4->PSC = 16; //prescale value, AHB/APB1 Fmax=32MHz / 2
TIM4->ARR = 20000-1; //motor Freq = 50Hz, Period(ARR)= 1/50 = 20000us


// initialization of TIM & PWM

TIM4->CCMR1 |= TIM_CCMR1_OC1M;  // 111: PWM mode 2 - In upcounting, channel 1 is inactive 
                               //as long as TIMx_CNT<TIMx_CCR1 else active. 
                              // In downcounting, channel 1 is active as long as 
                             //TIMx_CNT>TIMx_CCR1 else inactive.

TIM4->CCMR1 |= TIM_CCMR1_OC1PE;
TIM4->CR1 |= TIM_CR1_ARPE;
TIM4->CCER |= TIM_CCER_CC1E;
TIM4->EGR |= TIM_EGR_UG;
TIM4->SR &= ~TIM_SR_UIF;
TIM4->DIER |= TIM_DIER_UIE;
TIM4->CR1 |= TIM_CR1_CEN;
}

// set servo to 4 positions in sequence

int main(void){

int i;

int position=600; // initial motor position

TIM4_Init();

while (1){  

if ((position >=600)|| (position <=2100))
position = position+500;      // motor positions will be 600(0*), 1100(50*), 1600(100*)
                             //, 2100(150*)
TIM4->CCR1 = position; 

for(i=0;i<1000;i++); // short delay


   }


 }  

2 个答案:

答案 0 :(得分:1)

这取决于您的时钟设置。你需要首先配置你的时钟,因为只有复位2.097MHz后有多少L1有默认时钟,你设置的周期是0.152598951 sek,伺服接收的脉冲宽度是0.07到0.15sek,大约是75倍长(我认为PCS应该是15来存档16 * 20000个时钟周期)。根据您的设置,定时器时钟应该大于100MHz,这对于L1

是不可能的

定时器计数滴答以及滴答所需的时间取决于时钟速度和定时器时钟分频器。

要归档20ms,您需要将PSC保留为零值且ARR = 41939

当然,1ms将是2097和2ms - 4194

您需要计算正确的值

配置PLL的最简单方法是使用WYSIWYG CubeMX时钟编辑器

答案 1 :(得分:0)

正如@PeterJ所提到的,这取决于你的时钟设置。我会在这里提出更多的精确度。

您的ARR似乎很好,因为很清楚您的周期为20毫秒。

但是你的PSC应该根据ARR设置,以达到1kHz。为此你必须知道时钟频率。

旁注,根据stm文档,PSC值应该比所需的小1个单位(如果你想要16,你应该把15写入寄存器)。

  

计数器时钟频率CK_CNT等于fCK_PSC /(PSC [15:0] + 1)

相关问题