舵机驱动——STM32F407ZGT6探索者——HAL库

舵机驱动------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输出的引脚。

== 看完请点赞,小手一点,水逆退散!!!==

相关推荐
雅典没有娜7 天前
QT/C++与LUA交互过程中,利用ZeroBraneStudio对LUA脚本进行仿真调试
c++·qt·lua·调试·仿真·zerobranestudio
泷fyk24 天前
软件开发和调试:定位错误位置
嵌入式·c·调试·addr2line
Amd7941 个月前
Nuxt.js 应用中的 dev:ssr-logs 事件钩子
开发·监控·日志·nuxt.js·调试·ssr·钩子
这个菠萝好咸1 个月前
内核源码+vscode+bear+clang实现函数任意跳转,无缝跳转,无缝阅读,无缝开发
linux·c语言·驱动开发·后端·arm单片机
CYRUS STUDIO2 个月前
adb 远程调试,手动修改 adb 调试授权信息
android·adb·调试
云中双月2 个月前
如何使用Ida Pro和Core Dump文件定位崩溃位置(Linux下无调试符号的进程专享)
linux·嵌入式·gdb·调试·gcc·崩溃·ida pro·ulimit·core dump·cross compile
skylin198401012 个月前
iOS调试真机出现的 “__llvm_profile_initialize“ 错误
ios·objective-c·调试·1024程序员节
Projectsauron2 个月前
STM32 调试之栈回溯和 CmBacktrace 的使用
stm32·嵌入式·调试·1024程序员节
zkk95272 个月前
C++调试方法(Vscode)(一) ——本地调试
开发语言·c++·vscode·gdb·调试
zkk95272 个月前
C++调试方法(Vscode)(二) ——本地调试(ROS版)
开发语言·c++·vscode·gdb·调试