STM32入门之定时器输出比较

上图为定时器输出比较的各个模式,一般常用的时PWM1模式。上表中有两个需要注意的点,第一CCR为比较值,该值的作用是用来和计数器进行数字比较来改变GPIO口输出的高低电平。第二有效电平和无效电平,这个设计非常巧妙,可以灵活的解决各种应用问题,我们可以通过设计有效电平为高电平或者低电平来适应各种应用场景。

上图为输出比较的初始化流程,主要是设置CCR和有效电平和PWM的模式。

void TIM3_PWM_Init(uint16_t pwm_duty),这里需要注意的一点是PWM输出模式引脚需要复用。

例子代码如下所示:

{

    GPIO_InitTypeDef GPIO_InitStructure;

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    TIM_OCInitTypeDef TIM_OCInitStructure;

    // 1. 开启时钟

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);     // TIM3时钟

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);    // GPIOA时钟

    // 2. 配置 PA6 为复用模式 (AF2)

    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_UP;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 3. 将 PA6 连接到 TIM3 的 AF2

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM3);

    // 4. 配置 TIM3 的基本参数(假设目标频率为1kHz)

    //    SystemCoreClock = 84MHz, 预分频为83,计数频率 = 1MHz,每1000计数1ms → 1kHz

    TIM_TimeBaseStructure.TIM_Period = 1000 - 1;          // ARR 自动重装载寄存器

    TIM_TimeBaseStructure.TIM_Prescaler = 84 - 1;         // PSC 预分频器

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    // 5. 配置 PWM 模式

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;     // PWM模式1

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStructure.TIM_Pulse = pwm_duty;             // CCR = 占空比

    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;

    TIM_OC1Init(TIM3, &TIM_OCInitStructure);

    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);     // 允许CCR预装载

    // 6. 启动定时器

    TIM_ARRPreloadConfig(TIM3, ENABLE);                   // ARR自动重装载预装载使能

    TIM_Cmd(TIM3, ENABLE);

}

这里补充一个小技巧,可以使用更新中断来控制PWM波输出的个数。

void TIM3_IRQHandler(void)

{

    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)

    {

        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);

        pwm_pulse_count++;

        if (pwm_pulse_count >= PWM_TARGET_PULSE_NUM)

        {

            TIM_Cmd(TIM3, DISABLE);            // 停止定时器

            GPIO_ResetBits(GPIOA, GPIO_Pin_6); // 拉低引脚(避免残留高电平)

        }

    }

}

那么前面也需要加入中断配置的函数:

           // 3. 清除更新中断标志

    TIM_ClearITPendingBit(TIM3, TIM_IT_Update);

    // 4. 允许 TIM2 更新中断

    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);

    // 5. 配置 NVIC

    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 13;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

上面的输出比较初始化会有一些问题,当我使用逻辑分析仪去看GPIO输出的波形时发现,会有一个5us的干扰波。根据实验发现,是因为我先初始化了GPIO然后初始化了定时器在定时器的初始化过程中就会马上运行所以会输出一个5us的杂波。如果我们先初始化定时器再初始化GPIO口,杂波就会消失。

修改之前:

修改之后:

这里经过实验可知,如果我把复用函数放在最后面也会出现杂波,放在前面则不会。说明引脚的连接会导致出现一定的杂波。

代码如下所示:

void TIM3_PWM_Init(uint16_t pwm_duty)

{

       NVIC_InitTypeDef NVIC_InitStructure;

    GPIO_InitTypeDef GPIO_InitStructure;

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    TIM_OCInitTypeDef TIM_OCInitStructure;

    // 1. 开启时钟

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);     // TIM3时钟

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);    // GPIOA时钟

        // 3. 将 PA6 连接到 TIM3 的 AF2

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM3);

    // 4. 配置 TIM3 的基本参数(假设目标频率为1kHz)

    //    SystemCoreClock = 84MHz, 预分频为83,计数频率 = 1MHz,每1000计数1ms → 1kHz

    TIM_TimeBaseStructure.TIM_Period = 1000 - 1;          // ARR 自动重装载寄存器

    TIM_TimeBaseStructure.TIM_Prescaler = 84 - 1;         // PSC 预分频器

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

      

           // 3. 清除更新中断标志

    TIM_ClearITPendingBit(TIM3, TIM_IT_Update);

    // 4. 允许 TIM2 更新中断

    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);

    // 5. 配置 NVIC

    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 13;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

      

    // 5. 配置 PWM 模式

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;     // PWM模式1

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStructure.TIM_Pulse = pwm_duty;             // CCR = 占空比

    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

    TIM_OC1Init(TIM3, &TIM_OCInitStructure);

    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);     // 允许CCR预装载

    // 6. 启动定时器

    TIM_ARRPreloadConfig(TIM3, ENABLE);                   // ARR自动重装载预装载使能

    TIM_Cmd(TIM3, ENABLE);

      

           // 2. 配置 PA6 为复用模式 (AF2)

    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_UP;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值