舵機驅動——STM32F407ZGT6探索者——HAL庫

2023-11-03 06:01:09

舵機驅動——STM32F407ZGT6探索者——HAL庫

1、材料準備

  開發板:正點原子STM32F407ZGT6探索者

  舵機:SG90

  舵機線材分辨:褐色 / 紅色 / 橘黃色 —— GND / VCC / PWM_signal

  與開發板接線:褐色 / 紅色 / 橘黃色 —— GND / +5V / PF6(任選的PF6)

2、知識準備

  2.1、舵機需要的訊號頻率為50HZ,對應週期是 0.02 ,所以 arr 設定為 20000 -1 ,psc 設定為 168-1,原因是這麼設定可剛好按如下算出頻率是50HZ;

  2.2、定時器工作頻率 Ft = 84 MHz ,單位:Mhz,來源:此次任選採用PF6針腳,而PF6可重對映到TIM10_CH1,而TIM10掛載在APB2上,APB2上的定時器時脈頻率是168HZ(前提是這塊開發板的SYSCLK直接設定到最大頻率168MHz)。還想看168的圖解來源請直接開啟CuceMX或CubeIDE在「時鐘樹設定欄目」看到。

 

  2.3、計算方法

  定時器溢位時間計算方法: Tout = ( (arr + 1) * (psc + 1) ) / Ft us.

  週期 = (2 0000 * 168)/ (168 000 000) = 0.02 秒;

  頻率 = 1 / 週期 = 50 HZ ;

3、程式碼塊

gtim.h

 #ifndef __GTIM_H
 #define __GTIM_H
 
 #include "./SYSTEM/sys/sys.h"
 
 /*********************************以下是通用定時器PWM輸出實驗相關宏定義*************************************/
 
 /* TIMX PWM輸出定義
  * 這裡輸出的PWM控制LED0(RED)的亮度 , 或控制別的,如舵機
  * 預設是針對TIM2~TIM5
  * 注意: 通過修改這幾個宏定義,可以支援TIM1~TIM8任意一個定時器,任意一個IO口輸出PWM
  */
 #define GTIM_TIMX_PWM_CHY_GPIO_PORT         GPIOF
 #define GTIM_TIMX_PWM_CHY_GPIO_PIN         GPIO_PIN_6
 #define GTIM_TIMX_PWM_CHY_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOF_CLK_ENABLE(); }while(0)  /* PF口時鐘使能 */
 #define GTIM_TIMX_PWM_CHY_GPIO_AF           GPIO_AF3_TIM10                               /* 埠複用到TIM10,舵機用 */
 
 
 /* TIMX REMAP設定
  * 因為外設接在例如PF6上, 必須通過開啟TIM10的部分重對映功能, 才能將TIM10_CH1輸出到PF6上
  */
 #define GTIM_TIMX_PWM                       TIM10                                        /* TIMx */
 #define GTIM_TIMX_PWM_CHY                   TIM_CHANNEL_1                                /* 通道Y, 1<= Y <=4 */
 #define GTIM_TIMX_PWM_CHY_CCRX             TIM10->CCR1                                  /* 通道Y的輸出比較暫存器 */
 #define GTIM_TIMX_PWM_CHY_CLK_ENABLE()     do{ __HAL_RCC_TIM10_CLK_ENABLE(); }while(0)  /* TIMx 時鐘使能 */
 
 /****************************************************************************************************/
 
 void gtim_timx_pwm_chy_init(uint16_t arr, uint16_t psc);    /* 通用定時器 PWM初始化函數 */
 
 #endif

gtim.c

 #include "./BSP/TIMER/gtim.h"
 
 TIM_HandleTypeDef g_timx_pwm_chy_handle;     /* 定時器x控制程式碼 */
 
 /**
  * @brief       通用定時器TIM 10 通道 1 PWM輸出 初始化函數(使用PWM模式1)
  * @note
  *             通用定時器的時鐘來自APB2
  *             通用定時器的時鐘為APB2時鐘的2倍, 而APB2為84 MHZ, 所以定時器時鐘 = 168Mhz
  *             定時器溢位時間計算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
  *             Ft = 定時器工作頻率,單位:Mhz
  *
  * @param       arr: 自動重灌值
  * @param       psc: 預分頻係數
  * @retval     無
  */
 void gtim_timx_pwm_chy_init(uint16_t arr, uint16_t psc)
 {
     TIM_OC_InitTypeDef timx_oc_pwm_chy = {0};                       /* 定時器輸出控制程式碼 */
     
     g_timx_pwm_chy_handle.Instance = GTIM_TIMX_PWM;                 /* 定時器10 */
     g_timx_pwm_chy_handle.Init.Prescaler = psc;                     /* 預分頻係數 */
     g_timx_pwm_chy_handle.Init.CounterMode = TIM_COUNTERMODE_UP;    /* 遞增計數模式 */
     g_timx_pwm_chy_handle.Init.Period = arr;                        /* 自動重灌載值 */
     HAL_TIM_PWM_Init(&g_timx_pwm_chy_handle);                       /* 初始化PWM */
 
     timx_oc_pwm_chy.OCMode = TIM_OCMODE_PWM1;                       /* 模式選擇PWM1 */
     timx_oc_pwm_chy.Pulse = 0;                               /* 設定CCR比較值,此值用來確定佔空比 */
 
     timx_oc_pwm_chy.OCPolarity = TIM_OCPOLARITY_HIGH;                                        /* 輸出比較極性為HIGH */
     HAL_TIM_PWM_ConfigChannel(&g_timx_pwm_chy_handle, &timx_oc_pwm_chy, GTIM_TIMX_PWM_CHY); /* 設定TIM10通道1 */
     HAL_TIM_PWM_Start(&g_timx_pwm_chy_handle, GTIM_TIMX_PWM_CHY);                           /* 開啟對應PWM通道 */
 }
 
 
 /**
  * @brief       定時器底層驅動,時鐘使能,引腳設定
                 此函數會被HAL_TIM_PWM_Init()呼叫
  * @param       htim:定時器控制程式碼
  * @retval     無
  */
 void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
 {
     if (htim->Instance == GTIM_TIMX_PWM)     /* htim->Instance定時器基地址 */
    {
         GPIO_InitTypeDef gpio_init_struct;
 
         GTIM_TIMX_PWM_CHY_GPIO_CLK_ENABLE();                            /* 開啟通道1的CPIO時鐘 */
         GTIM_TIMX_PWM_CHY_CLK_ENABLE();                                 /* 使能定時器時鐘 */
 
         gpio_init_struct.Pin = GTIM_TIMX_PWM_CHY_GPIO_PIN;              /* 通道1的GPIO口 */
         gpio_init_struct.Mode = GPIO_MODE_AF_PP;                        /* 複用推輓輸出 */
         gpio_init_struct.Pull = GPIO_PULLUP;                            /* 上拉 */
         gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;             /* 高速 */
         gpio_init_struct.Alternate = GTIM_TIMX_PWM_CHY_GPIO_AF;         /* IO口REMAP設定, 是否必要檢視標頭檔案設定的說明! */
         
  HAL_GPIO_Init(GTIM_TIMX_PWM_CHY_GPIO_PORT, &gpio_init_struct);
    }
 }

main.c

 #include "./SYSTEM/sys/sys.h"
 #include "./SYSTEM/usart/usart.h"
 #include "./SYSTEM/delay/delay.h"
 #include "./BSP/LED/led.h"
 #include "./BSP/TIMER/gtim.h"
 
 extern TIM_HandleTypeDef g_timx_pwm_chy_handle; /* 定時器x控制程式碼 */
 
 int main(void)
 {                                                
 
     uint16_t pwm_val = 0; /* pwm value ,動態調節佔空比時用到*/
     
     HAL_Init();                                 /* 初始化HAL庫,必選 */
     sys_stm32_clock_init(336, 8, 2, 7);         /* 設定時鐘,168Mhz,必選 */
     delay_init(168);                            /* 延時初始化,必選 */
     usart_init(115200);                         /* 串列埠初始化為115200,可選*/
     led_init();                                 /* 初始化 LED ,可選*/
 
     gtim_timx_pwm_chy_init(20000- 1, 168 - 1);  //20000*168/168000000=0.02s
     
  delay_ms(10);
  LED0(0); /* 上電後程式執行提示 */
  delay_ms(10);
 
     while (1)
    {
  pwm_val =1500;       /* 1500對應約90度,前提是將指標撥到與機身長邊平行 */
         __HAL_TIM_SET_COMPARE(&g_timx_pwm_chy_handle, GTIM_TIMX_PWM_CHY, pwm_val);  /* 修改比較值控制佔空比 */ delay_ms(1000);
 
  pwm_val = 500;      
         __HAL_TIM_SET_COMPARE(&g_timx_pwm_chy_handle, GTIM_TIMX_PWM_CHY, pwm_val);  /* 修改比較值控制佔空比 */
  delay_ms(1000);
 
  pwm_val = 1500;      
         __HAL_TIM_SET_COMPARE(&g_timx_pwm_chy_handle, GTIM_TIMX_PWM_CHY, pwm_val);  /* 修改比較值控制佔空比 */
  delay_ms(1000);
 
  pwm_val = 2500;      
         __HAL_TIM_SET_COMPARE(&g_timx_pwm_chy_handle, GTIM_TIMX_PWM_CHY, pwm_val);  /* 修改比較值控制佔空比 */
  delay_ms(1000);
    }
 }

4、註釋:

  4.1、此塊程式碼可以直接拿去用,也可以按照需求改 main.c 裡 while(1) 裡面的語句完成自定義控制。

  4.2、PF6 與  「ATK MODULE」 處插 「 WIFI模組——正點原子ATK ESP 01 」 佔用衝突,請務必取下WIFI模組再拷貝程式碼執行或者非要用WiFi模組那就不用PF6改用其他帶定時器pwm輸出的引腳。

== 看完請點贊,小手一點,水逆退散!!!==