新手求助,PWM驱动舵机问题,急急急!!!

2019-07-20 03:37发布

本帖最后由 水墓年华 于 2019-2-26 11:17 编辑

大家好:
我是一个嵌入式初学者,现在要做一个小项目,需要用到PWM驱动的舵机,但是调试了好久也摸不清原理,代码也是网上找的,有些地方还不太理解,现在电机就是不停的正转大概30度,再转回来30度,这样一直循环,请各位帮忙解答一下
1.在定时器初始化函数中,设置时钟分频系数应该是htim2.Init.Prescaler = 168-1;将时钟频率分为更小的频率,如我的板子STM32F427是设置168M的时钟频率,设置psc=168分频,168/168=1得到1M时钟频率,但是我这样配置的话电机就不转了,我试了试最起码要在差不多400才能正常转起来,而且这个时候转的角度很小,大概在1200的时候能达到最大,大概是45度左右,是我理解的不对吗?
2.htim2.Init.Period = 200-1;这个是设定自动重装载值吗,周期是怎么算的?
3.我要如何更改代码才能实现精准的控制,比如现在怎么让舵机只朝一个方向转动
下面贴一下我的代码:
主函数

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_TIM2_Init();

    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);
    int n = 50;
    int dir = 0;

    while(1)
    {
        HAL_Delay(20);
        if(dir)n++;                                        //dir==1 n 递增
        else n--;                                          //dir==0 n 递减
        if(n>300)dir=0;                                    //n 到达 300 后,方向为递减
        if(n==50)dir=1;                                     //n 递减到 0 后,方向改为递增
        USER_PWM_SetDutyRatio(&htim2,TIM_CHANNEL_3,n);     //修改比较值,修改占空比
    }

定时器初始化

static void MX_TIM2_Init(void)
{

  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 1200-1;                                   //该分频将时钟频率分为更小的频率,如STM32F429是设置168M的时钟频率,设置psc=168分频,得到1M时钟频率
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;                    //设置计数方式为向上计数逐一增加从0到19999,此时得到的是20ms就重装初值的定时器
  htim2.Init.Period = 200-1;                                      //自动重装载值,在设置arr=20000重装初值,由公式1M/20000=50Hz,即周期T=20ms
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  HAL_TIM_MspPostInit(&htim2);
}

调整PWM占空比,value为占空比 value=50 即占空比为50%
void USER_PWM_SetDutyRatio(TIM_HandleTypeDef *htim,uint32_t Channel,uint8_t value)
{
    TIM_OC_InitTypeDef sConfigOC;
   
    uint32_t period=htim->Init.Period+1;
    uint32_t pluse=(value * period)/100;
   
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = pluse;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    HAL_TIM_PWM_ConfigChannel(htim, &sConfigOC, Channel);
    HAL_TIM_PWM_Start(htim, Channel);   
}


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
9条回答
水墓年华
1楼-- · 2019-07-21 00:34
本帖最后由 水墓年华 于 2019-2-27 10:18 编辑
亦辰 发表于 2019-2-27 09:18
额。。有点尴尬,我把舵机理解成伺服电机了,我查了下资料,舵机的基准信号的周期为20ms,也就是500Hz, ...

C:UsershaoDesktopTIM截图20190227095301哦哦好,那这些参数配置和我的时钟配置无关吗,这个是我的时钟配置图,我想问下我如何确定TIM2现在用的是APB1还是APB2呢?还有你说的Prescaler和Period这两个值是根据什么去配的可以说明一下吗。你说的比较值又该如何理解呢
亦辰
2楼-- · 2019-07-21 01:09
 精彩回答 2  元偷偷看……
水墓年华
3楼-- · 2019-07-21 06:31
亦辰 发表于 2019-2-27 11:01
你提供的代码说明你的时钟是在APB2的啊,怎么看的要去看stm32的参考手册,哪个外设在哪个总线上都有说明 ...

好的明白了,谢谢呀,我再去看看

一周热门 更多>