打印
[STM32F7]

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

[复制链接]
39|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Wordsworth|  楼主 | 2024-11-27 08:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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[1]; // 接收数据缓冲区
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] >= '0' && rx_data[0] <= '9') // 检查输入是否为数字
        {
            duty_cycle = (rx_data[0] - '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采集值动态调整占空比?感觉很有用!

使用特权

评论回复
5
童雨竹| | 2024-11-27 08:03 | 只看该作者
这个串口调试功能太方便了,我再也不用频繁刷代码了

使用特权

评论回复
6
万图| | 2024-11-27 08:03 | 只看该作者
请问能不能扩展到两个LED的控制啊?看起来挺好玩的!

使用特权

评论回复
7
Wordsworth|  楼主 | 2024-11-27 08:03 | 只看该作者
写得真详细,期待下一篇关于定时器中断的应用!

使用特权

评论回复
8
Bblythe| | 2024-11-27 08:04 | 只看该作者
如果PWM频率改成1 kHz,会不会影响占空比控制效果?

使用特权

评论回复
9
Pulitzer| | 2024-11-27 08:04 | 只看该作者
有机会能分享一下用FreeRTOS结合PWM的例子吗?

使用特权

评论回复
10
Uriah| | 2024-11-27 08:04 | 只看该作者
F407性能真强,除了PWM还能玩点什么?

使用特权

评论回复
11
Clyde011| | 2024-11-27 08:04 | 只看该作者
发现STM32学起来没想象中那么难,多谢分享!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

31

主题

3665

帖子

1

粉丝