文章来源地址https://www.toymoban.com/news/detail-486209.html
文章来源:https://www.toymoban.com/news/detail-486209.html
-
开启定时器TIMx的时钟、通道输出的GPIO时钟(通道输出GPIO初始化、优先级设置、中断使能)。
-
初始化定时器TIMx(设置TIMx的ARR和PSC等参数)
-
设置TIMx_CHy的PWM模式(设置输出比较极性/比较值)
-
使能定时器TIMx,使能TIMx的CHy输出
-
修改TIMx_CCRy来控制占空比
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/key/key.h"
#include "./BSP/gtim/gtim.h"
#include "./BSP/led/led.h"
#include "./BSP/gpio/gpio.h"
extern TIM_HandleTypeDef g_timx_pwm_chy_handle; /* 定时器x句柄 */
int main(void)
{
uint16_t motor_up(uint16_t PwmVal);
uint16_t motor_down(uint16_t PwmVal);
uint16_t MotorPwmVal = 0;
uint8_t key;
uint8_t t = 0;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
key_init();
led_init();
in_init();
gtim_timx_pwm_chy_init(500 - 1, 72 - 1);/* 1Mhz的计数频率,2Khz的PWM */
while (1){
t++;
key = key_scan(0);
if (key == KEY0_PRES ){
if (MotorPwmVal < 250){
MotorPwmVal += 10;
LED0_TOGGLE();
}
__HAL_TIM_SET_COMPARE(&g_timx_pwm_chy_handle, GTIM_TIMX_PWM_CHY, MotorPwmVal);
}
else if (key == KEY1_PRES){
if (MotorPwmVal > 10 ){
MotorPwmVal -= 10;
LED1_TOGGLE();
}
else{
MotorPwmVal = 0;
}
__HAL_TIM_SET_COMPARE(&g_timx_pwm_chy_handle, GTIM_TIMX_PWM_CHY, MotorPwmVal);
}
delay_ms(10);
}
}
(2)key.h和key.c
#ifndef __KEY_H
#define __KEY_H
#include "./SYSTEM/sys/sys.h"
/* 引脚定义 */
#define KEY1_GPIO_PORT GPIOE
#define KEY1_GPIO_PIN GPIO_PIN_3
#define KEY1_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0) /* PE口时钟使能 */
#define KEY0_GPIO_PORT GPIOE
#define KEY0_GPIO_PIN GPIO_PIN_4
#define KEY0_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0) /* PE口时钟使能 */
/* 引脚状态读取 */
#define KEY1 HAL_GPIO_ReadPin(KEY1_GPIO_PORT, KEY1_GPIO_PIN) /* 读取KEY1引脚 */
#define KEY0 HAL_GPIO_ReadPin(KEY0_GPIO_PORT, KEY0_GPIO_PIN) /* 读取key0引脚 */
#define KEY0_PRES 1 /* KEY0按下 */
#define KEY1_PRES 2 /* KEY1按下 */
void key_init(void); /* 按键初始化函数 */
uint8_t key_scan(uint8_t mode); /* 按键扫描函数 */
#endif
#include "./BSP/key/key.h"
#include "./SYSTEM/delay/delay.h"
void key_init(void)
{
GPIO_InitTypeDef gpio_init_struct;
KEY1_GPIO_CLK_ENABLE(); /* KEY1时钟使能 */
KEY0_GPIO_CLK_ENABLE(); /* WKUP时钟使能 */
gpio_init_struct.Pin = KEY0_GPIO_PIN; /* KEY0引脚 */
gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 输入 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(KEY0_GPIO_PORT, &gpio_init_struct); /* KEY0引脚模式设置,上拉输入 */
gpio_init_struct.Pin = KEY1_GPIO_PIN; /* KEY1引脚 */
gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 输入 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(KEY1_GPIO_PORT, &gpio_init_struct); /* KEY1引脚模式设置,上拉输入 */
}
/* 按键扫描函数 */
uint8_t key_scan(uint8_t mode)
{
static uint8_t key_up = 1; /* 按键按松开标志 */
uint8_t keyval = 0;
if (mode) key_up = 1; /* 支持连按 */
if (key_up && (KEY1 == 0 ||KEY0 == 0 )) /* 按键松开标志为1, 且有任意一个按键按下了 */
{
delay_ms(10); /* 去抖动 */
key_up = 0;
if (KEY0 == 0) keyval = KEY0_PRES;
if (KEY1 == 0) keyval = KEY1_PRES;
}
else if ( KEY1 == 1 && KEY0 == 1) /* 没有任何按键按下, 标记按键松开 */
{
key_up = 1;
}
return keyval; /* 返回键值 */
}
(3)gtim.h 和 gtim.c
#ifndef __GTIM_H
#define __GTIM_H
#include "./SYSTEM/sys/sys.h"
#define GTIM_TIMX_PWM_CHY_GPIO_PORT GPIOA
#define GTIM_TIMX_PWM_CHY_GPIO_PIN GPIO_PIN_1
#define GTIM_TIMX_PWM_CHY_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) /* PB口时钟使能 */
#define GTIM_TIMX_PWM TIM2
#define GTIM_TIMX_PWM_CHY TIM_CHANNEL_2 /* 通道Y, 1<= Y <=4 */
#define GTIM_TIMX_PWM_CHY_CCRX TIM2->CCR2 /* 通道Y的输出比较寄存器 */
#define GTIM_TIMX_PWM_CHY_CLK_ENABLE() do{ __HAL_RCC_TIM2_CLK_ENABLE(); }while(0) /* TIM3 时钟使能 */
void gtim_timx_pwm_chy_init(uint16_t arr, uint16_t psc); /* 通用定时器 PWM初始化函数 */
#endif
#include "./BSP/timer/gtim.h"
TIM_HandleTypeDef g_timx_pwm_chy_handle; /* 定时器x句柄 */
void gtim_timx_pwm_chy_init(uint16_t arr, uint16_t psc)
{
TIM_OC_InitTypeDef timx_oc_pwm_chy = {0}; /* 定时器PWM输出配置 */
GTIM_TIMX_PWM_CHY_GPIO_CLK_ENABLE(); /* 使能 通道y对应的CPIO时钟 */
GTIM_TIMX_PWM_CHY_CLK_ENABLE(); /* 使能 定时器时钟*/
GPIO_InitTypeDef gpio_init_struct;
gpio_init_struct.Pin = GTIM_TIMX_PWM_CHY_GPIO_PIN; /* 通道y的CPIO口 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推完输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(GTIM_TIMX_PWM_CHY_GPIO_PORT, &gpio_init_struct);
g_timx_pwm_chy_handle.Instance = GTIM_TIMX_PWM; /* 定时器x */
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 = arr / 2; /* 设置比较值,此值用来确定占空比 */
timx_oc_pwm_chy.OCPolarity = TIM_OCPOLARITY_LOW; /* 输出比较极性为低 */
HAL_TIM_PWM_ConfigChannel(&g_timx_pwm_chy_handle, &timx_oc_pwm_chy, GTIM_TIMX_PWM_CHY); /* 配置TIMx通道y */
HAL_TIM_PWM_Start(&g_timx_pwm_chy_handle, GTIM_TIMX_PWM_CHY); /* 开启对应PWM通道 */
}
(4)led.c 和 led.h
#ifndef _LED_H
#define _LED_H
#include "./SYSTEM/sys/sys.h"
/* 引脚定义 */
#define LED0_GPIO_PORT GPIOB
#define LED0_GPIO_PIN GPIO_PIN_5
#define LED0_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) /* PB口时钟使能 */
#define LED1_GPIO_PORT GPIOE
#define LED1_GPIO_PIN GPIO_PIN_5
#define LED1_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0) /* PE口时钟使能 */
/* LED端口定义 */
#define LED0(x) do{ x ? \
HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_RESET); \
}while(0) /* LED0翻转 */
#define LED1(x) do{ x ? \
HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_RESET); \
}while(0) /* LED1翻转 */
/* LED取反定义 */
#define LED0_TOGGLE() do{ HAL_GPIO_TogglePin(LED0_GPIO_PORT, LED0_GPIO_PIN); }while(0)
#define LED1_TOGGLE() do{ HAL_GPIO_TogglePin(LED1_GPIO_PORT, LED1_GPIO_PIN); }while(0)
/* 外部接口函数*/
void led_init(void); /* 初始化 */
#endif
#include "./BSP/led/led.h"
void led_init(void)
{
GPIO_InitTypeDef gpio_init_struct;
LED0_GPIO_CLK_ENABLE(); /* LED0时钟使能 */
LED1_GPIO_CLK_ENABLE(); /* LED1时钟使能 */
gpio_init_struct.Pin = LED0_GPIO_PIN; /* LED0引脚 */
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(LED0_GPIO_PORT, &gpio_init_struct); /* 初始化LED0引脚 */
gpio_init_struct.Pin = LED1_GPIO_PIN; /* LED1引脚 */
HAL_GPIO_Init(LED1_GPIO_PORT, &gpio_init_struct); /* 初始化LED1引脚 */
LED0(1); /* 关闭 LED0 */
LED1(1); /* 关闭 LED1 */
}
(5)gpio.h和gpio.c
#ifndef __GPIO_H
#define __GPIO_H
#include "./SYSTEM/sys/sys.h"
/* 引脚 定义 */
#define IN1_GPIO_PORT GPIOF
#define IN1_GPIO_PIN GPIO_PIN_13
#define IN1_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOF_CLK_ENABLE(); }while(0)
#define IN2_GPIO_PORT GPIOF
#define IN2_GPIO_PIN GPIO_PIN_14
#define IN2_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOF_CLK_ENABLE(); }while(0)
#define STBY_GPIO_PORT GPIOF
#define STBY_GPIO_PIN GPIO_PIN_11
#define STBY_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOF_CLK_ENABLE(); }while(0)
void in_init(void);
#endif
#include "./BSP/gpio/gpio.h"
void in_init(void){
GPIO_InitTypeDef gpio_init_struct;
IN1_GPIO_CLK_ENABLE();
IN2_GPIO_CLK_ENABLE();
gpio_init_struct.Pin = IN1_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
gpio_init_struct.Pull = GPIO_PULLUP;
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(IN1_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = IN2_GPIO_PIN;
HAL_GPIO_Init(IN2_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = STBY_GPIO_PIN;
HAL_GPIO_Init(STBY_GPIO_PORT, &gpio_init_struct);
HAL_GPIO_WritePin(IN1_GPIO_PORT,IN1_GPIO_PIN,GPIO_PIN_SET);
HAL_GPIO_WritePin(IN2_GPIO_PORT,IN2_GPIO_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(STBY_GPIO_PORT,STBY_GPIO_PIN,GPIO_PIN_SET);
}
实验结果:
按键调整端口输出电压大小
按键调整电机转速大小
到了这里,关于按键调整PWM占空比,实现电机转速调整(基于STM32开发板)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!