RicLab 0 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба Добрый день. Алгоритм обработки энкодера взял здесь. Переделал для CVAVR, но заставить работать не получается. К порту B подключены светодиоды, сигналы энкодера A и B подключены к порту D 2 и 3 соответственно. Chip type : ATtiny2313 Clock frequency : 8,000000 MHz Memory model : Tiny External SRAM size : 0 Data Stack size : 32 *****************************************************/ #include <tiny2313.h> int New; // новое значение состояния энкодера unsigned char EncData; // счётный регистр энкодера int EncState; // предыдущее состояние энкодера void EncoderScan(void) { New=PIND&0xC; // копируем в New состояние входов 2,3 switch (EncState) // сравниваем текущее значение New со старым смотря в какую сторону вращение изменениям EncData ++ или -- { case 2: { if (New==3) EncData++; if (New==0) EncData--; break; } case 0: { if (New==2) EncData++; if (New==1) EncData--; break; } case 1: { if (New==0) EncData++; if (New==3) EncData--; break; } case 3: { if (New==1) EncData++; if (New==2) EncData--; break; } } EncState=New; // записываем новое значение предыдущего состояния } // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { EncoderScan(); // запускаем функцию сканирования энкодера } // Declare your global variables here void main(void) { // Declare your local variables here // Crystal Oscillator division factor: 1 #pragma optsize- CLKPR=0x80; CLKPR=0x00; #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif // Port B initialization // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out // State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 PORTB=0x00; DDRB=0xFF; // Port D initialization // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State6=P State5=P State4=P State3=P State2=P State1=P State0=P PORTD=0x7F; DDRD=0x00; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 1000,000 kHz // Mode: Normal top=FFh // OC0A output: Disconnected // OC0B output: Disconnected TCCR0A=0x00; TCCR0B=0x02; TCNT0=0x00; OCR0A=0x00; OCR0B=0x00; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x02; // Global enable interrupts #asm("sei") while (1) { PORTB=EncData; }; } Где моё упущение? :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 7 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба Где моё упущение? :laughing: Вместо New=PIND&0xC; следует записать New=(PIND >> 2)&0x3; P.S. В начале программы хорошо бы переменной EncState присвоить значение. Как-то так: EncState=(PIND >> 2)&0x3; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
neiver 0 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба Упущение в "магических" константах 0, 1, 2, 3 в операторе switch. Биты вы скопировали, но не туда. switch их ожидает увидить в нулевом и первом битах. Если сделать так: New=PIND&0xC >> 2; то должно работать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=SSN= 0 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба EDN Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RicLab 0 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба заработало но на один щелчок энкодера на выходе 4 импульса. Так и должно быть по алгоритму. Как можно сделать 1 щелчок 1 импульс? Автор статьи писал об этом, А по моей логике, на один импульс приходится четыре смены состояния, т.е. полный период 3201_3201_3201 и один щелчок дает 4ре деления, что некрасиво. Поэтому я считаю до 1024, а потом делю сдвигом на четыре. Получаем на выходе один щелочок - один тик. но я не совсем понял как это реализовать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
neiver 0 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба Как можно сделать 1 щелчок 1 импульс? Выкинуть из switch три любые ветки case. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RicLab 0 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба тогда пострадает надёжность распознования вращения энкодера. Проверил в железе, бывают ложные импульсы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 7 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба Как можно сделать 1 щелчок 1 импульс?Ну, так же написано: "делю сдвигом на четыре"... Т.е. завести новую переменную, которая будет изменяться на единицу за один щелчок. Вычислять её - как-то так: NewEncData= EncData >> 2; что тоже самое NewEncData= EncData / 4; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RicLab 0 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба сильно не ругайте, я начинающий :smile3046: За советы большое спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dalkroz 0 17 октября, 2011 Опубликовано 17 октября, 2011 · Жалоба а у меня похожый проект.. так же прицеплен енкодер на входы INT0-INT1. у меня енкодер с розришением 1000имп\оборот и гдето в програме ошыбка у меня не работает на железе вот такой код... вроде всё просто а ошибку не могу найти(... у меня считает только в одну сторону (только в+)считает хорошо импульсы не пропускает, а если крутить вал енкодера в противоположную сторону то тоже считает в +..... помогите пожалуста) #include <mega8535.h> // Alphanumeric LCD Module functions #asm .equ __lcd_port=0x1B ;PORTA #endasm #include <lcd.h> #include <stdio.h> #include <math.h> #include <delay.h> #define KEYIN PINC char string_LCD[16]; int H,h,i; //i - счётчик импульсов... остальное для обработки количества импульсов // External Interrupt 0 service routine interrupt [EXT_INT0] void ext_int0_isr(void) { if (PIND.3==0) { //////////////////////// if (h==5) {h=0;H++;}; i++; h++; if (h==5) { H++; h=0;}; //////////////////////// } else { //////////////////////// if (h==0) {h=5;H--;}; i--; h--; if (h==0) {H--; h=5;}; //////////////////////// }; #asm("cli") } // External Interrupt 1 service routine interrupt [EXT_INT1] void ext_int1_isr(void) { #asm("cli") } // Timer 1 output compare A interrupt service routine interrupt [TIM1_COMPA] void timer1_compa_isr(void) { } // Declare your global variables here ///////////////////////////////////////////////////////////////////// void print(void) { ///////////////////////////////////////////////////////////// lcd_gotoxy(0,0); sprintf(string_LCD,"i=%iimp ",i); lcd_puts(string_LCD); lcd_gotoxy(9,0); sprintf(string_LCD,"h=%i ",h); lcd_puts(string_LCD); lcd_gotoxy(9,1); sprintf(string_LCD,"H=%imm ",H); lcd_puts(string_LCD); ///////////////////////////////////////////////////////////// } void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port A initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTA=0x00; DDRA=0x00; // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTB=0x00; DDRB=0x00; // Port C initialization // Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=Out Func0=Out // State7=T State6=T State5=T State4=T State3=0 State2=0 State1=0 State0=0 DDRC=0x0F; PORTC=0xFF; // Port D initialization // Func7=Out Func6=Out Func5=Out Func4=Out Func3=In Func2=In Func1=In Func0=In // State7=0 State6=0 State5=0 State4=0 State3=T State2=T State1=T State0=T DDRD=0xF0; PORTD=0x00; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 125,000 kHz // Mode: Normal top=FFh // OC0 output: Disconnected TCCR0=0x02; TCNT0=0x00; OCR0=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 0,977 kHz // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: On // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x05; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x03; OCR1AL=0xD1; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Normal top=FFh // OC2 output: Disconnected ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00; // External Interrupt(s) initialization // INT0: On // INT0 Mode: Rising Edge // INT1: Off // INT2: Off GICR|=0x40; MCUCR=0x03; MCUCSR=0x00; GIFR=0x40; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00; // LCD module initialization lcd_init(16); // Global enable interrupts #asm("cli"); while (1) { print(); /////////////////////////// #asm("sei; nop; cli; nop") /////////////////////////// }; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 7 18 октября, 2011 Опубликовано 18 октября, 2011 · Жалоба если крутить вал енкодера в противоположную сторону то тоже считает в +..... Что-то Вы "накрутили" в прерывании... Но, похоже, что проблема - чисто "железная": вероятно, что на ноге PD3 висит "глухой" ноль. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dalkroz 0 20 октября, 2011 Опубликовано 20 октября, 2011 · Жалоба большое спасибо за совет Палыч ) пересмотрел все соединения и обнаружыл ошибки.... к стати код абсолютно робочий))) пользуйтесь))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться