使用 TIM4 产生一定数量的PWM 波形

应用背景:

现有的项目平台是stm32f407; 想使用PB6管脚翻转输出方波(个数2000个),但是模拟的频率不稳定;想要输出一定数量的波形可以通过PWM实现;经过查阅手册;发现 PB6正好是 TIM4_ch1 通道;TIM4: PB6 (CH1), PB7 (CH2), PA0 (CH3), PA1 (CH4);

实现思路:

问题1:平台一共有多少路pwm可以用? 普通的IO可以配置成pwm输出管脚吗?

STM32F407微控制器支持多个定时器,其中一些定时器可以用来产生PWM信号。通常,高级定时器(如TIM1和TIM8)和通用定时器(如TIM2、TIM3、TIM4和TIM5)可以配置为产生PWM输出。每个定时器通常有4个通道可用于PWM输出,但有些定时器(如TIM6和TIM7)不支持PWM输出。

STM32F407 支持的定时器及其PWM能力:

  • TIM1: 16位高级控制定时器,具有4个通道(CH1-CH4),每个通道都可以配置为PWM输出。
  • TIM8: 16位高级控制定时器,具有4个通道(CH1-CH4),每个通道都可以配置为PWM输出。
  • TIM2: 16位通用定时器,具有4个通道(CH1-CH4),每个通道都可以配置为PWM输出。
  • TIM3: 16位通用定时器,具有4个通道(CH1-CH4),每个通道都可以配置为PWM输出。
  • TIM4: 16位通用定时器,具有4个通道(CH1-CH4),每个通道都可以配置为PWM输出。
  • TIM5: 16位通用定时器,具有4个通道(CH1-CH4),每个通道都可以配置为PWM输出。

这意味着STM32F407最多可以支持多达16路独立的PWM输出(如果所有定时器都被充分利用的话)。

关于普通GPIO是否可以配置为PWM输出:

STM32F407的某些GPIO引脚可以通过配置为定时器的复用功能来产生PWM输出。并不是所有的GPIO引脚都可以配置为PWM输出,而是特定的GPIO引脚与定时器的通道相关联。例如,对于TIM2,它的通道可以映射到以下GPIO引脚:

  • TIM2 CH1: PA5
  • TIM2 CH2: PA6
  • TIM2 CH3: PA7
  • TIM2 CH4: PA0 or PB3 (取决于具体配置)

为了确定哪些GPIO引脚可以配置为PWM输出,您需要查看STM32F407的参考手册或数据手册,查找定时器通道与GPIO引脚之间的映射关系。通常,手册中的“Pinout and Pin Purpose”章节会列出这些信息。

示例:

以下是一些常见的定时器和相关的GPIO映射:

  • TIM1: PA8 (CH1), PA9 (CH2), PA10 (CH3), PB1 (CH4)
  • TIM2: PA5 (CH1), PA6 (CH2), PA7 (CH3), PA0 (CH4), PB3 (CH4)
  • TIM3: PA2 (CH1), PA3 (CH2), PB4 (CH3), PB5 (CH4)
  • TIM4: PB6 (CH1), PB7 (CH2), PA0 (CH3), PA1 (CH4)
  • TIM5: PA0 (CH1), PA1 (CH2), PA2 (CH3), PA3 (CH4)

查阅手册:

问题2:想要控制PWM 输出2000个怎么实现?

要实现PB6 (TIM4_CH1) 输出一定数量的PWM波形,例如2000个2MHz的PWM波形,您需要配置定时器TIM4,并设置适当的预分频器和计数周期以达到所需的频率。此外,您还需要一个计数器来跟踪已经输出的PWM波形的数量。

源码:

// 初始化定时器
void PWM_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    
    // 使能TIM4和GPIOB时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    // 配置GPIO PB6 (TIM4_CH1) 为复用推挽输出

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    // 配置GPIO PB6为TIM4_CH1的复用功能
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_TIM4);

    // 初始化TIM4定时器

  /* 累计 TIM_Period个后产生一个更新或者中断*/		
  //当定时器从0计数到4,即为5次,为一个定时周期  
    TIM_TimeBaseStructure.TIM_Period = 4; // 设置周期为5 (周期为2MHz)//从0计数到 5

// 设置TIM4定时器的时钟预分频器
	// 通用控制定时器时钟源TIMxCLK = HCLK/2=90MHz 
	// 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=10MHz -> 90Mhz / (9-1) + 1 = 10Mhz 
    
    TIM_TimeBaseStructure.TIM_Prescaler = 8; // 预分频器设置为8 (9-1)
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

    // 配置通道1的PWM输出
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_Pulse = 2; // 设置CCR1比较值为2, 占空比为2/5 %
    TIM_OC1Init(TIM4, &TIM_OCInitStructure); //使能通道
    TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);

    //定时器
    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 使能TIM4定时器
    TIM_Cmd(TIM4, ENABLE);

    // 使能更新中断
    TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
    //TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}



int main(void)
{


    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);   
     
	jtag_Pins_Init();

	delay_init(180);

    PWM_Init();

    delay_ms(1000);
    
    TIM_Cmd(TIM4, DISABLE); //如果定时器不计数,不终止,则直接输出1S 的PWM;
   
	return 0;
}


//stm32f4xx_it.c
#define PWM_COUNT 2000 // PWM波形的数量

volatile uint32_t pwmCounter = 0; // 用于计数已输出的PWM波形

// 更新中断服务例程
void TIM4_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
    {
        TIM_ClearITPendingBit(TIM4, TIM_IT_Update); // 清除中断标志

        // 检查是否达到了指定的PWM波形数量
        if (++pwmCounter >= PWM_COUNT)
        {
            // 达到了指定数量,停止定时器
            TIM_Cmd(TIM4, DISABLE);
        }
    }
}

验证:

  • 9
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值