STM32-HAL库-舵机学习


软硬件平台

  软件

    STM32CubeIDE 1.7.0

    Saleae Logic 1.2.18

  硬件

    STM32F103ZET6

    MG995

    Saleae Logic Analyer

工程初始化

  RCC(系统时钟)

    HSE(外部高速时钟) -> Crystal/Ceramic Resonator(晶振 / 陶瓷谐振器)

    HSE(外部低速时钟) -> Crystal/Ceramic Resonator(晶振 / 陶瓷谐振器)

    HCLK(AHB总线时钟) -> 72MHz 

    APB2 Prescaier(APB2总线预分频器) -> 1(即不分频)

  TIM1(高级控制定时器)

    Clock Source(时钟源) -> Internal Clock(内部时钟)

    Channel1(通道1) -> PWM Generation CH1(PWM模式通道1)

    Prescaier(预分频器) -> 720-1

      TIM1所使用的APB2时钟为72MHz,现期望获得100KHz(10us)时钟信号

    Counter Period(计数周期) -> 2000-1

      时钟周期为10us,MG995舵机信号周期为20ms

    auto-reload preload(自动重装载) -> Enable(使能)

代码部分

  开启通道PWM输出

/* main.c */

/* 开启定时器 1 通道 1 PWM */
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);

  舵机控制

    由于发现不同的舵机的控制信号不一样,但是大同小异,所以就将定时器通道以及舵机控制信号的一些指标通过define的方式定义,方便移植。

/* servo.c */

#include "servo.h"

/* 设置所使用的定时器 */
#define  servo_htim  htim1

/* 设置所使用的通道 */
#define  servo_channel  TIM_CHANNEL_1

/* 设置定时器计数值 */
#define  servo_plus  2000

/* 设置舵机控制信号周期(ms)  */
#define  servo_cycle_ms  20.0

/* 设置舵机控制信号最短脉冲宽度(ms) */
#define  servo_min_ms  0.5

/* 设置舵机控制信号1ms脉冲宽度变化所对应的角度变化值 */
#define  servo_1ms_angle  90.0

void servo_control(int angle)
{
    int value;
    /* 目标角度为0时需要单独处理 */
    if(angle == 0)
    {
        value = ((servo_min_ms / servo_cycle_ms) * servo_plus);
    }
    /* 通过计算目标角脉冲宽度来计算所需要的脉冲计数值 */
    else
    {
        value = (((servo_min_ms + (angle / servo_1ms_angle)) / servo_cycle_ms) * servo_plus);
    }
    /* 改变定时器 1 通道 1 的脉冲计数值 */
    __HAL_TIM_SET_COMPARE(&servo1_htim,servo1_channel,value);
}

 

/* servo.h */

#ifndef INC_SERVO_H_
#define INC_SERVO_H_

#include "main.h"
#include "tim.h"

void servo_control(int angle);

#endif /* INC_SERVO_H_ */

测试

  测试代码

/* 舵机转到0°位置 */
servo1_control(0);
HAL_Delay(1000);

/* 舵机转到45°位置 */
servo1_control(45);
HAL_Delay(1000);

/* 舵机转到90°位置 */
servo1_control(90);
HAL_Delay(1000);

/* 舵机转到120°位置 */
servo1_control(135);
HAL_Delay(1000);

/* 舵机转到180°位置 */
servo1_control(180);
HAL_Delay(1000);

   测试结果

舵机转到0°位置

舵机转到45°位置

舵机转到90°位置

舵机转到135°位置

舵机转到180°位置

 Debug

  对于下面这条语句我最初想当然的加了一个 -1 ,后来采集出来的脉冲宽度少了10us,下面对这个问题的。

value = (((servo_min_ms + (angle / servo_1ms_angle)) / servo_cycle_ms) * servo_plus);

  上面这条语句是被下面这条语句所使用的。

__HAL_TIM_SET_COMPARE(&servo1_htim,servo1_channel,value);

  查询数据手册,发现有如下描述:

  

进一步的,看一下我们的 value 指向到哪里,可以在 stm32f1xx_hal_tim.h 中看到这样的描述。

如果我没有理解错的话,value 值最终被指向Capture Compare Register,那就是手册中的CCRx了。

 

  再进一步可以在手册中发现OCXREF信号为高电平有效信号,CCxIF是一个置中断状态寄存器中的标志位也是高有效。

  分析到现在,很显然,ARR的值在我们设置的过程中是需要-1的,不然会多计数一个。

  而CCRx的值就是表示计数的次数,那么在这里加上-1的话就会少计数一次。

  至此,这个bug已经分析完成了,那么在以后执行相关操作的时候这个点就要注意了,不要赋错值。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM