stm32编码器模式

2019-10-16 05:58发布

我最近有一个项目要利用stm32的编码器模式计数,我很苦恼,我想用原子的寄存器设置模式,库函数的我没有很好的接触,我自己也配置了,可是lcd上始终显示不到数字,这是库函数的程序:
void ENC_Init(void) {   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;   TIM_ICInitTypeDef TIM_ICInitStructure;   GPIO_InitTypeDef GPIO_InitStructure;   NVIC_InitTypeDef NVIC_InitStructure;      RCC_APB1PeriphClockCmd(RCC_APBPeriph_ENCODER_TIMER, ENABLE);   // ENCODER_TIMER时钟初始化   RCC_APB2PeriphClockCmd(RCC_APBPeriph_ENCODER_GPIO, ENABLE);   // ENCODER_GPIO时钟初始化      GPIO_StructInit(&GPIO_InitStructure);  //TI1 TI2初始化   GPIO_InitStructure.GPIO_Pin = ENCODER_TI1 | ENCODER_TI2;   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入   GPIO_Init(ENCODER_GPIO, &GPIO_InitStructure);      NVIC_InitStructure.NVIC_IRQChannel = TIMER_IRQChannel; //设置ENCODER_TIMER的优先级   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRIORITY;   NVIC_InitStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY;   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   NVIC_Init(&NVIC_InitStructure);
  /* Timer configuration in Encoder mode */ //设置ENCODER_TIMER为编码器模式   TIM_DeInit(ENCODER_TIMER);   //ENCODER_TIMER复位   TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);      TIM_TimeBaseStructure.TIM_Prescaler = 0x0;  // 无分频   TIM_TimeBaseStructure.TIM_Period = (4*ENCODER_PPR)-1; //计数器重载值 设置了在下一个更新事件装入活动的自动重装载寄存器周期的值   TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //设置时钟分割   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式      TIM_TimeBaseInit(ENCODER_TIMER, &TIM_TimeBaseStructure);     TIM_EncoderInterfaceConfig(ENCODER_TIMER, TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); //编码器接口初始化   //TIM_ICPolarity_Rising:  TIM输入捕获上升沿   TIM_ICStructInit(&TIM_ICInitStructure);   TIM_ICInitStructure.TIM_ICFilter = ICx_FILTER; // TIM_ICFilter选择输入比较滤波器。该参数取值在0x0和0xF之间   TIM_ICInit(ENCODER_TIMER, &TIM_ICInitStructure);     // Clear all pending interrupts   TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);// 清除TIMx的待处理标志位   TIM_ITConfig(ENCODER_TIMER, TIM_IT_Update, ENABLE);  //使能或者失能指定的TIM中断   //Reset counter   TIM2->CNT = COUNTER_RESET;   
     TIM_Cmd(ENCODER_TIMER, ENABLE);  //  使能或者失能TIMx外设 } //**************************************************************************************************** // 计算马达转子相对于初始位置的角度  -180至+180 //**************************************************************************************************** void ENC_Get_Electrical_Angle(uint16_t *degree) { int32_t temp; int16_t tim_count;   tim_count=TIM_GetCounter(ENCODER_TIMER);   //获取ENCODER_TIMER的值 if(tim_count>=400) //如果超过180度,角度为负数 { degree[0]='-'; degree[1]=(800-tim_count)*180/(4*ENCODER_PPR/2); //整数部分 temp = (int32_t)(800-tim_count) * (int32_t)(1000000/(4*ENCODER_PPR/2))*360-degree[1]*1000000;    degree[2]=(unsigned char)temp; //小数部分 } else //如果未超过180度,角度为正数 { degree[0]='+'; degree[1]=tim_count*180/(4*ENCODER_PPR/2); //整数部分 temp = (int32_t)tim_count * (int32_t)(1000000/(4*ENCODER_PPR/2))*180-degree[1]*1000000;    degree[2]=(unsigned char)temp;   //小数部分 } } //**************************************************************************************************** //TIm2_IRQ 计算编码器每秒钟产生的脉冲数 //************************************************************************************************** void Tim2_IRQ(void) {   unsigned int temp; if(Count[0]==0) { Count[0]++; //以便下次读取并计算 Count[2]=Count[1]; Encoder_TIM_Count[0]=TIM_GetCounter(ENCODER_TIMER); //第一次读取ENCODER_TIMER的值 } else   { temp=Count[1]-Count[2]; //ENCODER_TIMER溢出次数 Encoder_TIM_Count[1]=TIM_GetCounter(ENCODER_TIMER); //第二次读取ENCODER_TIMER的值 Count[0]=0; Count[1]=0; if(temp==0) //如果ENCODER_TIMER溢出次数为0 { if(Encoder_TIM_Count[1]>=Encoder_TIM_Count[0]) { Speed[1]=(Encoder_TIM_Count[1]-Encoder_TIM_Count[0])*8;  //每秒的脉冲数等于两次计数器差的绝对值*4 } else { Speed[1]=(Encoder_TIM_Count[0]-Encoder_TIM_Count[1])*8; } } else //如果ENCODER_TIMER溢出次数不为0 { if(Speed[0]=='+') //如果ENCODER_TIMER正向溢出  { if(Encoder_TIM_Count[1]>=Encoder_TIM_Count[0]) { Speed[1]=(Encoder_TIM_Count[1]-Encoder_TIM_Count[0]+(4*ENCODER_PPR)*temp)*8; } else   { Speed[1]=(800-Encoder_TIM_Count[0]+Encoder_TIM_Count[1]+(4*ENCODER_PPR)*(temp-1))*8; } else //如果ENCODER_TIMER逆向溢出 { Speed[1]=(800-Encoder_TIM_Count[1]+Encoder_TIM_Count[0]+(4*ENCODER_PPR)*(temp-1))*8; } } }
} //**************************************************************************************************** //TIm4_IRQ   获得溢出此数count[1]和旋转方向speed //**************************************************************************************************** void Tim4_IRQ(void) { unsigned int temp; Count[1]++;
 /* Clear the interrupt pending flag */ TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);
temp=TIM_GetCounter(ENCODER_TIMER); if(temp==0)  //如果计数器的值为0,则正向旋转 Speed[0]='+'; else if(temp==799)   //如果计数器的值为0,则逆向旋转 Speed[0]='-';   }
库函数版本的编码器很多例子,可是原子大哥配置的寄存器模式,不知道哪位大哥、大神可曾经调试过,或者有什么经验,可以交流一下,我的qq号是505021476,谢谢了!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
6条回答
HC0821
2019-10-16 16:15
/*Configure TIM2 TIM3 TIM4 TIM5 as Encoder Interfaces input*/
/*TIM base Configuration*/
    TIM_TimeBaseInitStructure.TIM_Prescaler = 0;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period = 65535;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;

/*预分频=1,向上计数,不分频,自动重装载=65535,软件产生一次更新事件(UG)*/
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);
TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);

/*编码器模式3,通道1、2为输入,映射到TI1、2上;        IC1输入捕获在上升沿;      IC2输入捕获在上升沿*/
TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); 
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_EncoderInterfaceConfig(TIM5, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);

    /* TIM2 3 4 enable counter */
    TIM_Cmd(TIM2, ENABLE);
    TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM4, ENABLE); 
TIM_Cmd(TIM5, ENABLE); 

我用过这段代码,使用TIM2345作为伺服电机的闭环反馈,对码盘反馈脉冲周期计数从而测得实际速度。
使用时注意TIMx的通道引脚映射;以上函数为V3.50的库

一周热门 更多>