新手求助,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-20 03:46
 精彩回答 2  元偷偷看……
1208
2楼-- · 2019-07-20 07:24
 精彩回答 2  元偷偷看……
水墓年华
3楼-- · 2019-07-20 10:11
1208 发表于 2019-2-26 12:37
舵机只朝一个方向转动,用一个if(n>0)判断语句,n++阔以试下
还是要多改改看看

这样还是不行,参数我也改了好多次了
水墓年华
4楼-- · 2019-07-20 15:54
亦辰 发表于 2019-2-26 10:46
你这问题有点大啊,第一,你贴的这个代码本来是用PWM来驱动led灯的,n值的改变是改CCRx值(比较值)的,是 ...

谢谢,听你这么一说恍然大悟,一下子懂了点,麻烦再问下有你有没有相关的驱动电机的代码,有的话让我参考一下可以吗,还有就是我这个是舵机只有电源正负极,白 {MOD}的信号线这三根线,那就是说这个白 {MOD}信号线接PWM波输出,没有DIR口的概念对吗,这个要怎么控制呢,能详细说说吗
1208
5楼-- · 2019-07-20 17:09
 精彩回答 2  元偷偷看……
亦辰
6楼-- · 2019-07-20 22:28
 精彩回答 2  元偷偷看……

一周热门 更多>