输入捕获是对外部输入信号高低电平的捕获,发生在边沿跳变处,也就是低电平变为高电平时(或高电平变为低电平时)。
输入捕获框图
根据参考手册输入捕获的框图如下。
可以发现三个重要的部分。
1.滤波器部分
2.边沿检测部分
3.分频器部分
滤波器
在按键驱动代码的编写中,会在软件层面(当然也可在硬件上实现)加按键的滤波算法。因为按键按下或抬起的前后过程中会出现抖动。这里滤波器的目的是一样的,根据设置滤波器是防止出现抖动造成误判。
边沿检测
这里是对边沿跳变进行检测,检测到边沿跳变时,将计数器内的值锁定到CCMR寄存器。
可以看到这一部分有三个通道,一个通道1的,一个通道2的,一个从模式。通道1这条路径,是从通道的输入直接过来,通道2的这条路径是从通道2经过通道2的滤波器、边沿检测传过来。
这种可以实现一个很简单的检测,以通道2为例,通道2输入某一周期和频率的pwm波,通道2直接路径捕获高电平,间接路径(也就是通道2经过滤波边沿检测后走通道1)捕获低电平.这样可以很方便的计算pwm的占空比。
分频
这一部分主要是经过几次捕获信号才将计数器的值锁存到ccmr中。
如果是2分频,上升沿捕获,表示发生两次上升沿是才触发一次输入捕获。
hal解析
这是输入捕获配置基本参数的函数:
HAL_StatusTypeDef HAL_TIM_IC_Init(TIM_HandleTypeDef *htim)
参数结构体的具体如下:
我们经常配置的是前两个参数,
TIM_TypeDef *Instance; /*!< Register base address */
TIM_Base_InitTypeDef Init; /*!< TIM Time Base required parameters */
第一个参数是表示使用那个定时器,有以下值:
第二个参数结构体内参数如下:
typedef struct
{
uint32_t Prescaler; /*!< Specifies the prescaler value used to divide the TIM clock.
This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */
uint32_t CounterMode; /*!< Specifies the counter mode.
This parameter can be a value of @ref TIM_Counter_Mode */
uint32_t Period; /*!< Specifies the period value to be loaded into the active
Auto-Reload Register at the next update event.
This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t ClockDivision; /*!< Specifies the clock division.
This parameter can be a value of @ref TIM_ClockDivision */
uint32_t RepetitionCounter; /*!< Specifies the repetition counter value. Each time the RCR downcounter
reaches zero, an update event is generated and counting restarts
from the RCR value (N).
This means in PWM mode that (N+1) corresponds to:
- the number of PWM periods in edge-aligned mode
- the number of half PWM period in center-aligned mode
GP timers: this parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF.
Advanced timers: this parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t AutoReloadPreload; /*!< Specifies the auto-reload preload.
This parameter can be a value of @ref TIM_AutoReloadPreload */
} TIM_Base_InitTypeDef;
Prescaler:预分频设置,就是将定时器的时钟源进行分频
CounterMode:计数模式,向上、向下、双边沿
Period:计数,就是在分频后是时钟频率下,记多少个数
ClockDivision:分频,在定时功能不设置也不影响,是cr1寄存器的ckd位。
RepetitionCounter:重复计数,当设置好Period时,从0计数到Period时,会从0重新计数(向上模式时),如果开启中断计数到Period时会进入中断,但是当设置该参数为2时,会在第二次计数到Period才进入中断。
AutoReloadPreload:是否开启影子寄存器,也就是当修改计数值Period时,是立即生效还是,在完成本次计数后再生效。
通道配置:
HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, TIM_IC_InitTypeDef *sConfig, uint32_t Channel)
TIM_HandleTypeDef *htim:基础配置的结构体
TIM_IC_InitTypeDef *sConfig:通道配置的结构体
uint32_t Channel:所使用的通道(一般是4个通道,但也不绝对,具体查看数据手册)
TIM_IC_InitTypeDef *sConfig解析:
typedef struct
{
uint32_t ICPolarity; /*!< Specifies the active edge of the input signal.
This parameter can be a value of @ref TIM_Input_Capture_Polarity */
uint32_t ICSelection; /*!< Specifies the input.
This parameter can be a value of @ref TIM_Input_Capture_Selection */
uint32_t ICPrescaler; /*!< Specifies the Input Capture Prescaler.
This parameter can be a value of @ref TIM_Input_Capture_Prescaler */
uint32_t ICFilter; /*!< Specifies the input capture filter.
This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */
} TIM_IC_InitTypeDef;
ICPolarity:输入捕获极性,是捕获上升沿、下降沿还是双边沿
ICSelection:输入捕获通道,捕获通道选择,是输入1直接映射通道1,还是输入1映射通道1,输入2映射通道2
ICPrescaler:也是分频,是捕获到几个极性信号后,将计数器的值锁存到ccmr寄存器中
ICFilter:滤波,这个和基础配置的ClockDivision参数有关联
配置完后就可以使用
HAL_TIM_IC_Start(), HAL_TIM_IC_Start_DMA(), HAL_TIM_IC_Start_IT(),开启输入捕获
总结:
基础配置和通道配置有几个分频,千万不要弄混了
基础配置有一个时钟分频,是配置计数器的时钟频率
还有一个ckd是用于配置后面滤波器
输入捕获通道的分频,是表示捕获几次边沿才触发中断(如果开启中断)。
输入捕获其实就是对通道输入信号的边沿进行捕获,当捕获到配置的边沿信号时,将计数器的值锁定到ccmr寄存器中,如果开启中断就进入中断。