STM32 定时器PWM配置函数及实验

一、定时器PWM配置函数

1. HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)

功能:

启动定时器的PWM输出功能。

参数:

复制代码
htim:定时器句柄指针
Channel:PWM输出通道(TIM_CHANNEL_1~4)

特点:

启动指定通道的PWM信号输出

需要预先配置定时器为PWM模式

计数器开始运行,产生PWM波形

可以单独启动每个通道

2. __HAL_TIM_SET_COMPARE(HANDLE, CHANNEL, COMPARE)

功能:

设置定时器通道的比较值(捕获/比较寄存器CCR)。

参数:

复制代码
__HANDLE__:定时器句柄
__CHANNEL__:定时器通道
__COMPARE__:比较值

特点:

这是一个宏定义,直接操作CCR寄存器

用于动态调整PWM占空比

立即生效,无需停止PWM输出

比较值应小于等于自动重装载值(ARR)

二、舵机控制实验

1. 按键原理图

2. 实验现象

通过两个按键控制舵机的转动角度:按下PA0按键时舵机角度增加(脉冲宽度增加500us),按下PC13按键时舵机角度减小(脉冲宽度减少500us)。舵机的控制脉冲宽度在500us到2500us范围内变化,每次按键按下后PWM输出立即更新,并有300ms延时和按键释放检测防止误触发。通过改变TIM3通道3的PWM比较值来精确控制舵机的位置。

3. 示例代码

GPIO初始化

复制代码
/**
  * @brief  GPIO初始化函数
  */
void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};  // GPIO配置结构体

  // 使能GPIO端口时钟
  __HAL_RCC_GPIOC_CLK_ENABLE();  // 使能GPIOC时钟
  __HAL_RCC_GPIOD_CLK_ENABLE();  // 使能GPIOD时钟
  __HAL_RCC_GPIOA_CLK_ENABLE();  // 使能GPIOA时钟
  __HAL_RCC_GPIOB_CLK_ENABLE();  // 使能GPIOB时钟

  // 配置PC13为输入引脚(角度减小按键)
  GPIO_InitStruct.Pin = GPIO_PIN_13;       // 引脚13
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;  // 输入模式
  GPIO_InitStruct.Pull = GPIO_NOPULL;      // 无上拉下拉
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);  // 初始化PC13

  // 配置PA0为输入引脚(角度增加按键)
  GPIO_InitStruct.Pin = GPIO_PIN_0;        // 引脚0
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;  // 输入模式
  GPIO_InitStruct.Pull = GPIO_NOPULL;      // 无上拉下拉
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);  // 初始化PA0
}

TIM初始化

复制代码
/**
  * @brief  TIM3定时器初始化函数(PWM模式)
  */
void MX_TIM3_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig = {0};  // 主模式配置结构体
  TIM_OC_InitTypeDef sConfigOC = {0};           // 输出比较配置结构体

  // 定时器基础配置
  htim3.Instance = TIM3;                           // 定时器实例TIM3
  htim3.Init.Prescaler = 72-1;                     // 预分频值71(72分频)
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;     // 向上计数模式
  htim3.Init.Period = 20000-1;                     // 自动重装载值19999(20ms周期)
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 时钟分频(不分频)
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; // 使能自动重装载预装载
  
  // 初始化定时器PWM模式
  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
  {
    Error_Handler();  // 错误处理
  }

  // 配置主模式
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;        // 主模式触发输出复位
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; // 禁用主从模式
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();  // 错误处理
  }

  // 配置PWM通道参数
  sConfigOC.OCMode = TIM_OCMODE_PWM1;          // PWM模式1
  sConfigOC.Pulse = 0;                         // 初始脉冲宽度为0
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;  // 输出极性高
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;   // 禁用快速模式
  
  // 配置PWM通道3
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();  // 错误处理
  }
  
  // 定时器MSP后初始化(通常用于GPIO配置)
  HAL_TIM_MspPostInit(&htim3);
}

主函数

复制代码
// 舵机控制参数定义
#define sg_step  500    // 舵机角度步进值(单位:微秒)
#define sg_min 500      // 舵机最小脉冲宽度(0.5ms)
#define sg_max  2500    // 舵机最大脉冲宽度(2.5ms)
uint16_t sg = 500;      // 当前舵机脉冲宽度值

// 系统时钟配置函数声明
void SystemClock_Config(void);

/**
  * @brief  应用程序主函数
  * @retval int
  */
int main(void)
{
  // HAL库初始化
  HAL_Init();

  // 系统时钟配置
  SystemClock_Config();

  // 初始化所有配置的外设
  MX_GPIO_Init();   // GPIO初始化
  MX_TIM3_Init();   // TIM3定时器初始化(PWM模式)

  // 启动TIM3通道3的PWM输出
  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);

  // 主循环
  while (1)
  {
    // 检测PA0按键(角度增加)
    if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET)
    {
      // 检查是否超出最大角度限制
      if(sg + sg_step <= sg_max)
      {
        sg += sg_step;  // 增加脉冲宽度
      }
      // 更新PWM比较值(改变舵机角度)
      __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, sg);
      HAL_Delay(300);  // 延时防抖
      // 等待按键释放
      while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET);
    }
    
    // 检测PC13按键(角度减小)
    if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_SET)
    {
      // 检查是否超出最小角度限制
      if(sg - sg_step >= sg_min)
      {
        sg -= sg_step;  // 减小脉冲宽度
      }
      // 更新PWM比较值(改变舵机角度)
      __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, sg);
      HAL_Delay(300);  // 延时防抖
      // 等待按键释放
      while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_SET);
    }
  }
}

三、呼吸灯实验

1. LED原理图

2. 实验现象

TIM2定时器的三个PWM通道(2、3、4)同时控制三路LED,通过变量aaa从0到1000循环递增递减,每5毫秒改变一次PWM占空比。LED亮度会平滑地从最暗逐渐增强到最亮,然后再逐渐减弱到最暗,形成同步的呼吸灯效果。

3.示例代码

GPIO初始化

复制代码
/**
  * @brief  GPIO初始化函数
  */
void MX_GPIO_Init(void)
{
  // 使能GPIO端口时钟
  __HAL_RCC_GPIOC_CLK_ENABLE();  // 使能GPIOC时钟
  __HAL_RCC_GPIOD_CLK_ENABLE();  // 使能GPIOD时钟
  __HAL_RCC_GPIOA_CLK_ENABLE();  // 使能GPIOA时钟
}

TIM初始化

复制代码
/**
  * @brief  TIM2定时器初始化函数(PWM模式)
  */
void MX_TIM2_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig = {0};  // 主模式配置结构体
  TIM_OC_InitTypeDef sConfigOC = {0};           // 输出比较配置结构体

  // 定时器基础配置
  htim2.Instance = TIM2;                           // 定时器实例TIM2
  htim2.Init.Prescaler = 72-1;                     // 预分频值71(72分频)
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;     // 向上计数模式
  htim2.Init.Period = 1000-1;                      // 自动重装载值999(PWM周期)
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 时钟分频(不分频)
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; // 禁用自动重装载预装载
  
  // 初始化定时器PWM模式
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();  // 错误处理
  }

  // 配置主模式
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;        // 主模式触发输出复位
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; // 禁用主从模式
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();  // 错误处理
  }

  // 配置PWM通道参数
  sConfigOC.OCMode = TIM_OCMODE_PWM1;          // PWM模式1
  sConfigOC.Pulse = 0;                         // 初始脉冲宽度为0
  sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;   // 输出极性低(低电平有效)
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;   // 禁用快速模式
  
  // 配置PWM通道2
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();  // 错误处理
  }
  
  // 配置PWM通道3(使用相同参数)
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();  // 错误处理
  }
  
  // 配置PWM通道4(使用相同参数)
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();  // 错误处理
  }
  
  // 定时器MSP后初始化(用于GPIO引脚配置)
  HAL_TIM_MspPostInit(&htim2);
}

主函数

复制代码
uint32_t aaa = 0;     // PWM占空比控制变量(0-1000范围)
int8_t bbb = 10;      // 占空比变化步进值(正负控制增减方向)

// 系统时钟配置函数声明
void SystemClock_Config(void);

/**
  * @brief  应用程序主函数
  * @retval int
  */
int main(void)
{
  // HAL库初始化
  HAL_Init();

  // 系统时钟配置
  SystemClock_Config();

  // 初始化所有配置的外设
  MX_GPIO_Init();   // GPIO初始化
  MX_TIM2_Init();   // TIM2定时器初始化(PWM模式)

  // 启动TIM2的三个PWM输出通道
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);  // 启动通道2
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);  // 启动通道3
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);  // 启动通道4

  // 主循环
  while (1)
  {
    // 同时设置三个PWM通道的比较值(同步控制三个LED亮度)
    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, aaa);
    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, aaa);
    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, aaa);
    
    // 更新占空比变量
    aaa += bbb;
    
    // 边界检查:达到最大值时改为递减
    if(aaa >= 1000)
    {
      bbb = -10;  // 改变方向为递减
    }
    
    // 边界检查:达到最小值时改为递增
    if(aaa <= 0)
    {
      bbb = 10;   // 改变方向为递增
    }
    
    // 延时5ms控制呼吸速度
    HAL_Delay(5);
  }
}
相关推荐
三佛科技-134163842124 小时前
KP32511SGA固定12V输出小家电电源芯片 典型应用电路
单片机·嵌入式硬件
xingzhemengyou15 小时前
STM32启动流程
stm32·单片机·嵌入式硬件
aduzhe5 小时前
int32 - int32MAX 出现异常
c语言·stm32
youcans_5 小时前
【动手学STM32G4】(4)STM32G431之ADC与DAC
stm32·单片机·嵌入式硬件·数据采集·串口通信
boneStudent8 小时前
Day32:SPI 配置与使用
stm32·单片机·嵌入式硬件
逆小舟9 小时前
【RTOS】处理中断
单片机·嵌入式硬件
ACP广源盛139246256739 小时前
GSV1015@ACP#1015/2015产品规格详解及产品应用分享
单片机·嵌入式硬件·音视频
三品吉他手会点灯10 小时前
STM32F103学习笔记-19-SysTick-系统定时器(第1节)-功能框图讲解和优先级配置
笔记·stm32·单片机·嵌入式硬件·学习
风哥在风中10 小时前
与防静电腕带完全不同性质:电烙铁必须硬接地,而且良好接地
单片机·嵌入式硬件·智能硬件·esd防护·iot硬件