[STM32G4] 使用STM32G431实现PWM信号的精确控制

[复制链接]
2255|12
 楼主| Clyde011 发表于 2024-12-15 07:55 | 显示全部楼层 |阅读模式
在嵌入式系统中,PWM(脉宽调制)信号常用于控制电机速度、调节LED亮度等场景。本文将以STM32G431微控制器为例,详细讲解如何配置TIM1定时器生成PWM信号,并通过调整占空比实现精确控制。
STM32G431简介STM32G431是ST公司推出的一款功能强大的32位微控制器,基于Cortex-M4内核,主频高达170 MHz。它内置多个高级定时器(如TIM1),支持高分辨率的PWM输出,非常适合电机控制、工业自动化和其他实时应用。
PWM信号生成原理PWM信号通过固定频率的方波控制信号强度,其占空比(即高电平持续时间与整个周期的比值)决定了输出的平均功率。例如,50%占空比表示输出信号的高低电平时间相等,而25%占空比表示高电平时间仅为整个周期的四分之一。
开发环境准备
  • STM32CubeIDE(用于编写代码和调试)。
  • STM32G431开发板。
  • 一个PWM信号测试设备(如LED或示波器)。
硬件连接将一个LED连接到开发板的PWM引脚(例如PA8),并在电路中串联一个限流电阻(如220欧姆)。
软件实现以下代码实现了使用TIM1定时器生成PWM信号,并通过调整占空比控制LED的亮度。
  1. #include "stm32g4xx_hal.h"

  2. // 定时器句柄
  3. TIM_HandleTypeDef htim1;

  4. // 初始化定时器
  5. void TIM1_Init(void) {
  6.     __HAL_RCC_TIM1_CLK_ENABLE();
  7.     htim1.Instance = TIM1;
  8.     htim1.Init.Prescaler = 170 - 1; // 定时器预分频值
  9.     htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  10.     htim1.Init.Period = 1000 - 1; // PWM周期1000个计数
  11.     htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  12.     htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  13.     HAL_TIM_PWM_Init(&htim1);

  14.     // 配置PWM输出通道
  15.     TIM_OC_InitTypeDef sConfigOC;
  16.     sConfigOC.OCMode = TIM_OCMODE_PWM1;
  17.     sConfigOC.Pulse = 500; // 初始占空比为50%
  18.     sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  19.     sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  20.     HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);

  21.     // 启动PWM
  22.     HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
  23. }

  24. // 初始化GPIO
  25. void GPIO_Init(void) {
  26.     __HAL_RCC_GPIOA_CLK_ENABLE();
  27.     GPIO_InitTypeDef GPIO_InitStruct = {0};
  28.     GPIO_InitStruct.Pin = GPIO_PIN_8; // TIM1_CH1引脚
  29.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  30.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  31.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  32.     GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
  33.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  34. }

  35. // 修改占空比
  36. void Set_PWM_DutyCycle(uint16_t dutyCycle) {
  37.     if (dutyCycle <= 1000) { // 确保占空比值合法
  38.         __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, dutyCycle);
  39.     }
  40. }

  41. int main(void) {
  42.     HAL_Init();
  43.     SystemClock_Config();
  44.     GPIO_Init();
  45.     TIM1_Init();

  46.     while (1) {
  47.         for (uint16_t duty = 0; duty <= 1000; duty += 10) {
  48.             Set_PWM_DutyCycle(duty); // 增加占空比
  49.             HAL_Delay(50);
  50.         }
  51.         for (uint16_t duty = 1000; duty > 0; duty -= 10) {
  52.             Set_PWM_DutyCycle(duty); // 减小占空比
  53.             HAL_Delay(50);
  54.         }
  55.     }
  56. }
代码解析
  • TIM1_Init函数:初始化TIM1定时器并配置PWM模式。
  • Set_PWM_DutyCycle函数:通过修改TIM1的比较寄存器(CCR1),动态调整PWM占空比。
  • 主循环:实现占空比在0%到100%之间的循环渐变,从而让LED的亮度逐渐变化。
测试与优化
  • 使用示波器测试PA8引脚的PWM输出信号,观察占空比是否随代码变化。
  • 如果需要更高的分辨率,可以调整Prescaler和Period参数,使PWM周期更精确。
小结通过STM32G431和其高级定时器TIM1,我们可以轻松生成高精度的PWM信号,并灵活调整占空比。这种方法广泛适用于工业控制、电机驱动和信号调制等场景。

公羊子丹 发表于 2024-12-15 07:56 | 显示全部楼层
看起来很详细,正好最近在学习STM32的定时器,受教了。
周半梅 发表于 2024-12-15 07:56 | 显示全部楼层
有没有遇到初始化失败的情况?想了解一下调试经验。
帛灿灿 发表于 2024-12-15 07:56 | 显示全部楼层
PWM输出能支持多高的频率?对实际应用有些好奇。
童雨竹 发表于 2024-12-15 07:57 | 显示全部楼层
LED亮度变化很流畅,这种代码结构很实用!
万图 发表于 2024-12-15 07:57 | 显示全部楼层
你觉得用STM32G4控制电机和用G0系列有什么主要区别?
Wordsworth 发表于 2024-12-15 07:58 | 显示全部楼层
如果换成其他定时器,比如TIM2,是不是改一下引脚和时钟就可以了?
Bblythe 发表于 2024-12-15 07:58 | 显示全部楼层
定时器初始化这块代码很经典,感觉可以直接用到很多项目中。
Pulitzer 发表于 2024-12-15 07:58 | 显示全部楼层
想了解更多关于STM32CubeMX生成代码的方式,能否再写一篇?
Uriah 发表于 2024-12-15 07:59 | 显示全部楼层
G4系列的PWM精度真不错,支持!
Amazingxixixi 发表于 2024-12-27 16:55 | 显示全部楼层
过来学习学习
Stahan 发表于 2024-12-29 21:40 来自手机 | 显示全部楼层
G4是专门做电机控制的吗
是你的乱码 发表于 2024-12-31 00:32 | 显示全部楼层

通过调整占空比来控制 LED 亮度

通过调整占空比来控制 LED 亮度
您需要登录后才可以回帖 登录 | 注册

本版积分规则

155

主题

5872

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部