Wordsworth 发表于 2024-11-27 08:02

STM32F407ZG入门指南:简单的PWM信号生成与应用

STM32F407ZG是一款基于Arm Cortex-M4架构的高性能微控制器,运行主频高达168 MHz,内置丰富的外设资源和强大的定时器功能,非常适合需要精确时序控制的应用场景,比如电机驱动、LED调光和信号发生器。
本文将通过配置STM32F407ZG的定时器(Timer),实现一个简单的PWM信号生成,并应用于控制LED的亮度。希望通过这篇文章,帮助初学者快速掌握PWM的基本概念和STM32的实现方法。
准备工作硬件准备:

[*]STM32F407ZG开发板(如STM32F4 Discovery或Nucleo-F407ZG)。
[*]一个LED及其限流电阻(也可以直接使用板载LED)。
软件工具:

[*]STM32CubeIDE或Keil MDK(本文基于STM32CubeIDE)。
[*]STM32CubeMX,用于生成初始化代码。
项目目标
[*]配置Timer 3生成PWM信号。
[*]调节PWM占空比控制LED亮度。
[*]通过USART调试,实时调整占空比。
硬件连接
[*]使用板载LED时,无需额外连接,板载LED连接在PC13上。
[*]如果使用外接LED,将LED正极接PA6(Timer 3的Channel 1输出引脚),负极通过限流电阻接地。
代码实现以下是完整代码:
#include "main.h"

TIM_HandleTypeDef htim3; // 定时器3句柄
UART_HandleTypeDef huart2; // UART句柄
uint8_t rx_data; // 接收数据缓冲区
volatile uint8_t duty_cycle = 50; // 初始占空比,50%

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM3_Init(void);
static void MX_USART2_UART_Init(void);

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_TIM3_Init();
    MX_USART2_UART_Init();

    // 开始PWM输出
    HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
    // 设置初始占空比
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, duty_cycle);

    // 开启UART接收中断
    HAL_UART_Receive_IT(&huart2, rx_data, 1);

    while (1)
    {
      // 主循环空闲,可扩展其他逻辑
    }
}

// UART中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART2)
    {
      if (rx_data >= '0' && rx_data <= '9') // 检查输入是否为数字
      {
            duty_cycle = (rx_data - '0') * 10; // 转换占空比(0-100)
            __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, duty_cycle); // 更新占空比
      }
      // 重新开启接收中断
      HAL_UART_Receive_IT(&huart2, rx_data, 1);
    }
}

// 定时器3初始化
static void MX_TIM3_Init(void)
{
    TIM_OC_InitTypeDef sConfigOC = {0};
    TIM_ClockConfigTypeDef sClockSourceConfig = {0};

    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 84 - 1; // 1 MHz计数频率
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim3.Init.Period = 100 - 1; // PWM频率为10 kHz
    htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
    {
      Error_Handler();
    }
    if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
    {
      Error_Handler();
    }

    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 50; // 初始占空比50%
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
    {
      Error_Handler();
    }
}

// USART2初始化
static void MX_USART2_UART_Init(void)
{
    huart2.Instance = USART2;
    huart2.Init.BaudRate = 9600;
    huart2.Init.WordLength = UART_WORDLENGTH_8B;
    huart2.Init.StopBits = UART_STOPBITS_1;
    huart2.Init.Parity = UART_PARITY_NONE;
    huart2.Init.Mode = UART_MODE_TX_RX;
    huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart2.Init.OverSampling = UART_OVERSAMPLING_16;
    if (HAL_UART_Init(&huart2) != HAL_OK)
    {
      Error_Handler();
    }
}

// GPIO初始化
static void MX_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

// 错误处理函数
void Error_Handler(void)
{
    while (1)
    {
      // 错误状态指示
    }
}
代码说明
[*]PWM信号生成:


[*]使用定时器3的通道1生成PWM信号,频率为10 kHz。
[*]初始占空比为50%,通过UART输入调整占空比。
[*]UART通信:


[*]接收用户输入的数字(0-9),实时调整PWM信号的占空比。
[*]可扩展性:


[*]可以添加更多UART命令实现频率调节或切换其他功能。
项目验证
[*]将代码烧录到STM32F407ZG开发板。
[*]使用串口助手(如PuTTY)连接USART2,波特率设置为9600。
[*]在串口中输入0-9,观察LED亮度随占空比变化。
总结通过本项目,您可以初步掌握STM32的PWM生成与应用。STM32F407ZG的高性能和灵活性使其能够满足多种嵌入式需求。如果进一步扩展,可以尝试多通道PWM生成或结合ADC实现闭环控制。

公羊子丹 发表于 2024-11-27 08:02

这教程真不错,刚好我有个F407的板子可以试试!

周半梅 发表于 2024-11-27 08:03

原来PWM这么简单就能实现了,学到了!

帛灿灿 发表于 2024-11-27 08:03

能不能教下用ADC采集值动态调整占空比?感觉很有用!

童雨竹 发表于 2024-11-27 08:03

这个串口调试功能太方便了,我再也不用频繁刷代码了

万图 发表于 2024-11-27 08:03

请问能不能扩展到两个LED的控制啊?看起来挺好玩的!

Wordsworth 发表于 2024-11-27 08:03

写得真详细,期待下一篇关于定时器中断的应用!

Bblythe 发表于 2024-11-27 08:04

如果PWM频率改成1 kHz,会不会影响占空比控制效果?

Pulitzer 发表于 2024-11-27 08:04

有机会能分享一下用FreeRTOS结合PWM的例子吗?

Uriah 发表于 2024-11-27 08:04

F407性能真强,除了PWM还能玩点什么?

Clyde011 发表于 2024-11-27 08:04

发现STM32学起来没想象中那么难,多谢分享!
页: [1]
查看完整版本: STM32F407ZG入门指南:简单的PWM信号生成与应用