Enkoder a debounce v preruseni

Jan Waclawek konfera na efton.sk
Čtvrtek Říjen 22 16:30:42 CEST 2015


>Ne, B0/B1 to byt nemusi, v podstate slo o nahodny vyber. Ten implementovany 
>dekoder se mi podarilo nejak prehlednout, to by mohlo byt rozumne reseni, 
>urcite ho vyzkousim (nebo se o to aspon pokusim), diky za upozorneni.

Pre inspiraciu:

Inicializacia pinov a zapnutie hodin GPIO a timera su trivialne, dalej
nastavenie timera (tu je pouzity 16-bitvy) mam takto:

  // we need spome filtering
  // the longest filter setting (without setting the tDTS prescaler) is
32*8=256 cycles, i.e. around 3us
  // with DTS prescaler set to its maximum (tdts = 1/4 tck) it's still
around 12us, so we can go all the way for it
    TIM<use name="ENCODER TIMER nr"/>->ARR = 0xFFFF;

    TIM<use name="ENCODER TIMER nr"/>->SMCR = 0
      OR (TIM_SMCR_SMS__ENCODER1   * TIM_SMCR_SMS_0)    // encoder mode 1
-> counter clock
    ;

    TIM<use name="ENCODER TIMER nr"/>->CCMR1 = 0
      OR (TIM_CCMR_CCS__INPUT_TI1  * TIM_CCMR1_CC1S_0)  // capture mode,
input is "own" pin - on both channels
      OR (TIM_CCMR_CCS__INPUT_TI1  * TIM_CCMR1_CC2S_0)
      OR (TIM_CCMR_ICF__32_8S      * TIM_CCMR1_IC1F_0)  // maximum
filtering on both channels
      OR (TIM_CCMR_ICF__32_8S      * TIM_CCMR1_IC2F_0)
    ;
    // no need to set TIM3->CCER, if we don't want to invert some of the
signals

    TIM<use name="ENCODER TIMER nr"/>->CR1 = 0
      OR ( TIM_CR1_CKD__4          * TIM_CR1_CKD_0 )  // tDTS set to
maximum for maximum input capture filtering
      OR ( 1                       * TIM_CR1_CEN   )  // enable the timer
to run freely
    ;


no a potom v hlavnej slucke robim toto (dalo by sa to zrejme urobit aj tak
ze by sa zaplo capture na jeden z tych kanalov, prerusenie od capture a
vyhodnocovalo v tom preruseni):
    static uint16_t oldCnt;
    uint16_t cnt;
    int16_t delta;

    cnt = TIM<use name="ENCODER TIMER nr"/>->CNT AND 0xFFFE;  // timer's
hardware counts on both edges i.e. 2Q, and we need 1Q as that's how the
detents on the encoder are
    delta = (int16_t)(oldCnt - cnt);
    delta /= 2;                  //  ... so we need to div 2; the AND
0xFFFE above is to not to lose the LSB (otherwise two subsequent changes
by 1 in the same direction would both be ignored)
    oldCnt = cnt;

    if (delta != 0) { urob nieco }

wek



Další informace o konferenci Hw-list