第28章 通用定时器-4路PWM输出

第二十八章 通用定时器-4路PWM输出

1. 硬件设计

无硬件设计

2. 软件设计

  • TIM3相关参数和四个通道宏定义
// 通用定时器参数宏定义-TIM3
#define GENERAL_TIM                   TIM3                   // 选择使用的通用定时器-TIM3
#define GENERAL_TIM_APBxClock_FUN     RCC_APB1PeriphClockCmd // 选择要挂载的时钟-APB1
#define GENERAL_TIM_CLK               RCC_APB1Periph_TIM3    // 选择时钟源-APB1时钟_TIM3
#define GENERAL_TIM_Period            9                      // 定时器周期-9
#define GENERAL_TIM_Prescaler         71                     // 定时器分频系数-71
// TIM3 输出比较通道1
#define GENERAL_TIM_CH1_GPIO_CLK      RCC_APB2Periph_GPIOA
#define GENERAL_TIM_CH1_PORT          GPIOA
#define GENERAL_TIM_CH1_PIN           GPIO_Pin_6

// TIM3 输出比较通道2(PA7)
#define GENERAL_TIM_CH2_GPIO_CLK      RCC_APB2Periph_GPIOA
#define GENERAL_TIM_CH2_PORT          GPIOA
#define GENERAL_TIM_CH2_PIN           GPIO_Pin_7

// TIM3 输出比较通道3(PB0)
#define GENERAL_TIM_CH3_GPIO_CLK      RCC_APB2Periph_GPIOB
#define GENERAL_TIM_CH3_PORT          GPIOB
#define GENERAL_TIM_CH3_PIN           GPIO_Pin_0

// TIM3 输出比较通道4(PB1)
#define GENERAL_TIM_CH4_GPIO_CLK      RCC_APB2Periph_GPIOB
#define GENERAL_TIM_CH4_PORT          GPIOB
#define GENERAL_TIM_CH4_PIN           GPIO_Pin_1

宏定义了通用定时器的基本参数还有四个通道的GPIO

  • GPIO配置
static void GENERAL_TIM_GPIO_Config(void) 
{
    // 1.定义一个GPIO_InitTypeDef结构体变量
    GPIO_InitTypeDef GPIO_InitStructure;

    // 2.输出比较通道1 GPIO 初始化
    RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK, ENABLE); // 开启通道1 GPIO时钟
    GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH1_PIN;       // 选择通道1引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;           // 复用推挽输出模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         // 50MHz
    GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);     // 初始化GPIO

    // 输出比较通道2 GPIO 初始化
    RCC_APB2PeriphClockCmd(GENERAL_TIM_CH2_GPIO_CLK, ENABLE);
    GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH2_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GENERAL_TIM_CH2_PORT, &GPIO_InitStructure);

    // 输出比较通道3 GPIO 初始化
    RCC_APB2PeriphClockCmd(GENERAL_TIM_CH3_GPIO_CLK, ENABLE);
    GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH3_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GENERAL_TIM_CH3_PORT, &GPIO_InitStructure);

    // 输出比较通道4 GPIO 初始化
    RCC_APB2PeriphClockCmd(GENERAL_TIM_CH4_GPIO_CLK, ENABLE);
    GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH4_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GENERAL_TIM_CH4_PORT, &GPIO_InitStructure);
}

四个通道 GPIO 初始化

  • TIM模式配置
// TIM模式配置
static void GENERAL_TIM_Mode_Config(void)
{
    // 开启定时器时钟,即内部时钟CK_INT=72M
    GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK, ENABLE);

/*--------------------时基结构体初始化-------------------------*/
    // 配置周期,这里配置为100K
    // 1.定义一个TIM_TimeBaseInitTypeDef结构体变量
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    // 2.自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
    TIM_TimeBaseStructure.TIM_Period = GENERAL_TIM_Period;    
    // 3.驱动CNT计数器的时钟 = Fck_int/(psc+1)
    TIM_TimeBaseStructure.TIM_Prescaler = GENERAL_TIM_Prescaler;    
    // 4.时钟分频因子 ,配置死区时间时需要用到
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;        
    // 5.计数器计数模式,设置为向上计数
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;        
    // 6.重复计数器的值,没用到不用管
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;    
    // 初始化定时器
    TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);
  • 输出比较结构体配置
/*---------------------输出比较结构体初始化--------------------*/    
    // 1.占空比配置
    uint16_t CCR1_Val = 5; // 通道1的占空比为50%
    uint16_t CCR2_Val = 4; // 通道2的占空比为40%
    uint16_t CCR3_Val = 3; // 通道3的占空比为30%
    uint16_t CCR4_Val = 2; // 通道4的占空比为20%

    // 2.定义一个TIM_OCInitTypeDef结构体变量
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    // 3.配置为PWM模式1
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    // 4.输出使能
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    // 5.输出通道电平极性配置    
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

    // 输出比较通道 1
    TIM_OCInitStructure.TIM_Pulse = CCR1_Val;                // 输出比较值
    TIM_OC1Init(GENERAL_TIM, &TIM_OCInitStructure);          // 初始化输出比较通道1
    TIM_OC1PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable); // 使能预装载

    // 输出比较通道 2
    TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
    TIM_OC2Init(GENERAL_TIM, &TIM_OCInitStructure);
    TIM_OC2PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);

    // 输出比较通道 3
    TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
    TIM_OC3Init(GENERAL_TIM, &TIM_OCInitStructure);
    TIM_OC3PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);

    // 输出比较通道 4
    TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
    TIM_OC4Init(GENERAL_TIM, &TIM_OCInitStructure);
    TIM_OC4PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);

    // 使能计数器
    TIM_Cmd(GENERAL_TIM, ENABLE);
}

其中一个新的库函数我们需要解释一下:

TIM_OC1PreloadConfig 是 STM32 微控制器中用于配置定时器输出比较通道的函数。其原型如下:

void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

  • TIMx: 指定定时器实例,如 TIM1TIM2 等。
  • TIM_OCPreload: 预装载使能状态,取值为 TIM_OCPreload_Enable 或 TIM_OCPreload_Disable

功能: 启用或禁用通道1的预装载寄存器。启用预装载使得在更新事件发生时,比较寄存器的值可以被预装载寄存器的值替代,从而避免在运行中改变比较值。

示例:

// 启用通道1的预装载
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
// 这将确保在定时器更新事件时,新的比较值会被加载。
  • 主函数
// TIM—通用定时器-4路PWM输出应用
#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_GeneralTim.h"  

int main(void)
{
    // led 端口配置 
    LED_GPIO_Config();
    // 定时器初始化
    GENERAL_TIM_Init();

  while(1)
  {      

  }
}

3. 小结

如何利用通用定时器进行4路PWM输出,我们简化一下流程:

  1. 初始化 GPIO:配置对应的 GPIO 引脚为定时器输出模式。
  2. 初始化定时器:设置定时器的计数周期、预分频器等。
  3. 配置输出比较通道:设置每个通道的 PWM 参数。
  4. 启动定时器:启动定时器并开始输出 PWM 信号。

下面是一个简单的示例代码,使用 TIM2 定时器产生 4 路 PWM 输出信号。假设你使用的是 STM32F103 系列的微控制器,通道配置如下:

  • 通道 1: GPIOA Pin 0
  • 通道 2: GPIOA Pin 1
  • 通道 3: GPIOA Pin 2
  • 通道 4: GPIOA Pin 3

代码示例

#include "stm32f10x.h"

// 初始化 GPIO
void GPIO_Config(void) {
    GPIO_InitTypeDef GPIO_InitStructure;

    // 启用 GPIOA 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    // 配置 GPIOA 的四个引脚为定时器输出模式
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

// 初始化定时器
void TIM_Config(void) {
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;

    // 启用 TIM2 时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // 配置定时器基准时间
    TIM_TimeBaseStructure.TIM_Period = 999;          // 自动重装载寄存器值
    TIM_TimeBaseStructure.TIM_Prescaler = 71;        // 预分频器,APB1 时钟 / (71 + 1)
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟分割
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    // 配置通道 1 PWM 输出
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM 模式 1
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 499;             // PWM 占空比的脉冲宽度 (50% 的占空比)
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 极性高
    TIM_OC1Init(TIM2, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); // 使能通道 1 的预装载

    // 配置通道 2 PWM 输出
    TIM_OCInitStructure.TIM_Pulse = 249;             // 不同的占空比
    TIM_OC2Init(TIM2, &TIM_OCInitStructure);
    TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); // 使能通道 2 的预装载

    // 配置通道 3 PWM 输出
    TIM_OCInitStructure.TIM_Pulse = 749;             // 不同的占空比
    TIM_OC3Init(TIM2, &TIM_OCInitStructure);
    TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); // 使能通道 3 的预装载

    // 配置通道 4 PWM 输出
    TIM_OCInitStructure.TIM_Pulse = 999;             // 不同的占空比
    TIM_OC4Init(TIM2, &TIM_OCInitStructure);
    TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable); // 使能通道 4 的预装载

    // 启动定时器
    TIM_Cmd(TIM2, ENABLE);
}

// 主函数
int main(void) {
    // 配置 GPIO
    GPIO_Config();

    // 配置定时器
    TIM_Config();

    while (1) {
        // 主循环中可以进行其他操作
    }
}

代码解释

  1. GPIO_Config:
  • 启用 GPIOA 的时钟。
  • 配置 GPIOA 的四个引脚为推挽输出模式,用于输出 PWM 信号。
  1. TIM_Config:
  • 启用 TIM2 的时钟。
  • 配置定时器 TIM2 的基准时间,包括周期(TIM_Period)、预分频器(TIM_Prescaler)、计数模式等。
  • 配置 TIM2 的四个通道为 PWM 输出模式,并设置各通道的占空比。
  • 启动 TIM2 定时器。
  1. 主函数:
  • 调用配置函数初始化 GPIO 和定时器。
  • 进入无限循环,持续运行主程序。

该示例代码中,PWM 信号的占空比是通过调整 TIM_OCInitStructure.TIM_Pulse 来设置的。


2024.9.12 第一次修订,后期不再维护

posted @ 2024-09-12 16:37  hazy1k  阅读(9)  评论(0编辑  收藏  举报