1。编码器原理
什么是正交?若是两个信号相位相差90度,则这两个信号称为正交。因为两个信号相差90度,所以能够根据两个信号哪一个先哪一个后来判断方向。算法
这里使用了TI12模式,例如当T1上升沿,T2在低电平时;T1降低沿,T2在高电平时,向上计数,这样的好处是当有毛刺产生的时候,会自动+1 -1过滤掉毛刺。编码
2。编码器的中断blog
因为编码器是基于定时器的,因此编码器的中断实际上就是定时器的中断。也就是说定时器是每隔必定时间加一个数(或减一个数 ),当数到达预设值时就产生中断,而编码器是每个有效脉冲就加一个数(或减一个数 ),当数到达预设值时就产生中断。若预设值为1000则编码器与定时器中断不一样的是,当编码器反转时值到达999产生一次中断,而当编码器正转到达0时同 样产生一次中断。在硬件上这两个中断是无法区分的,这也就形成了有种状况的误判。io
3。STM32编码器没有考虑的状况ast
想象一下,若是编码器的预设值为1000,当某次咱们使得编码器正转产生中断后,当即反转则又该怎么办呢?根据上面的说法,这时候会产生两次同样的中断。 若是在算法上没有处理的话,极有可能认为是行走了两次正向。但实际上并无。因此这个时候必须结合方向来判断行走的状况(判断方向使用的是DIR寄存器 位)或者在产生中断后读一次count寄存器位(看看是999仍是0,以此来判断当前的方向)。只有上一次为正且这一次一样为正,距离才是相加的。变量
4。STM32f1系列定时器16位的问题原理
我用STM32的定时器3工做于编码器方式,能够正常获得编码器位置,但因为如今只有16位计数,位数不够,我想扩展到32位,能够先用定时器内部链接,将定时器3 的溢出送到定时器2,用定时器2作高位,在正转的时候正常,但反向的时候出错。换了个思路,作个每10ms产生一次的中断,在中断中调用下面的代码,下述代码中MAX_COUNT是 比 10ms内可能出现的计数最大值还要大的值,ENCODER_TIM_PERIOD是定时器的period值,最比如MAX_COUNT大,而后定义一个32位的有符号变量,如currentCount,而后每隔10ms执行一次currentCount += Enc_GetCount();只须要去读取currentCount的值就能够获得位移信息了。扩展
s16 Enc_GetCount(void)
{
static u16 lastCount = 0;
u16 curCount = ENCODER_TIM->CNT;
s32 dAngle = curCount - lastCount;
if(dAngle >= MAX_COUNT){
dAngle -= ENCODER_TIM_PERIOD;
}else if(dAngle < -MAX_COUNT){
dAngle += ENCODER_TIM_PERIOD;
}
lastCount = curCount;
return (s16)dAngle;
}软件
5。其它一些获得的信息硬件
1.编码器有个转速上限,超过这个上限是不能正常工做的,这个是硬件的限制,原则上线数越多转速就越低,这点在选型时要注意,编码器的输出通常是开漏的,因此单片机的io必定要上拉输入状态. 2.定时器初始化好之后,任什么时候候CNT寄存器的值就是编码器的位置信息,正转他会加反转他会减这部分是不须要软件干预的,初始化时给的TIM_Period 值应该是码盘整圈的刻度值,在减溢出会自动修正为这个数.加超过此数值就回0. 3.若是要扩展成多圈计数须要溢出中断,程序上圈计数加减方向位就好了. 4.每一个定时器的输入脚能够经过软件设定滤波 5.应用中若是没有绝对位置信号或者初始化完成后尚未收到绝对位置信号前的计数只能是相对计数.收到绝对位置信号后从新修改一次CNT的值就好了.码盘通常都有零位置信号,结合到定时器捕获输入就行.上电之后要往返运动一下找到这个位置. 6.即使有滤波计数值偶尔也会有出错误的状况,一圈多计一个或少计一个数都是很正常的特别是转速比较高的时候尤为明显,有个绝对位置信号作修正是颇有必要的.绝对位置信号不须要必定在零位置点,收到这个信号就将CNT修正为一个固定的数值便可. 7.开启定时器的输入中断能够达到每一个步计数都做处理的效果,可是高速运转的时候你可能处理不过来.