32 timer input filter

STM32定时器的输入滤波机制 
  

STM32的定时器输入通道都有一个滤波单元,分别位于每个输入通路上(下图中的黄色框)和外部触发输入通路上(下图中的兰色框),它们的作用是滤除输入信号上的高频干扰。



具体操作原理如下:


在TIMx_CR1中的CKD[1:0]可以由用户设置对输入信号的采样频率基准,有三种选择:
1)采样频率基准fDTS=定时器输入频率fCK_INT
2)采样频率基准fDTS=定时器输入频率fCK_INT/2
3)采样频率基准fDTS=定时器输入频率fCK_INT/4


然后使用上述频率作为基准对输入信号进行采样,当连续采样到N次个有效电平时,认为一次有效的输入电平。


实际的采样频率和采样次数可以由用户程序根据需要选择;外部触发输入通道的滤波参数在从模式控制寄存器(TIMx_SMCR)的ETF[3:0]中设置;每个输入通道的滤波参数在捕获/比较模式寄存器1(TIMx_CCMR1)或捕获/比较模式寄存器2(TIMx_CCMR2)的IC1F[3:0]、IC2F[3:0]、IC3F[3:0]和IC4F[3:0]中设置。






例如:当fCK_INT=72MHz时,选择fDTS=fCK_INT/2=36MHz,采样频率fSAMPLING=fDTS/2=18MHz且N=6,则频率高于3MHz的信号将被这个滤波器滤除,有效地屏蔽了高于3MHz的干扰。




比如,结合输入捕获的中断,可以轻松地实现按键的去抖动功能,而不需要软件的干预;这可是由硬件实现的去抖动功能,大大节省了软件的开销和程序代码的长度。


每个定时器最多可以实现4个按键的输入,这个方法也可以用于键盘矩阵的扫描,而且因为是通过中断实现,软件不需频繁的进行扫描动作

--------------------------------------------------------------------------------------------------------------------------------------------------------------

滤波器对输入信号进行采样,当连续采样到N个有效电平时,认为一次有效的输入电平。这里采样频率是18MHz,那么两次采样之间的时间间隔是1/18MHz。那么如果要连续采样到6个有效电平需要的时间是1/3MHz,所以对于脉冲宽度小于1/3MHz的信号来说是永远不可能连续采样到6个有效电平的,所以对于大于3MHz的信号来说,其脉冲宽度小于1/3MHz,因此被滤掉。

----------------------------------------------------------------------------------------------------------------------------------

如果APB1预分频系数=1,那么timer2-7的时钟就是APB1的时钟,如果APB1的预分频系数不等于1,那么APB1的时钟乘以2之后就是定时器timer2-7的时钟, 
系统初始化的时候,APB1的分频系数好像是2吧(两分频),然后APB1的时钟是36MHz,那么,由于分频系数不是1,所以,timer2-7的时钟是APB1时钟的两倍,所以定时器的时钟就是72MHz了。

----------------------------------------------------------------------------------------------------------------------------------

1)当滤波器连续采样到N次个有效电平时,认为一次有效的输入电平。
2)该数字滤波器实际上是个事件计数器,它记录到N个事件后会产生一个输出的跳变。
例如:当f(CK_INT) = 72MHz, CKD[1:0] = 01时,选择f(DTS) = f(CK_INT)/2 = 36MHz;
而ETF[3:0] = 0100,则采样频率f(SAMPLING) = f(DTS) / 2 = 18MHz, N = 6,此时高于3MHz的信号
将被这个滤波器滤除,这样就有效地屏蔽了高于3MHz的干扰。


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
接口程序 以下是一个使用合泰单片机HT32F52352编码器接口的示例程序。此程序演示了如何使用HT32F52352的定时器和GPIO模块来读取编码器的脉冲信号并计算其位置。 ``` #include "ht32f5xxxx_01.h" #include "ht32f52352_sk.h" #define ENCODER_PIN_A GPIO_PIN_12 #define ENCODER_PIN_B GPIO_PIN_13 int main(void) { CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}}; NVIC_InitTypeDef NVIC_InitStructure = {0}; GPIO_InitTypeDef GPIO_InitStructure = {0}; TMR_TimerBaseInitTypeDef TIM_InitStructure = {0}; TMR_EncoderInitTypeDef ENC_InitStructure = {0}; // Enable the peripheral clock for GPIO and Timer modules CKCUClock.Bit.GPIO = 1; CKCUClock.Bit.TIMER0 = 1; CKCUClock.Bit.TIMER1 = 1; CKCUClock.Bit.TIMER2 = 1; CKCUClock.Bit.TIMER3 = 1; CKCU_PeripClockConfig(CKCUClock, ENABLE); // Configure GPIO pins for encoder input GPIO_InitStructure.GPIO_Pin = ENCODER_PIN_A | ENCODER_PIN_B; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_IPD; // Input with pull-down GPIO_InitStructure.GPIO_Pull = GPIO_PULL_DOWN; GPIO_Init(GPIOC, &GPIO_InitStructure); // Configure Timer module for encoder input TIM_InitStructure.TMR_Prescaler = 0; // No prescaling TIM_InitStructure.TMR_Period = 65535; // Max period TIM_InitStructure.TMR_ClockDivision = TMR_CDIV_DIV1; // No clock division TIM_InitStructure.TMR_CounterMode = TMR_CNT_MODE_UP; // Count up TMR_TimerBaseInit(TIMER0, &TIM_InitStructure); // Configure Encoder module for Timer module ENC_InitStructure.TMR_EncoderMode = TMR_ENCODER_MODE_QUADRATURE_X4; // Quadrature X4 mode ENC_InitStructure.TMR_IC1Polarity = TMR_IC_POLARITY_RISING; // Rising edge ENC_InitStructure.TMR_IC2Polarity = TMR_IC_POLARITY_RISING; // Rising edge ENC_InitStructure.TMR_IC1Prescaler = TMR_IC_PSC_DIV1; // No prescaling ENC_InitStructure.TMR_IC2Prescaler = TMR_IC_PSC_DIV1; // No prescaling ENC_InitStructure.TMR_IC1Filter = 0; // No filter ENC_InitStructure.TMR_IC2Filter = 0; // No filter TMR_EncoderInit(TIMER0, &ENC_InitStructure); // Enable interrupt for Timer module NVIC_InitStructure.NVIC_IRQChannel = TIMER0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // Enable interrupt for Timer module overflow TMR_IntConfig(TIMER0, TMR_INT_UIF, ENABLE); // Start Timer module TMR_Cmd(TIMER0, ENABLE); while (1) { // Do something here } } void TIMER0_IRQHandler(void) { if (TMR_GetIntStatus(TIMER0, TMR_INT_UIF) == SET) { // Handle Timer module overflow here // Calculate encoder position using TMR_GetCounterValue(TIMER0) function // Reset Timer module counter using TMR_SetCounterValue(TIMER0, 0) function TMR_ClearIntPendingBit(TIMER0, TMR_INT_UIF); } } ``` 在此示例程序中,我们首先启用了GPIO和Timer模块的外围时钟。然后我们配置GPIO模块来读取编码器的脉冲信号,并配置Timer模块来计算编码器的位置。我们使用Timer0来计算位置,因此我们使用TMR_TimerBaseInitTypeDef结构体来初始化Timer0的基本参数。我们将Timer0的计数器模式设置为向上计数,并将其预分频器,时钟分频器和周期设置为最小值,以获得最高的计数速度。接下来,我们使用TMR_EncoderInitTypeDef结构体来初始化Timer0的编码器参数。我们将编码器模式设置为Quadrature X4,这意味着我们将使用四个脉冲信号来确定编码器位置。我们还将输入捕获极性设置为上升沿,并将预分频器和滤波器设置为最小值。最后,我们启用了Timer0的中断和溢出中断,并在主循环中等待处理编码器位置。在中断处理程序中,我们处理Timer模块的溢出中断,并使用TMR_GetCounterValue函数获取当前的编码器位置。然后,我们使用TMR_SetCounterValue函数将Timer0的计数器重置为0,以便在下一个溢出时重新开始计数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值