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