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

[复制链接]
1509|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输出引脚),负极通过限流电阻接地。

代码实现以下是完整代码:
  1. #include "main.h"

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

  6. void SystemClock_Config(void);
  7. static void MX_GPIO_Init(void);
  8. static void MX_TIM3_Init(void);
  9. static void MX_USART2_UART_Init(void);

  10. int main(void)
  11. {
  12.     HAL_Init();
  13.     SystemClock_Config();
  14.     MX_GPIO_Init();
  15.     MX_TIM3_Init();
  16.     MX_USART2_UART_Init();

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

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

  23.     while (1)
  24.     {
  25.         // 主循环空闲,可扩展其他逻辑
  26.     }
  27. }

  28. // UART中断回调函数
  29. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  30. {
  31.     if (huart->Instance == USART2)
  32.     {
  33.         if (rx_data[0] >= '0' && rx_data[0] <= '9') // 检查输入是否为数字
  34.         {
  35.             duty_cycle = (rx_data[0] - '0') * 10; // 转换占空比(0-100)
  36.             __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, duty_cycle); // 更新占空比
  37.         }
  38.         // 重新开启接收中断
  39.         HAL_UART_Receive_IT(&huart2, rx_data, 1);
  40.     }
  41. }

  42. // 定时器3初始化
  43. static void MX_TIM3_Init(void)
  44. {
  45.     TIM_OC_InitTypeDef sConfigOC = {0};
  46.     TIM_ClockConfigTypeDef sClockSourceConfig = {0};

  47.     htim3.Instance = TIM3;
  48.     htim3.Init.Prescaler = 84 - 1; // 1 MHz计数频率
  49.     htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  50.     htim3.Init.Period = 100 - 1; // PWM频率为10 kHz
  51.     htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  52.     htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  53.     if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  54.     {
  55.         Error_Handler();
  56.     }
  57.     if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
  58.     {
  59.         Error_Handler();
  60.     }

  61.     sConfigOC.OCMode = TIM_OCMODE_PWM1;
  62.     sConfigOC.Pulse = 50; // 初始占空比50%
  63.     sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  64.     sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  65.     if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  66.     {
  67.         Error_Handler();
  68.     }
  69. }

  70. // USART2初始化
  71. static void MX_USART2_UART_Init(void)
  72. {
  73.     huart2.Instance = USART2;
  74.     huart2.Init.BaudRate = 9600;
  75.     huart2.Init.WordLength = UART_WORDLENGTH_8B;
  76.     huart2.Init.StopBits = UART_STOPBITS_1;
  77.     huart2.Init.Parity = UART_PARITY_NONE;
  78.     huart2.Init.Mode = UART_MODE_TX_RX;
  79.     huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  80.     huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  81.     if (HAL_UART_Init(&huart2) != HAL_OK)
  82.     {
  83.         Error_Handler();
  84.     }
  85. }

  86. // GPIO初始化
  87. static void MX_GPIO_Init(void)
  88. {
  89.     GPIO_InitTypeDef GPIO_InitStruct = {0};
  90.     __HAL_RCC_GPIOA_CLK_ENABLE();
  91.     GPIO_InitStruct.Pin = GPIO_PIN_6;
  92.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  93.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  94.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  95.     GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
  96.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  97. }

  98. // 错误处理函数
  99. void Error_Handler(void)
  100. {
  101.     while (1)
  102.     {
  103.         // 错误状态指示
  104.     }
  105. }
代码说明
  • 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学起来没想象中那么难,多谢分享!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

166

主题

6174

帖子

1

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