STM32 输入捕获模式详解:PWM 输入捕获与 PWI 模式(续篇)
在前两篇文章中,我们探讨了 STM32 输入捕获的基础和 PWI 模式的工作原理,特别是定时器的两个通道如何协同工作以捕获 PWM 信号。本文将进一步结合 STM32 标准库函数中的 TIM_PWMIConfig()
,来讲解如何通过库函数配置定时器实现 PWI 模式。
我们将分析该函数的工作流程,讲解它是如何通过不同通道的配置来捕获上升沿和下降沿信号,并计算 PWM 信号的频率和占空比。
1. TIM_PWMIConfig()
函数概述
TIM_PWMIConfig()
函数专门用于配置定时器的 PWI 模式,以捕获外部的 PWM 信号。该函数的核心功能是将定时器的两个输入通道(通常是 CH1 和 CH2)分别设置为捕获上升沿和下降沿信号,从而实现对 PWM 信号周期和占空比的测量。
该函数主要完成了以下任务:
- 输入捕获极性设置:将一个通道(如 CH1)设置为检测上升沿,另一个通道(如 CH2)设置为检测下降沿。
- 通道选择:为两个通道选择输入信号源,CH1 直接输入,CH2 选择间接输入。
- 滤波和预分频器配置:设置输入信号的滤波和预分频参数。
2. TIM_PWMIConfig()
代码分析
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct)
{
uint16_t icoppositepolarity = TIM_ICPolarity_Rising;
uint16_t icoppositeselection = TIM_ICSelection_DirectTI;
/* 检查参数有效性 */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
/* 配置与输入极性相反的通道极性 */
if (TIM_ICInitStruct->TIM_ICPolarity == TIM_ICPolarity_Rising)
{
icoppositepolarity = TIM_ICPolarity_Falling;
}
else
{
icoppositepolarity = TIM_ICPolarity_Rising;
}
/* 配置与输入选择相反的通道选择 */
if (TIM_ICInitStruct->TIM_ICSelection == TIM_ICSelection_DirectTI)
{
icoppositeselection = TIM_ICSelection_IndirectTI;
}
else
{
icoppositeselection = TIM_ICSelection_DirectTI;
}
if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_1)
{
/* 配置TI1为上升沿捕获 */
TI1_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection,
TIM_ICInitStruct->TIM_ICFilter);
/* 设置捕获预分频值 */
TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
/* 配置TI2为下降沿捕获 */
TI2_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter);
/* 设置捕获预分频值 */
TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
}
else
{
/* 配置TI2为上升沿捕获 */
TI2_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection,
TIM_ICInitStruct->TIM_ICFilter);
/* 设置捕获预分频值 */
TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
/* 配置TI1为下降沿捕获 */
TI1_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter);
/* 设置捕获预分频值 */
TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
}
}
3. 工作原理解析
3.1 上升沿与下降沿的捕获
在 PWI 模式中,TIM_PWMIConfig()
函数的核心任务是通过对两个通道的极性配置实现 PWM 信号的输入捕获。以 TIM3 为例:
- CH1 捕获上升沿:在函数中,CH1 配置为检测 PWM 信号的上升沿,捕获此时的计数器值。
- CH2 捕获下降沿:CH2 配置为捕获下降沿,从而获取信号的低电平时长。
该函数通过以下逻辑处理:
- 根据通道设置判断 CH1 捕获上升沿,CH2 捕获下降沿。
- 如果配置为上升沿捕获,CH1 的输入极性为
TIM_ICPolarity_Rising
,而 CH2 则配置为相反的极性TIM_ICPolarity_Falling
。 - 两个通道同时捕获相同的输入信号,通过 CH1 和 CH2 捕获到的不同时间点,计算出信号的周期和占空比。
3.2 通道选择
函数中不仅配置了通道的极性,还通过 TIM_ICSelection_DirectTI
和 TIM_ICSelection_IndirectTI
配置输入源:
- DirectTI(直接输入):对应的 TIx 信号源直接连接到输入捕获通道。
- IndirectTI(间接输入):另一个通道的输入信号作为该通道的捕获源。这在 PWI 模式中用于确保同一个引脚可以同时捕获上升沿和下降沿信号。
3.3 输入信号滤波和预分频
TIM_ICInitStruct->TIM_ICFilter
用于配置输入信号的滤波,确保抖动或噪声较大的信号不会误触发输入捕获事件。而 TIM_ICInitStruct->TIM_ICPrescaler
则用于调整输入信号的分频率,适用于需要对信号频率进行压缩测量的情况。
4. 基于标准库的完整 PWI 模式代码
void IC_Init(void)
{
// 使能GPIOA和TIM3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
// 配置PA6为输入模式
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // PA6引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置TIM3基本参数
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructre;
TIM_TimeBaseInitStructre.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructre.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructre.TIM_Period = 65536 - 1; // 自动重装载值 (ARR)
TIM_TimeBaseInitStructre.TIM_Prescaler = 72 - 1; // 预分频值 (PSC)
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructre);
// 配置PWM输入捕获
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; // 通道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 = 0xf; // 滤波
TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
// 配置从模式为复位模式
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); // 选择TI1作为触发输入
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); // 从模式为复位模式
// 启动定时器
TIM_Cmd(TIM3, ENABLE);
}
uint32_t IC_GetFreq(void)
{
return 1000000 / (TIM_GetCapture1(TIM3) + 1); // 单位为Hz
}
uint32_t IC_GetDuty(void)
{
return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);
}
5. 小结
通过对TIM_PWMIConfig()
函数的分析,我们进一步理解了如何通过 STM32 的标准库函数实现对外部 PWM 信号的捕获和测量。这不仅为开发者提供了更灵活的输入捕获配置方式,也让我们看到了 STM32 定时器的强大功能。你在实际使用输入捕获功能时,遇到过哪些挑战?分享你的解决方法吧!