第30章 通用定时器-同步
第三十章 通用定时器-同步
1. 硬件设计
无需硬件设计
2. 软件设计
- 定时器相关参数宏定义
// 定时器参数宏定义
#define GENERAL_TIM_MASTER TIM2 // 主定时器--TIM2
#define GENERAL_TIM_MASTER_CLK RCC_APB1Periph_TIM2 // 主定时器时钟--RCC_APB1Periph_TIM2
#define GENERAL_TIM_SLAVE1 TIM3 // 从定时器1--TIM3
#define GENERAL_TIM_SLAVE1_CLK RCC_APB1Periph_TIM3 // 从定时器1时钟--RCC_APB1Periph_TIM3
#define GENERAL_TIM_SLAVE11 TIM4 // 从定时器11--TIM4
#define GENERAL_TIM_SLAVE11_CLK RCC_APB1Periph_TIM4 // 从定时器11时钟--RCC_APB1Periph_TIM4
// TIM主模式PWM输出引脚
#define GENERAL_MASTER_PIN GPIO_Pin_10 // 主定时器PWM输出引脚
#define GENERAL_MASTER_GPIO_PORT GPIOB // 主定时器PWM输出端口
#define GENERAL_MASTER_GPIO_CLK RCC_APB2Periph_GPIOB // 主定时器PWM输出端口时钟
#define GENERAL_MASTER_PINSOURCE GPIO_PinSource5 // 主定时器PWM输出引脚源
#define GENERAL_MASTER_AF GPIO_AF_TIM2 // 主定时器PWM输出引脚复用功能
// TIM从模式PWM输出引脚
#define GENERAL_SLAVE1_PIN GPIO_Pin_6
#define GENERAL_SLAVE1_GPIO_PORT GPIOC
#define GENERAL_SLAVE1_GPIO_CLK RCC_APB2Periph_GPIOC
#define GENERAL_SLAVE1_PINSOURCE GPIO_PinSource6
#define GENERAL_SLAVE1_AF GPIO_AF_TIM3
// TIM从模式的从模式PWM输出引脚
#define GENERAL_SLAVE11_PIN GPIO_Pin_6
#define GENERAL_SLAVE11_GPIO_PORT GPIOB
#define GENERAL_SLAVE11_GPIO_CLK RCC_APB2Periph_GPIOB
#define GENERAL_SLAVE11_PINSOURCE GPIO_PinSource6
#define GENERAL_SLAVE11_AF GPIO_AF_TIM4
- 定时器参数宏定义:
GENERAL_TIM_MASTER
和GENERAL_TIM_MASTER_CLK
定义了主定时器(TIM2)及其时钟。GENERAL_TIM_SLAVE1
和GENERAL_TIM_SLAVE1_CLK
定义了从定时器1(TIM3)及其时钟。GENERAL_TIM_SLAVE11
和GENERAL_TIM_SLAVE11_CLK
定义了从定时器11(TIM4)及其时钟。
- TIM主模式PWM输出引脚:
GENERAL_MASTER_PIN
、GENERAL_MASTER_GPIO_PORT
和GENERAL_MASTER_GPIO_CLK
定义了主定时器的PWM输出引脚(PB10)及其相关端口和时钟。GENERAL_MASTER_PINSOURCE
和GENERAL_MASTER_AF
定义了引脚的复用功能设置,表明该引脚用于TIM2的PWM输出。
- TIM从模式PWM输出引脚:
GENERAL_SLAVE1_PIN
、GENERAL_SLAVE1_GPIO_PORT
和GENERAL_SLAVE1_GPIO_CLK
定义了从定时器1的PWM输出引脚(PC6)及其相关端口和时钟。GENERAL_SLAVE1_PINSOURCE
和GENERAL_SLAVE1_AF
定义了引脚的复用功能设置,表明该引脚用于TIM3的PWM输出。
- TIM从模式的从模式PWM输出引脚:
-
GENERAL_SLAVE11_PIN
、GENERAL_SLAVE11_GPIO_PORT
和GENERAL_SLAVE11_GPIO_CLK
定义了从定时器11的PWM输出引脚(PB6)及其相关端口和时钟。 -
GENERAL_SLAVE11_PINSOURCE
和GENERAL_SLAVE11_AF
定义了引脚的复用功能设置,表明该引脚用于TIM4的PWM输出。 -
GPIO初始化
// TIM所使用的GPIO初始化
static void TIMx_GPIO_Config(void)
{
// 1.先定义一个GPIO_InitTypeDef结构体变量
GPIO_InitTypeDef GPIO_InitStructure;
// 2.使能GPIO时钟
RCC_APB2PeriphClockCmd(GENERAL_MASTER_GPIO_CLK |GENERAL_SLAVE1_GPIO_CLK | GENERAL_SLAVE11_GPIO_CLK, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); // 使能AFIO时钟
GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE); // 完全重映像TIM2_CH3->PB10
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); // 完全重映像TIM3_CH1->PC6
// 3.GPIO 配置: PC6(TIM3 CH1) 作为推挽复用输出功能
GPIO_InitStructure.GPIO_Pin = GENERAL_SLAVE1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;;
GPIO_Init(GENERAL_SLAVE1_GPIO_PORT, &GPIO_InitStructure);
// 4.GPIO 配置: PB6(TIM4 CH1) 作为推挽复用输出功能
GPIO_InitStructure.GPIO_Pin = GENERAL_SLAVE11_PIN;
GPIO_Init(GENERAL_SLAVE11_GPIO_PORT, &GPIO_InitStructure);
// 5.GPIO 配置: PB10(TIM2 CH3) 作为推挽复用输出功能
GPIO_InitStructure.GPIO_Pin = GENERAL_MASTER_PIN;
GPIO_Init(GENERAL_MASTER_GPIO_PORT, &GPIO_InitStructure);
}
- 使能GPIO时钟:
RCC_APB2PeriphClockCmd
使能了与主定时器和从定时器相关的GPIO时钟,并使能了AFIO时钟。GPIO_PinRemapConfig
配置了定时器通道的引脚重映射,例如将TIM2_CH3
重映射到PB10
。
- 配置GPIO引脚:
- 使用
GPIO_InitTypeDef
结构体配置引脚。 GPIO_InitStructure.GPIO_Mode
设置为推挽复用输出 (GPIO_Mode_AF_PP
),以支持定时器的PWM输出。GPIO_InitStructure.GPIO_Speed
设置为 50MHz。
- 具体GPIO引脚配置:
- PC6: 配置为
TIM3_CH1
的推挽复用输出。 - PB6: 配置为
TIM4_CH1
的推挽复用输出。 - PB10: 配置为
TIM2_CH3
的推挽复用输出。
这里出现了一个新的库函数,我们需要分析一下:
GPIO_PinRemapConfig
是一个用于配置GPIO引脚重映射的库函数,通常用于定时器或其他外设的引脚重映射,以便将外设功能映射到不同的引脚上。它的主要功能是在微控制器中重新定义某些功能引脚的位置。
函数原型
void GPIO_PinRemapConfig(GPIO_TypeDef* GPIOx, FunctionalState NewState);
参数说明
GPIOx
: 需要重映射的GPIO配置。例如,GPIO_FullRemap_TIM2
代表定时器2的完全重映射。NewState
: 指定是否启用重映射。ENABLE
启用重映射,DISABLE
禁用重映射。
功能描述
- 重映射引脚: 该函数将定时器或其他外设的特定功能引脚映射到其他可用引脚上。例如,将
TIM2_CH3
的功能映射到PB10
。 - 灵活性: 提供了更大的灵活性以适应不同的硬件布局和需求。
使用场景
- 当你需要将外设的功能引脚分配到不同的物理引脚时,例如在开发过程中调整硬件布局或在应用程序中使用不同的引脚。
示例
GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE); // 启用 TIM2 的完全重映射
- TIM模式配置
// TIM模式配置
static void TIM_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
// 使能TIM时钟
RCC_APB1PeriphClockCmd(GENERAL_TIM_MASTER_CLK | GENERAL_TIM_SLAVE1_CLK | GENERAL_TIM_SLAVE11_CLK, ENABLE);
// 时基配置
TIM_TimeBaseStructure.TIM_Period = 72;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(GENERAL_TIM_MASTER, &TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 4;
TIM_TimeBaseInit(GENERAL_TIM_SLAVE1, &TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 4;
TIM_TimeBaseInit(GENERAL_TIM_SLAVE11, &TIM_TimeBaseStructure);
// 主定时器设置成PWM1模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 36; // 占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC3Init(GENERAL_TIM_MASTER, &TIM_OCInitStructure); // 初始化 TIM2 输出通道3
// 使能主从模式
TIM_SelectMasterSlaveMode(GENERAL_TIM_MASTER, TIM_MasterSlaveMode_Enable);
// 输出触发源选项
TIM_SelectOutputTrigger(GENERAL_TIM_MASTER, TIM_TRGOSource_Update);
// 从定时器设置成PWM1模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1; // 占空比
TIM_OC1Init(GENERAL_TIM_SLAVE1, &TIM_OCInitStructure); // 初始化 TIM3 输出通道1
TIM_OC1Init(GENERAL_TIM_SLAVE11, &TIM_OCInitStructure); // 初始化 TIM4 输出通道1
// 使能主从模式
TIM_SelectMasterSlaveMode(GENERAL_TIM_SLAVE1, TIM_MasterSlaveMode_Enable);
// 输出触发源选项
TIM_SelectOutputTrigger(GENERAL_TIM_SLAVE1, TIM_TRGOSource_Update);
TIM_SelectSlaveMode(GENERAL_TIM_SLAVE1, TIM_SlaveMode_Gated); // 从模式配置 : TIM3
TIM_SelectInputTrigger(GENERAL_TIM_SLAVE1, TIM_TS_ITR1); // 设置输入触发源
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Gated); // 从模式配置 : TIM4
TIM_SelectInputTrigger(GENERAL_TIM_SLAVE11, TIM_TS_ITR2); // 设置输入触发源
// TIM 计数器溢出中断启用
TIM_Cmd(GENERAL_TIM_SLAVE1, ENABLE);
TIM_Cmd(GENERAL_TIM_MASTER, ENABLE);
TIM_Cmd(GENERAL_TIM_SLAVE11, ENABLE);
}
- 主函数
#include "stm32f10x.h"
#include "./tim/bsp_general_tim.h"
int main(void)
{
// 初始化通用定时器级联同步PWM输出
// 实现:TIM2发生事件更新时发送触发信号驱动TIM3计数
// TIM3发生事件更新时发送触发信号驱动TIM4计数
TIMx_Configuration();
while(1)
{
}
}
3. 小结
其他步骤我们已经很熟悉了,下面重点来分析一下配置TIM模式:
1. 启用定时器时钟
RCC_APB1PeriphClockCmd(GENERAL_TIM_MASTER_CLK | GENERAL_TIM_SLAVE1_CLK | GENERAL_TIM_SLAVE11_CLK, ENABLE);
这行代码启用了主定时器(GENERAL_TIM_MASTER
)和两个从定时器(GENERAL_TIM_SLAVE1
和 GENERAL_TIM_SLAVE11
)的时钟,使能它们的计数功能。
2. 配置时基
TIM_TimeBaseStructure.TIM_Period = 72;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(GENERAL_TIM_MASTER, &TIM_TimeBaseStructure);
TIM_Period
:定时器计数周期。当计数器的值从0增加到此值时,会产生一个溢出事件。TIM_Prescaler
:预分频器的值。它控制定时器计数频率。此处设置为0,意味着时钟频率没有被分频。TIM_ClockDivision
:时钟分频系数。设置为0时,定时器时钟没有额外分频。TIM_CounterMode
:计数模式,这里设置为TIM_CounterMode_Up
,意味着计数器将从0向上计数。
3. 配置 PWM 模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 36; // 占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC3Init(GENERAL_TIM_MASTER, &TIM_OCInitStructure);
TIM_OCMode
:输出比较模式,这里设置为TIM_OCMode_PWM1
,配置为PWM1模式。TIM_OutputState
:设置为TIM_OutputState_Enable
,启用输出。TIM_Pulse
:设置PWM信号的脉宽,决定占空比。脉宽为36。TIM_OCPolarity
:输出极性设置为高,即PWM信号的高电平在计数器计数期间持续时间。
4. 配置从定时器
TIM_TimeBaseStructure.TIM_Period = 4;
TIM_TimeBaseInit(GENERAL_TIM_SLAVE1, &TIM_TimeBaseStructure);
TIM_TimeBaseInit(GENERAL_TIM_SLAVE11, &TIM_TimeBaseStructure);
为两个从定时器设置周期为4的计数器。
TIM_OCInitStructure.TIM_Pulse = 1; // 占空比
TIM_OC1Init(GENERAL_TIM_SLAVE1, &TIM_OCInitStructure);
TIM_OC1Init(GENERAL_TIM_SLAVE11, &TIM_OCInitStructure);
5. 配置主从模式
使能主从模式
TIM_SelectMasterSlaveMode(GENERAL_TIM_MASTER, TIM_MasterSlaveMode_Enable);
启用主定时器的主从模式,这使得主定时器可以作为触发源来驱动从定时器。
选择输出触发源
TIM_SelectOutputTrigger(GENERAL_TIM_MASTER, TIM_TRGOSource_Update);
设置主定时器的触发源为更新事件(计数器溢出时),主定时器的更新事件将触发从定时器。
配置从定时器为从模式
TIM_SelectSlaveMode(GENERAL_TIM_SLAVE1, TIM_SlaveMode_Gated);
TIM_SelectInputTrigger(GENERAL_TIM_SLAVE1, TIM_TS_ITR1);
将GENERAL_TIM_SLAVE1
配置为“门控模式”(Gated Mode),这意味着从定时器的计数会被主定时器的触发事件控制。触发源设置为输入触发1(ITR1
),这是主定时器的触发信号。
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Gated);
TIM_SelectInputTrigger(GENERAL_TIM_SLAVE11, TIM_TS_ITR2);
同样地,将GENERAL_TIM_SLAVE11
配置为“门控模式”,并设置触发源为输入触发2(ITR2
),另一个主定时器的触发信号。
6. 启用定时器
TIM_Cmd(GENERAL_TIM_SLAVE1, ENABLE);
TIM_Cmd(GENERAL_TIM_MASTER, ENABLE);
TIM_Cmd(GENERAL_TIM_SLAVE11, ENABLE);
最后,启用所有定时器,使它们开始计数和生成PWM信号。
2024.9.13 第一次修订,后期不再维护