
我们还是继续研究通用定时器
我们主要是研究定时器的从模式
什么是从,就是定时器接受到其他信号来做出反应
这个信号可以是外部给的
也可以是内部给的
定时器触发
外部触发

我们上一篇看过了STM定时器可以通过TIx捕获
TIX捕获会经过TIxFPx通道
然后我们根据图片,刚刚好TI1FP1和TI2FP2可以到从模式控制器
内部触发

我们看图片,发现他还有ITRx和TI1F_ED
ITRx是内部定时器发出的信号
他是内部定时器CNT溢出复位后才会产生一次TRGO信号
TI1F_ED是内部定时器的通道接收到了边沿信号就会产生一次信号
参考代码函数
外部触发配置
基本上来说,无论是ETR还是TIX
前面都是正常的配置和有无启用从模式无关
你改咋样配置ETR或TIX就咋配置
配置完成之后,我们只需要加两个函数把他关联到从模式里面去就可以了
(我建议去HAL库看,那样子更容易理解)
1 | void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource); |
| 参数 | 数据类型 | 作用 | 选项 |
|---|---|---|---|
| TIM_TypeDef* TIMx | TIM_TypeDef* | 选择的定时器 | TIM1~TIM8 |
| uint16_t TIM_InputTriggerSource | uint16_t | 选择触发源 | TIM_TS_ITR0~TIM_TS_ITR3:内部触发(其他定时器) TIM_TS_TI1F_ED:TI1的边沿检测器 TIM_TS_TI1FP1:滤波后的TI1输入 TIM_TS_TI2FP2:滤波后的TI2输入 TIM_TS_ETRF:外部触发输入 |
| 返回值 | 无 | 无 | 无 |
如果你用了TI1F_ED那么配置初始化TIM_ICInit()里面的TIM_ICPolarity会无效
需要配置直接模式
点击展开参考代码
// 1. 开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 2. 配置GPIO PA0:TIM2_CH1 输入
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 3. 配置输入捕获(必须配置!TI1通道硬件初始化)
TIM_ICInitTypeDef TIM_ICInitStruct;
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1; // 选择TI1通道
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; // 双边沿无效,由TI1F_ED接管
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; // 直接映射TI1
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; // 不分频
TIM_ICInitStruct.TIM_ICFilter = 0x0F; // 硬件滤波(抗干扰,0~0x0F)
TIM_ICInit(TIM2, &TIM_ICInitStruct);
// 4. 定时器基础配置
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_Period = 999; // 自动重装载值ARR
TIM_TimeBaseInitStruct.TIM_Prescaler = 7199; // 内部时钟预分频
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
// 5. 核心配置:触发源 = TI1F_ED + 从模式 = Trigger
TIM_SelectInputTrigger(TIM2, TIM_TS_TI1F_ED); // 选择TI1双边沿为触发源
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Trigger); // 双边沿触发启动计数
// 6. 使能定时器
TIM_Cmd(TIM2, ENABLE);
选择触发效果
1 | void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode); |
| 参数 | 数据类型 | 作用 | 选项 |
|---|---|---|---|
| TIM_TypeDef* TIMx | TIM_TypeDef* | 选择的定时器 | TIM1~TIM8 |
| uint16_t TIM_SlaveMode | uint16_t | 选择事件 | TIM_SlaveMode_Reset:选择复位模式 TIM_SlaveMode_Reset:触发信号上升沿时重新初始化计数器 TIM_SlaveMode_Gated:触发信号高电平时计数 TIM_SlaveMode_Trigger:触发信号作为时钟 TIM_SlaveMode_External1:外部时钟模式1 |
关于计数其实就是记录到CNT里面
关于这俩模式 TIM_SlaveMode_Trigger:触发信号作为时钟 和 TIM_SlaveMode_External1:外部时钟模式1
TIM_SlaveMode_Trigger相当是直接记录到cnt
TIM_SlaveMode_External1相当是变成时钟要经过PSC再到CNT
内部触发配置
我们这边用TIM1和TIM2举例
假设TIM1是主定时器,TIM2是从定时器
TIM1选择内部时钟初始化,然后下面多一行函数去配置输出到TRGO
1 | void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource); |
| 配置项 | 可选项 | 作用与解释 |
|---|---|---|
| TIM_TypeDef* TIMx | TIM1-TIM8 | 选择定时器 |
| uint16_t TIM_TRGOSource | TIM_TRGOSource_Reset TIM_TRGOSource_Enable TIM_TRGOSource_Update TIM_TRGOSource_OC1 TIM_TRGOSource_OC1Ref TIM_TRGOSource_OC2Ref TIM_TRGOSource_OC3Ref TIM_TRGOSource_OC4Ref |
定时器触发输出源选择: - Reset:软件复位事件(UG 位)作为 TRGO - Enable:计数器使能事件(CEN 置位)作为 TRGO - Update:更新事件(计数溢出/重载)作为 TRGO - OC1:通道1比较匹配事件作为 TRGO - OC1Ref:通道1参考信号(OC1REF)作为 TRGO - OC2Ref:通道2参考信号(OC2REF)作为 TRGO - OC3Ref:通道3参考信号(OC3REF)作为 TRGO - OC4Ref:通道4参考信号(OC4REF)作为 TRGO |
一般默认用TIM_TRGOSource_Reset就是复位模式
也就是CNT记满之后会触发给TRGO
然后我们对TIM2进行配置
和上面一样的
1 | void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource); |
| 参数 | 数据类型 | 作用 | 选项 |
|---|---|---|---|
| TIM_TypeDef* TIMx | TIM_TypeDef* | 选择的定时器 | TIM1~TIM8 |
| uint16_t TIM_InputTriggerSource | uint16_t | 选择触发源 | TIM_TS_ITR0~TIM_TS_ITR3:内部触发(其他定时器) TIM_TS_TI1F_ED:TI1的边沿检测器 TIM_TS_TI1FP1:滤波后的TI1输入 TIM_TS_TI2FP2:滤波后的TI2输入 TIM_TS_ETRF:外部触发输入 |
| 返回值 | 无 | 无 | 无 |
1 | void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode); |
| 参数 | 数据类型 | 作用 | 选项 |
|---|---|---|---|
| TIM_TypeDef* TIMx | TIM_TypeDef* | 选择的定时器 | TIM1~TIM8 |
| uint16_t TIM_SlaveMode | uint16_t | 选择事件 | TIM_SlaveMode_Reset:选择复位模式 TIM_SlaveMode_Reset:触发信号上升沿时重新初始化计数器 TIM_SlaveMode_Gated:触发信号高电平时计数 TIM_SlaveMode_Trigger:触发信号作为时钟 TIM_SlaveMode_External1:外部时钟模式1 |
基本上就只要修改SelectInputTrigger这个函数
选择对应ITR
- 高级定时器(从定时器)
| 从定时器 | ITR0 (TS=000) | ITR1 (TS=001) | ITR2 (TS=010) | ITR3 (TS=011) |
|---|---|---|---|---|
| TIM1 | TIM5 | TIM2 | TIM3 | TIM4 |
| TIM8 | TIM1 | TIM2 | TIM4 | TIM5 |
- 通用定时器(从定时器)
| 从定时器 | ITR0 (TS=000) | ITR1 (TS=001) | ITR2 (TS=010) | ITR3 (TS=011) |
|---|---|---|---|---|
| TIM2 | TIM1 | TIM8 | TIM3 | TIM4 |
| TIM3 | TIM1 | TIM2 | TIM5 | TIM4 |
| TIM4 | TIM1 | TIM2 | TIM3 | TIM8 |
| TIM5 | TIM2 | TIM3 | TIM4 | TIM8 |
这是对应的表格
因为是tim2作为从,tim1是主,那么就是对应ITR0