TIM—编码器模式注意事项

TIM编码器模式实现如下功能

 代码:

 TIM4的通道1 PB6连接PA1,通道2 PB7连接PA2

用IO口模拟向上计数的输入波形

#include "debug.h"
typedef struct
{
  uint8_t Dir;
  uint16_t Count;
} EncodTypeDef;

#define TIM_IS_TIM_COUNTING_DOWN()    (((TIM1->CTLR1)&TIM_DIR) == (TIM_DIR))

EncodTypeDef encoder;

int main(void)
{
    u16 count=0;

    GPIO_InitTypeDef        GPIO_InitStructure={0};
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure={0};
    TIM_ICInitTypeDef       TIM_ICInitStructure={0};
    NVIC_InitTypeDef        NVIC_InitStructure={0};

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    SystemCoreClockUpdate();
    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n",SystemCoreClock);

    //使能相应时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_ResetBits(GPIOA, GPIO_Pin_1);
    GPIO_ResetBits(GPIOA, GPIO_Pin_2);

    //定时器初始化配置
    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    TIM_TimeBaseStructure.TIM_Period = 0xFFFF;                  //计数器自动重装载值
    TIM_TimeBaseStructure.TIM_Prescaler = 0;                    //预分频器值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //时钟分频
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;            //重复计数器值
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);             //初始化结构体

    TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); //使用编码器模式3
    TIM_ICStructInit(&TIM_ICInitStructure);

    //输入捕获配置
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1|TIM_Channel_2;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;       //输入捕获极性设置,可用于配置编码器正反相
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;             //输入捕获预分频器设置
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;   //输入捕获通道选择,编码器模式需选用此配置
    TIM_ICInitStructure.TIM_ICFilter = 0;                            //输入捕获滤波器设置
    TIM_ICInit(TIM4, &TIM_ICInitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;           //使能中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //设置抢占优先级为1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;         //设置子优先级为2
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //使能外部中断通道
    NVIC_Init(&NVIC_InitStructure);                            //中断优先级分组初始化

    TIM_ClearFlag(TIM4, TIM_FLAG_Update);        //清除TIM更新标志位
    TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);   //使能开启TIM中断

    TIM_SetCounter(TIM4,0);

    TIM_Cmd(TIM4, ENABLE);

    while(1)
    {
        count++;
        if(count==1)
        {
            GPIO_SetBits(GPIOA, GPIO_Pin_1);
        }
        if(count==2)
        {
            GPIO_SetBits(GPIOA, GPIO_Pin_2);
        }
        if(count==3)
        {
            GPIO_ResetBits(GPIOA, GPIO_Pin_1);
        }
        if(count==4)
        {
            GPIO_ResetBits(GPIOA, GPIO_Pin_2);
            count=0;
        }

        encoder.Dir=TIM_IS_TIM_COUNTING_DOWN();
        encoder.Count=TIM_GetCounter(TIM4);
        printf("Dir=%d,count=%d\r\n",encoder.Dir,encoder.Count);
        Delay_Ms(10);
    }
}

void TIM4_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM4_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET)    //是否产生更新(溢出)中断
    {
        TIM_ClearITPendingBit(TIM4,TIM_IT_Update);  //清空TIM中断标志位
    }
}

注意事项:

1.TIM的预分频值设为0,设为1时CNT会除以2。

2.滤波系数TIM_ICFilter,当信号变化速度非常快时,需要设置为0,否则会丢信号,变化速度不是很快时,可以设置高一些,防止干扰,可以参考RM手册中的描述,具体值以测试为准。

posted @ 2023-05-17 18:00  WCH_CH32  阅读(507)  评论(0)    收藏  举报