STMicroelectronics 系列:STM32G4 系列_(4).STM32G4系列定时器详解

STM32G4系列定时器详解

1. 定时器概述

STM32G4 系列微控制器提供了多种定时器,包括基本定时器、通用定时器、高级定时器和低功耗定时器。这些定时器在不同的应用场景中发挥着重要作用,例如精确的时间控制、脉冲宽度调制(PWM)生成、输入捕获等。本节将详细介绍这些定时器的基本原理和应用场景。

1.1 定时器类型

  • 基本定时器(Timers 6 and 14):主要用于简单的时间延迟和周期性事件触发。

  • 通用定时器(Timers 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13):提供了丰富的功能,包括 PWM 生成、输入捕获、死区时间控制等。

  • 高级定时器(Timers 1 and 8):专为复杂电机控制应用设计,支持多种 PWM 模式、死区时间设置和互补输出。

  • 低功耗定时器(Timers 5, 6, 14):在低功耗模式下仍能保持运行,适合需要节能的应用。

  • 1.2 定时器的基本原理

    定时器通过一个递增或递减的计数器来实现时间的测量。计数器的工作频率由定时器时钟源(TIMxCLK)除以预分频器(PSC)值得到。当计数器达到设定的周期值(ARR)时,定时器会产生一个更新事件,可以触发中断或 DMA 请求。

    1.3 定时器的主要寄存器

  • 控制寄存器(CR1, CR2):用于配置定时器的基本工作模式。

  • 预分频器寄存器(PSC):设置计数器的分频值。

  • 自动重装载寄存器(ARR):设置计数器的周期值。

  • 捕获/比较寄存器(CCR1, CCR2, CCR3, CCR4):用于设置 PWM 输出或输入捕获的比较值。

  • 状态寄存器(SR):反映定时器的当前状态。

  • 中断使能寄存器(DIER):用于使能或禁止定时器中断。

  • 事件生成寄存器(EGR):用于手动触发定时器事件。

  • DMA 请求使能寄存器(DMAR):用于使能或禁止 DMA 请求。

  • 配置寄存器(CCMR1, CCMR2):用于配置捕获/比较通道的模式。

  • 捕获/比较使能寄存器(CCER):用于配置捕获/比较通道的极性和使能状态。

  • 定时器外设寄存器(TIMx):包含上述所有寄存器,用于配置和控制定时器。

  • 2. 基本定时器

    2.1 基本定时器的特点

    基本定时器(Timers 6 and 14)相对简单,主要用于生成周期性的中断或事件,适用于简单的时间延迟和周期性任务控制。它们不支持 PWM 输出和输入捕获功能。

    2.2 基本定时器的配置

    2.2.1 时钟配置

    基本定时器的时钟源可以是内部时钟或外部时钟。通常使用内部时钟,例如 APB1 时钟。

    
    // 使能定时器 6 的时钟
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
    
    
    2.2.2 预分频器和自动重装载寄存器配置

    预分频器(PSC)和自动重装载寄存器(ARR)决定了定时器的周期和频率。

    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
    
    
    TIM_TimeBaseStructure.TIM_Period = 999; // 周期值
    
    TIM_TimeBaseStructure.TIM_Prescaler = 168 - 1; // 预分频器值
    
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; // 时钟分频
    
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 计数器模式
    
    
    
    TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
    
    
    2.2.3 中断配置

    配置定时器中断,使其在计数器溢出时触发。

    
    TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
    
    
    
    // 使能定时器 6
    
    TIM_Cmd(TIM6, ENABLE);
    
    
    
    // 配置 NVIC 以处理定时器 6 中断
    
    NVIC_InitTypeDef NVIC_InitStructure;
    
    NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn;
    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    
    NVIC_Init(&NVIC_InitStructure);
    
    
    2.2.4 中断处理函数

    编写中断处理函数,处理定时器 6 的更新事件。

    
    void TIM6_DAC_IRQHandler(void) {
    
        if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) {
    
            // 处理更新事件
    
            TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
    
        }
    
    }
    
    

    2.3 基本定时器的应用示例

    2.3.1 周期性中断

    使用基本定时器 6 生成每 1 秒一次的中断。

    
    #include "stm32g4xx.h"
    
    
    
    // 定义中断处理函数
    
    void TIM6_DAC_IRQHandler(void) {
    
        if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) {
    
            // 处理更新事件
    
            TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
    
            // 执行周期性任务
    
        }
    
    }
    
    
    
    int main(void) {
    
        // 使能定时器 6 的时钟
    
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
    
    
    
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
        NVIC_InitTypeDef NVIC_InitStructure;
    
    
    
        // 配置定时器 6
    
        TIM_TimeBaseStructure.TIM_Period = 9999; // 10000 - 1
    
        TIM_TimeBaseStructure.TIM_Prescaler = 16800 - 1; // 16800 - 1
    
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    
    
    
        TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
    
    
    
        // 使能定时器 6 的更新中断
    
        TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
    
    
    
        // 使能定时器 6
    
        TIM_Cmd(TIM6, ENABLE);
    
    
    
        // 配置 NVIC 以处理定时器 6 中断
    
        NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn;
    
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    
        NVIC_Init(&NVIC_InitStructure);
    
    
    
        while (1) {
    
            // 主循环
    
        }
    
    }
    
    

    3. 通用定时器

    3.1 通用定时器的特点

    通用定时器(Timers 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13)功能丰富,适用于多种应用场景,包括 PWM 生成、输入捕获、死区时间控制等。它们通常有 4 个捕获/比较通道。

    3.2 通用定时器的配置

    3.2.1 时钟配置

    通用定时器的时钟源同样可以是内部时钟或外部时钟。通常使用内部时钟,例如 APB1 时钟。

    
    // 使能定时器 2 的时钟
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    
    
    3.2.2 预分频器和自动重装载寄存器配置

    配置预分频器(PSC)和自动重装载寄存器(ARR)以设置定时器的周期和频率。

    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
    
    
    TIM_TimeBaseStructure.TIM_Period = 999; // 周期值
    
    TIM_TimeBaseStructure.TIM_Prescaler = 8400 - 1; // 预分频器值
    
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; // 时钟分频
    
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 计数器模式
    
    
    
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    
    
    3.2.3 捕获/比较通道配置

    配置捕获/比较通道,用于 PWM 输出或输入捕获。

    
    TIM_OCInitTypeDef TIM_OCInitStructure;
    
    
    
    // 配置通道 1 为 PWM 模式
    
    TIM_OCStructInit(&TIM_OCInitStructure);
    
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    
    TIM_OCInitStructure.TIM_Pulse = 500; // PWM 脉冲宽度
    
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    
    
    
    TIM_OC1Init(TIM2, &TIM_OCInitStructure);
    
    TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
    
    
    3.2.4 中断配置

    配置定时器中断,使其在特定事件时触发。

    
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    
    
    
    // 使能定时器 2
    
    TIM_Cmd(TIM2, ENABLE);
    
    
    
    // 配置 NVIC 以处理定时器 2 中断
    
    NVIC_InitTypeDef NVIC_InitStructure;
    
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    
    NVIC_Init(&NVIC_InitStructure);
    
    
    3.2.5 中断处理函数

    编写中断处理函数,处理定时器 2 的更新事件。

    
    void TIM2_IRQHandler(void) {
    
        if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
    
            // 处理更新事件
    
            TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    
        }
    
    }
    
    

    3.3 通用定时器的应用示例

    3.3.1 PWM 输出

    使用通用定时器 2 生成 PWM 信号。

    
    #include "stm32g4xx.h"
    
    
    
    void TIM2_PWM_Init(void) {
    
        // 使能定时器 2 的时钟
    
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    
    
    
        // 使能 GPIOA 的时钟
    
        RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_GPIOA, ENABLE);
    
    
    
        // 配置 PA0 为复用推挽输出
    
        GPIO_InitTypeDef GPIO_InitStructure;
    
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    
    
        // 配置通道 1 为 TIM2
    
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM2);
    
    
    
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
        TIM_OCInitTypeDef TIM_OCInitStructure;
    
    
    
        // 配置定时器 2
    
        TIM_TimeBaseStructure.TIM_Period = 999; // 周期值
    
        TIM_TimeBaseStructure.TIM_Prescaler = 8400 - 1; // 预分频器值
    
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    
    
    
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    
    
    
        // 配置通道 1 为 PWM 模式
    
        TIM_OCStructInit(&TIM_OCInitStructure);
    
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    
        TIM_OCInitStructure.TIM_Pulse = 500; // PWM 脉冲宽度
    
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    
    
    
        TIM_OC1Init(TIM2, &TIM_OCInitStructure);
    
        TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
    
    
    
        // 使能定时器 2
    
        TIM_Cmd(TIM2, ENABLE);
    
    }
    
    
    
    int main(void) {
    
        TIM2_PWM_Init();
    
    
    
        while (1) {
    
            // 主循环
    
        }
    
    }
    
    
    3.3.2 输入捕获

    使用通用定时器 2 进行输入捕获,测量外部信号的频率或脉宽。

    
    #include "stm32g4xx.h"
    
    
    
    void TIM2_InputCapture_Init(void) {
    
        // 使能定时器 2 的时钟
    
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    
    
    
        // 使能 GPIOA 的时钟
    
        RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_GPIOA, ENABLE);
    
    
    
        // 配置 PA0 为输入模式
    
        GPIO_InitTypeDef GPIO_InitStructure;
    
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    
    
        // 配置通道 1 为输入捕获模式
    
        TIM_ICInitTypeDef TIM_ICInitStructure;
    
    
    
        TIM_ICStructInit(&TIM_ICInitStructure);
    
        TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
    
        TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    
        TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    
        TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    
        TIM_ICInitStructure.TIM_ICFilter = 0;
    
    
    
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
        TIM_TimeBaseStructure.TIM_Period = 65535; // 周期值
    
        TIM_TimeBaseStructure.TIM_Prescaler = 84 - 1; // 预分频器值
    
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    
    
    
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    
        TIM_ICInit(TIM2, &TIM_ICInitStructure);
    
    
    
        // 使能输入捕获中断
    
        TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
    
    
    
        // 使能定时器 2
    
        TIM_Cmd(TIM2, ENABLE);
    
    
    
        // 配置 NVIC 以处理定时器 2 中断
    
        NVIC_InitTypeDef NVIC_InitStructure;
    
        NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    
        NVIC_Init(&NVIC_InitStructure);
    
    }
    
    
    
    void TIM2_IRQHandler(void) {
    
        if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) {
    
            // 读取捕获值
    
            uint32_t capture_value = TIM_GetCapture1(TIM2);
    
    
    
            // 处理捕获值
    
            // 例如,计算脉宽或频率
    
    
    
            // 清除捕获中断标志
    
            TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
    
        }
    
    }
    
    
    
    int main(void) {
    
        TIM2_InputCapture_Init();
    
    
    
        while (1) {
    
            // 主循环
    
        }
    
    }
    
    

    4. 高级定时器

    4.1 高级定时器的特点

    高级定时器(Timers 1 and 8)专为复杂电机控制应用设计,支持多种 PWM 模式、死区时间设置和互补输出。它们通常有 4 个捕获/比较通道,并支持更多的中断和事件。

    4. 高级定时器

    4.1 高级定时器的特点

    高级定时器(Timers 1 and 8)专为复杂电机控制应用设计,支持多种 PWM 模式、死区时间设置和互补输出。它们通常有 4 个捕获/比较通道,并支持更多的中断和事件。这些定时器在电机控制、电源控制和其他需要精确时序控制的应用中非常有用。

    4.2 高级定时器的配置

    4.2.1 时钟配置

    高级定时器的时钟源同样可以是内部时钟或外部时钟。通常使用内部时钟,例如 APB2 时钟。以下是一个示例,使能定时器 1 的时钟:

    
    // 使能定时器 1 的时钟
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
    
    
    4.2.2 预分频器和自动重装载寄存器配置

    配置预分频器(PSC)和自动重装载寄存器(ARR)以设置定时器的周期和频率。以下是一个示例,配置定时器 1 的周期和预分频器:

    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
    
    
    TIM_TimeBaseStructure.TIM_Period = 999; // 周期值
    
    TIM_TimeBaseStructure.TIM_Prescaler = 8400 - 1; // 预分频器值
    
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; // 时钟分频
    
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 计数器模式
    
    
    
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
    
    
    4.2.3 捕获/比较通道配置

    配置捕获/比较通道,用于 PWM 输出或输入捕获。以下是一个示例,配置通道 1 为 PWM 模式:

    
    TIM_OCInitTypeDef TIM_OCInitStructure;
    
    
    
    // 配置通道 1 为 PWM 模式
    
    TIM_OCStructInit(&TIM_OCInitStructure);
    
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    
    TIM_OCInitStructure.TIM_Pulse = 500; // PWM 脉冲宽度
    
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    
    
    
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);
    
    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
    
    
    4.2.4 死区时间配置

    配置死区时间,用于防止电机驱动中的直通现象。以下是一个示例,配置定时器 1 的死区时间:

    
    TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
    
    
    
    TIM_BDTRStructInit(&TIM_BDTRInitStructure);
    
    TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSR_Enable;
    
    TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSI_Enable;
    
    TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
    
    TIM_BDTRInitStructure.TIM_DeadTime = 128; // 死区时间值
    
    TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
    
    TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
    
    TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
    
    
    
    TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
    
    
    4.2.5 中断配置

    配置定时器中断,使其在特定事件时触发。以下是一个示例,配置定时器 1 的更新中断:

    
    TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
    
    
    
    // 使能定时器 1
    
    TIM_Cmd(TIM1, ENABLE);
    
    
    
    // 配置 NVIC 以处理定时器 1 中断
    
    NVIC_InitTypeDef NVIC_InitStructure;
    
    NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM16_IRQn;
    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    
    NVIC_Init(&NVIC_InitStructure);
    
    
    4.2.6 中断处理函数

    编写中断处理函数,处理定时器 1 的更新事件。以下是一个示例:

    
    void TIM1_UP_TIM16_IRQHandler(void) {
    
        if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) {
    
            // 处理更新事件
    
            TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
    
        }
    
    }
    
    

    4.3 高级定时器的应用示例

    4.3.1 互补 PWM 输出

    使用高级定时器 1 生成互补的 PWM 信号,适用于电机控制中的桥式驱动。

    
    #include "stm32g4xx.h"
    
    
    
    void TIM1_ComplementaryPWM_Init(void) {
    
        // 使能定时器 1 的时钟
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
    
    
    
        // 使能 GPIOA 的时钟
    
        RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_GPIOA, ENABLE);
    
    
    
        // 配置 PA8 和 PA9 为复用推挽输出
    
        GPIO_InitTypeDef GPIO_InitStructure;
    
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
    
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    
    
        // 配置通道 1 和 2 为 TIM1
    
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_TIM1);
    
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_TIM1);
    
    
    
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
        TIM_OCInitTypeDef TIM_OCInitStructure;
    
        TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
    
    
    
        // 配置定时器 1
    
        TIM_TimeBaseStructure.TIM_Period = 999; // 周期值
    
        TIM_TimeBaseStructure.TIM_Prescaler = 8400 - 1; // 预分频器值
    
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    
    
    
        TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
    
    
    
        // 配置通道 1 为 PWM 模式
    
        TIM_OCStructInit(&TIM_OCInitStructure);
    
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    
        TIM_OCInitStructure.TIM_Pulse = 500; // PWM 脉冲宽度
    
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    
    
    
        TIM_OC1Init(TIM1, &TIM_OCInitStructure);
    
        TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
    
    
    
        // 配置通道 2 为互补 PWM 模式
    
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    
        TIM_OCInitStructure.TIM_Pulse = 500; // PWM 脉冲宽度
    
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    
        TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
    
        TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
    
    
    
        TIM_OC2Init(TIM1, &TIM_OCInitStructure);
    
        TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
    
    
    
        // 配置死区时间
    
        TIM_BDTRStructInit(&TIM_BDTRInitStructure);
    
        TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSR_Enable;
    
        TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSI_Enable;
    
        TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
    
        TIM_BDTRInitStructure.TIM_DeadTime = 128; // 死区时间值
    
        TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
    
        TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
    
        TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
    
    
    
        TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
    
    
    
        // 使能定时器 1
    
        TIM_Cmd(TIM1, ENABLE);
    
    }
    
    
    
    int main(void) {
    
        TIM1_ComplementaryPWM_Init();
    
    
    
        while (1) {
    
            // 主循环
    
        }
    
    }
    
    

    5. 低功耗定时器

    5.1 低功耗定时器的特点

    低功耗定时器(Timers 5, 6, 14)在低功耗模式下仍能保持运行,适合需要节能的应用。它们通常用于生成周期性的中断或事件,但不支持 PWM 输出和输入捕获功能。

    5.2 低功耗定时器的配置

    5.2.1 时钟配置

    低功耗定时器的时钟源可以是内部时钟或外部时钟。以下是一个示例,使能定时器 6 的时钟:

    
    // 使能定时器 6 的时钟
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
    
    
    5.2.2 预分频器和自动重装载寄存器配置

    配置预分频器(PSC)和自动重装载寄存器(ARR)以设置定时器的周期和频率。以下是一个示例,配置定时器 6 的周期和预分频器:

    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
    
    
    TIM_TimeBaseStructure.TIM_Period = 9999; // 周期值
    
    TIM_TimeBaseStructure.TIM_Prescaler = 16800 - 1; // 预分频器值
    
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; // 时钟分频
    
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 计数器模式
    
    
    
    TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
    
    
    5.2.3 中断配置

    配置定时器中断,使其在计数器溢出时触发。以下是一个示例,配置定时器 6 的更新中断:

    
    TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
    
    
    
    // 使能定时器 6
    
    TIM_Cmd(TIM6, ENABLE);
    
    
    
    // 配置 NVIC 以处理定时器 6 中断
    
    NVIC_InitTypeDef NVIC_InitStructure;
    
    NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn;
    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    
    NVIC_Init(&NVIC_InitStructure);
    
    
    5.2.4 中断处理函数

    编写中断处理函数,处理定时器 6 的更新事件。以下是一个示例:

    
    void TIM6_DAC_IRQHandler(void) {
    
        if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) {
    
            // 处理更新事件
    
            TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
    
        }
    
    }
    
    

    5.3 低功耗定时器的应用示例

    5.3.1 周期性中断

    使用低功耗定时器 6 生成每 1 秒一次的中断,适合在低功耗模式下运行。

    
    #include "stm32g4xx.h"
    
    
    
    // 定义中断处理函数
    
    void TIM6_DAC_IRQHandler(void) {
    
        if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) {
    
            // 读取捕获值
    
            uint32_t capture_value = TIM_GetCapture1(TIM6);
    
    
    
            // 处理捕获值
    
            // 例如,计算脉宽或频率
    
    
    
            // 清除捕获中断标志
    
            TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
    
        }
    
    }
    
    
    
    void TIM6_LowPower_Init(void) {
    
        // 使能定时器 6 的时钟
    
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
    
    
    
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
        NVIC_InitTypeDef NVIC_InitStructure;
    
    
    
        // 配置定时器 6
    
        TIM_TimeBaseStructure.TIM_Period = 9999; // 10000 - 1
    
        TIM_TimeBaseStructure.TIM_Prescaler = 16800 - 1; // 16800 - 1
    
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    
    
    
        TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
    
    
    
        // 使能定时器 6 的更新中断
    
        TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
    
    
    
        // 使能定时器 6
    
        TIM_Cmd(TIM6, ENABLE);
    
    
    
        // 配置 NVIC 以处理定时器 6 中断
    
        NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn;
    
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    
        NVIC_Init(&NVIC_InitStructure);
    
    }
    
    
    
    int main(void) {
    
        TIM6_LowPower_Init();
    
    
    
        while (1) {
    
            // 主循环
    
        }
    
    }
    
    

    6. 总结

    STM32G4 系列微控制器提供了多种定时器,每种定时器都有其独特的特点和应用场景。基本定时器适用于简单的时间延迟和周期性任务控制,通用定时器功能丰富,适用于 PWM 生成、输入捕获和死区时间控制等复杂应用,高级定时器专为电机控制设计,支持互补 PWM 和死区时间设置,低功耗定时器在低功耗模式下仍能保持运行,适合需要节能的应用。通过合理配置这些定时器,可以实现高效、精准的时间控制功能。

    希望本篇文章对理解和使用 STM32G4 系列定时器有所帮助。如果需要更详细的配置和应用示例,可以参考 STM32G4 系列的官方数据手册和库函数文档。

    作者:kkchenkx

    物联沃分享整理
    物联沃-IOTWORD物联网 » STMicroelectronics 系列:STM32G4 系列_(4).STM32G4系列定时器详解

    发表回复