本帖最后由 lx911gt 于 2016-5-31 13:55 编辑
昨天下班前看到几个小伙伴在搞正交编码器??
之前我也摆弄过,但是没咋用过,正常识别没问题,原理就不讲了,坛子里有,百度也能搜
如果是音响编码器的话不要直接接入单片机,要么加个正交识别模块,要么自己随便整个整形的电路,因为音响编码器那玩是开关量,抖动太严重,如果靠软件滤波的话做起来其实挺逗比的,而且效果很可能并不理想
音响编码器我就用了两个三极管,电容电阻啥的整了下形就OK了
程序分两种,一个是用定时器的编码器模式,另一个是外部中断方式的
其实不建议用中断方式,原因我想大家都知道的,如果非要用外部中断的方式的话,还是建议看看能不能利用上DMA来减少中断次数,这个我没做,但是应该不是那么难吧
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
假设a上升沿,b低电平为正转,那应该怎么判断呢?
我用的if()先判断低电平,下次再判断高电平且前一次为低电平,这就是上升沿了,但如果两次判断跟方波周期相同了,会不会每次判断都是高电平或低电平呢?
如果在while里做是不行的,没有实时性,在中断里的话很简单,先看时序,如果上升沿中断,看上升沿对应的B项,肯定对应的是高或低电平,这时在中断里直接if(B项电平 )或if(!B项电平)就行了
1.我的代码里面 TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising ,TIM_ICPolarity_Rising); 是这样设置的,a,b相上升沿和下降沿都会产生计数,那么我的定时器的预设值是否应该是4*线数-1?
2.通过定时器得到了脉冲数之后,怎么计算速度?
3.能否楼主帮我看一下这段代码如何获取角度的?我刚开始学32,对于最后的中断处理程序搞不懂。。。
static int count=0;
static unsigned char firstflagcount=1;
/////初始化程序省略
/*******************************************************************************
* Function Name : ENC_Get_Electrical_Angle
* Description : Returns the absolute electrical Rotor angle
* Input : None
* Output : None
* Return : Rotor electrical angle: 0 -> 0 degrees,
* S16_MAX-> 180 degrees,
* S16_MIN-> -180 degrees
*******************************************************************************/
float ENC_Get_Electrical_Angle(void)
{
float temp;
temp = (TIM_GetCounter(ENCODER_TIMER)*1.0) *( 180.0/ (ENCODER_PPR))+180.0*count; //ÎÊÌâ5£ºÕâÀïΪʲҪ´ó·ÑÖÜÕÛÕâÑù×ö
return(temp);
}
/*******************************************************************************
* Function Name : LCD_Display
* Description : This function handles the display of timer counter, theta and
electronical frequency:
theta --- resolution: 1 degree; //resolution ·Ö±æÂÊ
electronical frequency --- resolution: 0.1Hz.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void LCD_Display(void)
{
float Theta;
u16 pulse;
char str[9];
pulse=TIM_GetCounter(ENCODER_TIMER);
Theta = ENC_Get_Electrical_Angle();
sprintf(str,"%6.2f",Theta);
LcdPutString(0,8,(char *)str);
sprintf(str,"%6d",rev);
LcdPutString(1,6,(char *)str);
sprintf(str,"%6d",pulse);
LcdPutString(2,6,(char *)str);
}
/*******************************************************************************
* Function Name : TIM3_IRQHandler
* Description : This function handles TIMx Update interrupt request.
Encoder unit connected to TIM3
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TIM3_IRQHandler(void)
{
/* Clear the interrupt pending flag */
TIM_ClearITPendingBit(ENCODER_TIMER, TIM_FLAG_Update);
if((TIM3->CR1 & 0x0010)==0x0010) //Èç¹ûΪÏòϼÆÊý
{
if(count==0) //Èç¹ûTIM3Ϊ
{
count=1;
if(firstflagcount ==1)
{
firstflagcount=0;
}
else
{
rev--;
}
}
else
count--;
}
else //Èç¹ûΪÏòÉϼÆÊý
{
count++;
if(count >= 2)
{
count=0;
rev++;
}
}
}
一周热门 更多>