TIM定时器输入捕获
文章目录
- TIM定时器输入捕获
- 1. 输入捕获
- 1. 输入捕获的工作原理
- 2. 输入捕获的应用场景
- 2.输入捕获配置流程
- 测量频率和占空比的函数
1. 输入捕获
输入捕获是STM32定时器的一项重要功能,它允许微控制器捕捉外部信号的变化(通常是边沿变化),并将当前计数器的值锁定到捕获/比较寄存器中。这项功能非常有用,可以用来测量外部信号的周期、频率、脉宽等参数。
1. 输入捕获的工作原理
-
配置捕获通道:
- 选择定时器的某个捕获/比较通道作为输入捕获通道。
- 配置该通道的触发条件,如上升沿、下降沿或双边沿触发。
-
检测外部信号:
- 当输入信号的电平发生变化(如上升沿或下降沿)时,定时器会捕获当前计数器的值。
- 这个值随后被锁存到对应的捕获/比较寄存器(TIMx_CCRx)中。
-
读取捕获值:
- 用户可以通过读取TIMx_CCRx寄存器来获取捕获到的值。
- 根据计数器的频率和预分频器的设置,可以计算出信号的周期或频率。
2. 输入捕获的应用场景
- 测量信号周期:通过捕获连续两次上升沿的时间差来计算信号周期。
- 测量信号频率:根据信号周期计算信号频率。
- 测量脉冲宽度:测量单个脉冲的持续时间。
- 测量占空比:测量高电平相对于整个周期的比例。
2.输入捕获配置流程
这段代码配置了STM32的通用定时器TIM3以进行输入捕获,并提供了两个函数来计算输入信号的频率和占空比。下面是详细的配置流程解释:
-
启用时钟:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
这两行代码分别启用了TIM3定时器和GPIOA端口的时钟。
-
配置GPIO引脚:
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);
这里配置了GPIOA.6引脚为上拉输入模式。
-
配置TIM3内部时钟:
TIM_InternalClockConfig(TIM3);
这一行配置TIM3使用内部时钟源。
-
配置TIM3基本定时器设置:
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; // ARR TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; // PSC TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
这里设置了TIM3的基本定时器特性:
TIM_ClockDivision
: 设置时钟分割因子为1,即不分频。TIM_CounterMode
: 设置向上计数模式。TIM_Period
: 设置自动装载寄存器值为65535,意味着每65536个计数周期后会重新加载。TIM_Prescaler
: 设置预分频器值为71,意味着实际的预分频器值为72。假设APB1时钟频率为72MHz,则预分频后的频率为1MHz。TIM_RepetitionCounter
: 设置重复计数器为0,不使用重复计数功能。
-
配置TIM3输入捕获通道:
TIM_ICInitTypeDef TIM_ICInitStructure; TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM_ICInitStructure.TIM_ICFilter = 0xF; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
这里配置了TIM3的输入捕获通道1 (CH1):
TIM_Channel_1
: 选择通道1。TIM_ICFilter
: 设置滤波器为16个采样点。TIM_ICPolarity
: 设置触发极性为上升沿。TIM_ICPrescaler
: 设置输入捕获分频器为1,即不分频。TIM_ICSelection
: 选择直接TI模式。TIM_PWMIConfig
:传入其中一个通道,将另外一个通道配置为该通道的相反模式。
-
选择输入触发源:
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
这两行代码配置了TIM3的输入触发源为TI1FP1,并选择了重置模式作为从模式。这意味着每当捕获到TI1FP1的上升沿时,定时器将被重置。
-
使能TIM3:
TIM_Cmd(TIM3, ENABLE);
最后,使能TIM3定时器。
测量频率和占空比的函数
-
测量频率:
uint32_t IC_GetFreq(void) {return 1000000 / (TIM_GetCapture1(TIM3) + 1); }
这个函数通过读取TIM3的捕获1寄存器的值来计算输入信号的频率。
-
测量占空比:
uint32_t IC_GetDuty(void) {return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1); }
这个函数通过读取TIM3的捕获2寄存器的值来计算输入信号的占空比。
完整代码:
#include "stm32f10x.h" // Device headervoid IC_Init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);TIM_InternalClockConfig(TIM3);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARRTIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);TIM_ICInitTypeDef TIM_ICInitStructure;TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;TIM_ICInitStructure.TIM_ICFilter = 0xF;TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);TIM_Cmd(TIM3, ENABLE);
}uint32_t IC_GetFreq(void)
{return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}uint32_t IC_GetDuty(void)
{return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);
}