12下一页
返回列表 发新帖我要提问本帖赏金: 30.00元(功能说明)

[STM32F4] 使用stm32f4 用一个定时器输出多个不同频率占空比PWM波

[复制链接]
3327|29
 楼主| poison0 发表于 2023-4-6 15:24 | 显示全部楼层 |阅读模式
本帖最后由 poison0 于 2023-4-6 15:26 编辑

#申请原创#
使用STM32F4的定时器和GPIO模块来生成多个不同频率和占空比的PWM波。下面是一个基本的步骤:

配置定时器
首先,需要配置STM32F4的定时器,以便能够生成PWM波。我们可以选择使用其中一个通道(Channel)来控制一个GPIO引脚上的PWM波,同时可以使用另一个通道来控制另一个GPIO引脚上的PWM波。

设置计数器和频率
接下来,需要设置计数器和频率。计数器的值越大,PWM波的周期就越长。而频率则决定了PWM波的频率。可以使用定时器的预分频器(Prescalr)和计数器的重载值(Auto Reload Register)来控制这些值。

配置占空比
然后,需要设置PWM波的占空比。可以通过在每个周期的不同阶段改变输出的高电平时间来实现。可以使用定时器的通道寄存器来控制输出引脚的占空比。

启动定时器
最后,需要启动定时器,以便开始生成PWM波。可以通过设置定时器的控制寄存器来启动和停止定时器。

下面是一个示例代码,可以生成两个不同频率和占空比的PWM波:
  1. c
  2. Copy code
  3. #include "stm32f4xx.h"

  4. void timer_pwm_init(void)
  5. {
  6.   TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  7.   TIM_OCInitTypeDef TIM_OCInitStructure;

  8.   // 使能时钟
  9.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  10.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

  11.   // 配置GPIO引脚
  12.   GPIO_InitTypeDef GPIO_InitStructure;
  13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
  14.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  15.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  16.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  17.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  18.   GPIO_Init(GPIOB, &GPIO_InitStructure);

  19.   GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_TIM3);
  20.   GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_TIM3);

  21.   // 配置定时器
  22.   TIM_TimeBaseStructure.TIM_Period = 1000 - 1; // 1kHz PWM
  23.   TIM_TimeBaseStructure.TIM_Prescaler = 84 - 1; // 84MHz / 84 = 1MHz
  24.   TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  25.   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  26.   TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  27.   // 配置PWM通道
  28.   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  29.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  30.   TIM_OCInitStructure.TIM_Pulse = 500; // 50% 占空比
  31.   TIM_OCInitStructure.TIM_O

大部分情况下,使用定时器生成PWM波总结为以下步骤
使用STM32F4的定时器生成PWM波可以分为以下步骤:

时钟使能
在使用定时器之前,需要先使能相应的外设时钟。例如,如果我们要使用定时器3TIM3),则需要使能TIM3的时钟和与之相关的GPIO口的时钟。具体操作可以参考芯片手册或者使用STM32CubeMX生成代码。

配置GPIO引脚
使用定时器生成PWM波需要将定时器的输出连接到GPIO引脚上。因此,需要先配置相应的GPIO引脚为复用模式,并选择定时器的输出映射到这些引脚上。具体操作可以参考芯片手册或者使用STM32CubeMX生成代码。

配置定时器基本参数
在使用定时器生成PWM波之前,需要配置定时器的基本参数,例如时钟分频器、自动重载计数器和计数模式等。这些参数的配置可以通过TIM_TimeBaseInitStruct结构体完成,具体参数的配置可以参考芯片手册或者使用STM32CubeMX生成代码。

配置PWM波的占空比
通过改变PWM波在周期中的高电平时间和低电平时间的比例,可以实现不同的占空比。在STM32F4中,可以使用定时器的比较寄存器(TIMx_CCRx)来控制占空比。具体来说,需要将比较寄存器的值设置为自动重载计数器值的一定比例,即可实现相应的占空比。

启动定时器
配置好定时器的参数之后,需要启动定时器,使其开始工作并输出PWM波。启动定时器可以通过设置TIMx_CR1寄存器中的CEN位来实现,其中CEN表示计数器使能。

下面是一个简单的代码示例,演示如何使用STM32F4的定时器生成PWM波:
  1. c
  2. Copy code
  3. #include "stm32f4xx.h"

  4. void TIM_Config(void)
  5. {
  6.   TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  7.   TIM_OCInitTypeDef TIM_OCInitStructure;

  8.   // 使能时钟
  9.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  10.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

  11.   // 配置GPIO引脚
  12.   GPIO_InitTypeDef GPIO_InitStructure;
  13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  14.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  15.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  16.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  17.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  18.   GPIO_Init(GPIOC, &GPIO_InitStructure);

  19.   GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM3);

  20.   // 配置定时器
  21.   TIM_TimeBaseStructure.TIM_Period = 999; // PWM频率 = 84MHz / (1 + 999) ≈ 84kHz
  22.   TIM_TimeBaseStructure.TIM_Prescaler = 0

修改频率与占空比

要修改PWM波的频率和占空比,需要修改定时器的相关参数,包括定时器的时钟分频、自动重载计数器值、比较寄存器值等。下面是一个简单的示例,演示如何修改PWM波的频率和占空比:
  1. c
  2. Copy code
  3. #include "stm32f4xx.h"

  4. void TIM_Config(void)
  5. {
  6.   TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  7.   TIM_OCInitTypeDef TIM_OCInitStructure;

  8.   // 使能时钟
  9.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  10.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

  11.   // 配置GPIO引脚
  12.   GPIO_InitTypeDef GPIO_InitStructure;
  13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  14.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  15.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  16.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  17.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  18.   GPIO_Init(GPIOC, &GPIO_InitStructure);

  19.   GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM3);

  20.   // 配置定时器
  21.   TIM_TimeBaseStructure.TIM_Period = 999; // PWM频率 = 84MHz / (1 + 999) ≈ 84kHz
  22.   TIM_TimeBaseStructure.TIM_Prescaler = 0;
  23.   TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  24.   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  25.   TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  26.   TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  27.   // 配置PWM波的占空比
  28.   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  29.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  30.   TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
  31.   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  32.   TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
  33.   TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
  34.   TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;

  35.   TIM_OCInitStructure.TIM_Pulse = 499; // PWM占空比 = (499+1) / (999+1) ≈ 50%
  36.   TIM_OC1Init(TIM3, &TIM_OCInitStructure);

  37.   // 启动定时器
  38.   TIM_Cmd(TIM3, ENABLE);
  39. }

  40. int main(void)
  41. {
  42.   TIM_Config();

  43.   // 修改PWM波的频率和占空比
  44.   TIM_SetAutoreload(TIM3, 3999); // PWM频率 = 84MHz / (1 + 3999) ≈ 21kHz
  45.   TIM_SetCompare1(TIM3, 1999);   // PWM占空比 = (1999+1) / (3999+1) ≈ 50%

  46.   while (1)
  47.   {
  48.   }
  49. }
在这个示例中,我们首先配置定时器3TIM3)和相应的GPIO引脚,然后使用TIM_TimeBaseInitStruct结构体配置定时器的基本参数和PWM波的占空比。

在启动定时器后,我们使用TIM_SetAutoreload()函数修改定时器的自动重载计数器值、比较寄存器值等。


以上是我在使用stm32f4 用一个定时器输出多个不同频率占空比PWM波的部分步骤和经验,欢迎大家参考,指正。


打赏榜单

21小跑堂 打赏了 30.00 元 2023-08-25
理由:恭喜通过原创审核!期待您更多的原创作品~

评论

以STM32F4为例,详细介绍了定时器输出PWM的配置,每一步的讲解较为详细,若是可以分享调试结果和源码会更好  发表于 2023-8-25 18:00
香水城 发表于 2023-4-7 16:54 | 显示全部楼层
本帖最后由 香水城 于 2023-4-9 21:54 编辑

一个定时器实现4个不同频率及占空比,是可以。

不过,没看懂你如何实现不同频率的。

基于中断方式固然可以,但有点辛苦,实用性不强。可以考虑DMA加TIMER toggle模式。
一个定时器输出4路不同频率波形的应用示例
Pretext 发表于 2023-4-10 11:46 | 显示全部楼层
你这是一个引脚输出四个不同频率的占空比?
朝生 发表于 2023-4-10 11:46 | 显示全部楼层
一个定时器,让四个引脚输出不同占空比的PWM吗?
芯路例程 发表于 2023-4-10 11:47 | 显示全部楼层
这么做的意义是什么?节省定时器吗?
Bowclad 发表于 2023-4-10 22:27 | 显示全部楼层
一个引脚不同的频率
Undshing 发表于 2023-4-11 21:44 | 显示全部楼层
同时输出吗?
 楼主| poison0 发表于 2023-4-18 12:21 | 显示全部楼层
香水城 发表于 2023-4-7 16:54
一个定时器实现4个不同频率及占空比,是可以。

不过,没看懂你如何实现不同频率的。

香水城版主推荐的文章非常棒,比我写的更有逻辑,确实有点繁琐,不太解释的清楚。我还需要多加学习。感谢!我去学习学习大佬。
 楼主| poison0 发表于 2023-4-18 12:54 | 显示全部楼层
Pretext 发表于 2023-4-10 11:46
你这是一个引脚输出四个不同频率的占空比?

一个定时器
 楼主| poison0 发表于 2023-4-18 12:55 | 显示全部楼层
芯路例程 发表于 2023-4-10 11:47
这么做的意义是什么?节省定时器吗?

不是为了节省,就是意思它有这个功能。至于最终是因为节省使用,还是因为多路使用那就看使用者了。
51xlf 发表于 2023-5-5 13:01 | 显示全部楼层
如果不是通过定时器中断计数,怎么实现的不同频率呢?
mollylawrence 发表于 2023-5-5 19:00 | 显示全部楼层
这个是需要多个定时器的吗              
wengh2016 发表于 2023-5-5 21:59 | 显示全部楼层
只能输出4中不同占空比吧。              
hilahope 发表于 2023-5-5 23:20 | 显示全部楼层
这个比较高端了。              
yeates333 发表于 2023-5-7 15:11 | 显示全部楼层
多个不同频率是怎么实现呢              
gygp 发表于 2023-5-7 17:48 | 显示全部楼层
不同频率是什么意思              
yorkbarney 发表于 2023-5-7 18:22 | 显示全部楼层
可以通过定时器中断实现。              
earlmax 发表于 2023-5-7 20:05 | 显示全部楼层
这个同一个定时器怎么实现的              
tpgf 发表于 2023-5-12 08:18 | 显示全部楼层
这种情况是不是得考虑使用io口进行模拟了啊
keaibukelian 发表于 2023-5-12 12:08 | 显示全部楼层
是一个定时器在同一时间输出不同频率的pwm波?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

82

主题

655

帖子

2

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