Tue Jul 27 2004 22:14, Vladislav Baliasov wrote to Alex Torres:
VB> Пpивет, Alex!
VB> *** 27 Jul 04 22:23, Alex Torres wrote to Vladislav Baliasov:
VB>>> Дальше закрываю прерывания на время антидребезга.
AT>> Постой, что за валкодер?
VB> А, я забыл сказать, что это механический контактный (PEC16 от Bourns).
Ох помню я помучался с подобным механическим валкодером. Его чем медленнее вращаешь - дем сильнее дребезг. Причем длительность дребезга прои медленном вращении сопостовима с длительностью полезного сигнала при быстром. По-зорошему надо было делать частотно зависимый подавитель, но нехотелось возиться. Я сделал попроще, работало удовлитворительно. Hо при _очень_ быстром вращении иногда сбоило. Я ловил прерывание по нарастающему фронту от одного из сигналов, а потом прерывание запрещал и пользовался таймером чтобы несколько раз считать состояние и принять решение куда оно крутится когда дребезг прекратится. Вот кусок кода
//AB terminal state #define ST1 RW_A #define ST2 RW_B #define ST3 (ST1 | ST2) #define ST4 0
#define DELAY1 (3277 /12) //0.1 msec #define DELAY2 (3277 /15) //0.1 msec #define DELAY3 (3277 * 2) // 2 msec #define MAX_RETR 5
int delay1=DELAY1; int delay2=DELAY2; int delay3=DELAY3; int max_retr=MAX_RETR;
int gcount; int gstate;
int prev_dir=0;
//Timer interrupt handler
static void rwheel_timer_handler (int irq, void *dev_id, struct pt_regs
*regs) { if (gcount==0){ gstate=get_wstate(); // Get rotary weel state (ST1..ST4) set_wtimer_delay(delay2); //Set delay for next timer irq ++gcount; return; } if ((gcount<max_retr) & (gcount>0)){ if(gstate == get_wstate()) ++gcount; else gcount=0; set_wtimer_delay(delay2); return; } if (gcount==max_retr){ if((gstate==ST4) || (gstate==ST3)) do_ccw(); //direction 1 else if((gstate==ST1) || (gstate==ST2)) do_cw(); //direction 2 else printk("RW bogus state.\n"); gcount=0x00AAFF0B; //Set exit flag set_wtimer_delay(delay3); return; } if (gcount==0x00AAFF0B){ disable_wtimer_int(); enable_rw_irq(); //Enable rising edge interrupt from Rotary Wheel } enable_cpld_rw_irq(); }
// Rotary wheel interrupt handler, triggered by rising edge //We don't do much in this handler, just enable timer and disable RW interrupt // real work for reading RW state and rotation decoding is placed to the timer handler
static void gpio_rwheel_handler1 (int irq, void *data) {
disable_rw_irq(CPLD_IRQ_RW_RIS_EN); gcount=0; set_wtimer_delay(delay1); enable_wtimer_int (); }
/Sam [samoutin(ат)hotbox.ru]