STM32外接编码器时的多圈计数脉冲

2019-10-15 20:42发布

本帖最后由 magicoctoy 于 2017-1-3 14:08 编辑

直接上代码:
/*********************************************************************************************************
编码器脉冲数/1圈
*********************************************************************************************************/
#define ENCODER_PULSE                1000


int main(void)
{
    TimerEncoderInit(TIM2);                        /* 编码器2初始化 */               
        while(1){
                /* 系统灯 1S/闪亮1次 */
                if(DelayBuf.SystemLedRunning > 100){
                        DelayBuf.SystemLedRunning = 0;
                        LedSystemRun = ~LedSystemRun;
                }
                Encoder2.Counter = TIM_GetCounter(TIM2);
                /* 计算方案2,适用于多圈,且十分简单。
                   总脉冲 = 单圈实时脉冲值 + (圈数 * 编码器单圈脉冲值 * 4倍数速)
                   单圈实时脉冲值:通过获取 TIM_GetCounter(TIMx)。
                   圈数:定时器溢出中断中得到。
                   编码器单圈脉冲值:编码器参数。
                   4倍数速:定时器设定值,A相和B相上下沿都计数。*/
                Encoder2.Pulse = Encoder2.Counter + (Encoder2.Circle * ENCODER_PULSE * 4);        
                /* 计算方案1,适用于单圈,多圈时必须在溢出时增加判断,否则有误。 */
//                Encoder2.Pulse += Timer2GetCount();

        }


}

/*
*********************************************************************************************************
* 函数名称: TimerEncoderInit
* 函数功能: 定时器/计数器,编码器接入初始化配置
* 输入参数:timer:TIM1~TIM4。
* 输出参数:无
* 返回值:  无
* 说明:   
*********************************************************************************************************
*/
void TimerEncoderInit(TIM_TypeDef* timer)
{
GPIO_InitTypeDef                         GPIO_InitStructure;
TIM_TimeBaseInitTypeDef          TIM_TimeBaseStructure;
TIM_ICInitTypeDef                         TIM_ICInitStructure;
NVIC_InitTypeDef                         NVIC_InitStructure;
/*----------------------------------------------------------------*/
        if(timer == TIM1){
                RCC_APB2PeriphClockCmd(ENCODER_1_RCC, ENABLE);
               
                GPIO_InitStructure.GPIO_Pin = ENCODER_1_PIN;
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
                GPIO_Init(ENCODER_1_PORT, &GPIO_InitStructure);

                NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
//                NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
//                NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
                NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
                NVIC_Init(&NVIC_InitStructure);        

                RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
        }else if(timer == TIM2){
                RCC_APB2PeriphClockCmd(ENCODER_2_RCC, ENABLE);
               
                GPIO_InitStructure.GPIO_Pin = ENCODER_2_PIN;
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
                GPIO_Init(ENCODER_2_PORT, &GPIO_InitStructure);

                NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
//                NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
//                NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
                NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
                NVIC_Init(&NVIC_InitStructure);        

                RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);               
        }else if(timer == TIM3){
                RCC_APB2PeriphClockCmd(ENCODER_3_RCC, ENABLE);
               
                GPIO_InitStructure.GPIO_Pin = ENCODER_3_PIN;
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
                GPIO_Init(ENCODER_3_PORT, &GPIO_InitStructure);

                NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
//                NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
//                NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
                NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
                NVIC_Init(&NVIC_InitStructure);        

                RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
        }else if(timer == TIM4){
                RCC_APB2PeriphClockCmd(ENCODER_4_RCC, ENABLE);
               
                GPIO_InitStructure.GPIO_Pin = ENCODER_4_PIN;
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
                GPIO_Init(ENCODER_4_PORT, &GPIO_InitStructure);

                NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
//                NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
//                NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
                NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
                NVIC_Init(&NVIC_InitStructure);        

                RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);        
        }
        
/*----------------------------------------------------------------*/
    /*初始化TIM1定时器-时间基数 */   
    TIM_TimeBaseStructure.TIM_Period =(ENCODER_PULSE * 4)-1;    //设定计数器重装值
    TIM_TimeBaseStructure.TIM_Prescaler =0;                                                //设置预分频,=0无预分频器,捕获输入口上检测到的每一个边沿都触发一次捕获
    TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ;     //设置时钟分频系数:不分频
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式,DIR方向    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;                        //重复计数设置(高级定时器TIM1和TIM8)不加进不了定时器1和8中断
    TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);   
/*-----------------------------------------------------------------*/
    /* 编码配置-编码模式 */
    TIM_EncoderInterfaceConfig(timer, TIM_EncoderMode_TI12,
    TIM_ICPolarity_BothEdge ,TIM_ICPolarity_BothEdge);                  //使用编码器模式3,上升下降都计数
/*----------------------------------------------------------------*/
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;        //TIM输入捕获上升沿
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//TIM输入1/2/3/4选择对应的与IC1/IC2/IC3/IC4相连
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;                 //TIM捕获在捕获输入上每探测到一个边沿执行一次
    TIM_ICInitStructure.TIM_ICFilter = 6;                               //选择输入比较滤波器:0x0~0xF
    TIM_ICInit(timer, &TIM_ICInitStructure);                             //将TIM_ICInitStructure中的指定参数初始化TIM3
/*----------------------------------------------------------------*/
        TIM_ClearFlag(timer, TIM_FLAG_Update);                                                //清除,溢出更新中断。
        TIM_ITConfig(timer, TIM_IT_Update, ENABLE);                                   //使能,溢出更新中断,计数器向上溢出/向下溢出。
/*----------------------------------------------------------------*/
        if(timer == TIM1){
//                TIM1->CNT =0;                                                                                        //复位计数值
                TIM_SetCounter(TIM1,0);
        }else if(timer == TIM2){
                TIM_SetCounter(TIM2,0);               
        }else if(timer == TIM3){
                TIM_SetCounter(TIM3,0);               
        }else if(timer == TIM4){
                TIM_SetCounter(TIM4,0);               
        }
        TIM_Cmd(timer, ENABLE);                                                                           //使能定时器
/*----------------------------------------------------------------*/         
}


/*
*********************************************************************************************************
* 函数名称: TIM2_IRQHandler
* 函数功能: TIM2中断处理函数
* 输入参数:无
* 输出参数:无
* 返回值:  无
* 说明:   
*********************************************************************************************************
*/
void TIM2_IRQHandler(void)
{        
    if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET){      
        TIM_ClearITPendingBit(TIM2,TIM_IT_Update);        /* 清除中断标志 */
                Encoder2.Counter = TIM_GetCounter(TIM2);
                if((((TIM2->CR1)&0x0010)>>4) == 1){                  /* 判断计数器计数方向 */   
            /* =1,向下计数 */
                        Encoder2.Direction = 1;        
                        Encoder2.Circle --;                 
                }else{  
            /* =0,向上计数 */                        
                        Encoder2.Direction = 0;
                        Encoder2.Circle ++;
                }               
    }   
}
/*
*********************************************************************************************************
* 函数名称: Timer2GetCount
* 函数功能: TIM2得到编码器脉冲值。
* 输入参数:无
* 输出参数:无
* 返回值:  无
* 说明:   
*********************************************************************************************************
*/
s32 Timer2GetCount(void)
{
static u16 lastCount = 0;
u16  nowCount;
s32 pulse;
        
        nowCount = TIM_GetCounter(TIM2);
        
        pulse = nowCount - lastCount;
        
        if(pulse >= (ENCODER_PULSE/2)){
                pulse -= ENCODER_PULSE;
        }else if(pulse < -(ENCODER_PULSE/2)){
                pulse += ENCODER_PULSE;
        }
        lastCount = nowCount;
        
        return (s32)pulse;
}



0条回答

一周热门 更多>