STM32通用定时器驱动SG90舵机

SG90舵机的控制原理

舵机的控制一般需要一个20ms的时基脉冲,该脉冲的高电平部分一般为0.5ms~2.5ms范围内的角度控制脉冲部分。以180度角度舵机为例,那么对应的控制关系是这样的:

0.5ms————-0度;
1.0ms————45度;
1.5ms————90度;
2.0ms———–135度;
2.5ms———–180度;

0SubZR.gif

所以,通过单片机输出相应的PWM信号即可控制舵机旋转相应的角度

STM32通用定时器输出PWM信号配置

定时器周期计算公式:

T = ((Prescaler + 1) * (Period + 1) ) / TimeClockFren;

Prescaler:分频TIM时钟的预分频器值。

Period:计数重载值,TIM计数当超过这个值,则重新计数。

TimeClockFren:定时器的输入时钟频率(单位MHZ),也就是当前使用的TIM所用的CLOK的时钟频率。 这里为72Mhz

需要20ms的时基脉冲 20ms = (7200*200)/72000000=0.02

所以TIM_Period = 199,TIM_Prescaler = 7199

结构体初始化

void pwm_init()
{
    GPIO_InitTypeDef GPIO_InitStructure;   //声明一个结构体变量,用来初始化GPIO

    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//声明一个结构体变量,用来初始化定时器

    TIM_OCInitTypeDef TIM_OCInitStructure;//根据TIM_OCInitStruct中指定的参数初始化外设TIMx

    /* 开启时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

    /*  配置GPIO的模式和IO口 */
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;// PA6
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
    GPIO_Init(GPIOA,&GPIO_InitStructure);

    //TIM3定时器初始化
    TIM_TimeBaseInitStructure.TIM_Period = 199; //PWM 频率=72000/(199+1)=36Khz//设置自动重装载寄存器周期的值
    TIM_TimeBaseInitStructure.TIM_Prescaler = 7199;//设置用来作为TIMx时钟频率预分频值
    TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;//设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;    //TIM向上计数模式
    TIM_TimeBaseInit(TIM3, & TIM_TimeBaseInitStructure);

    //PWM初始化      //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
    TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM输出使能
    TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;

    TIM_OC1Init(TIM3,&TIM_OCInitStructure);
    //注意此处初始化时TIM_OC1Init而不是TIM_OCInit,否则会出错。因为固件库的版本不一样。
    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能或者失能TIMx在CCR1上的预装载寄存器
    TIM_Cmd(TIM3,ENABLE);//使能或者失能TIMx外设
}

这里TIM_OCInitTypeDef.TIM_Pulse不用配置,而是在主函数中通过TIM_SetCompare1(TIMx,x)函数来修改他的值,已达到想要转动舵机角度的目的

TIMx_CCRx寄存器能够在任何时候通过软件进行更新以控制波形,这个通过软件写入控制波形的值是立即生效呢还是在定时器发生下一次更新事件时被更新的,是由TIM_OCxPreloadConfig(TIMx, TIM_OCPreload_Enable)这条语句决定的!Enable就是下一次更新事件时被更新;Disable是立即生效

int main(void)
{
    /* 定时器初始化 */
    pwm_init();

  while(1)
  {
        TIM_SetCompare1(TIM3, 195);//0度
        delay_ms(1000);
        TIM_SetCompare1(TIM3, 185);//90度
        delay_ms(1000);
        TIM_SetCompare1(TIM3, 175);//180度
        delay_ms(1000);    
  }
}

最终效果如图

0SKGWT.gif