Aktykuły które nie zmieściły się w żadnej kategorii

0102 /03
04Impulsator na jednym przerwaniu.06
070809

Rotor encoder impulsator

Schemat encodera

Wyjście B enkodera może by na innym dowolnym pinie, wymagane jest jedynie zmian pinu w algorytmie.


  1. /*
  2. wyjście impulsatora A do INT0 PORTD pin PD2
  3. wyjście impulsatora B do PORTD pin PD1
  4. Kompilowane i testowane na Atmega328P.
  5. Avr Studio 4.18
  6. Programator AVR Prog MKII
  7. */
  8. uint16_t licznik = 0x1000;  
  9. ISR (INT0_vect) //obsługa przerwania INT0 
  10.         // Linia 1   
  11.      if ((((PIND & 4)==4) & ((EICRA & 1) == 1 )) & ((PIND & 2)==0)) 
  12.                              {  EICRA &= ~(1 << ISC00); ++licznik; return;}
  13.         // Linia 2
  14.      if ((((PIND & 4)==0) & ((EICRA & 1) == 0 )) & ((PIND & 2)==2)) 
  15.                                {  EICRA |=  (1 << ISC00); ++licznik; return;}
  16.         // Linia 3        
  17.      if ((((PIND & 4)==4) & ((EICRA & 1) == 1 )) & ((PIND & 2)==2)) 
  18.                                {  EICRA &= ~(1 << ISC00); --licznik; return;}
  19.          // Linia 4 
  20.      if ((((PIND & 4)==0) & ((EICRA & 1) == 0 )) & ((PIND & 2)==0)) 
  21.                                  {  EICRA |=  (1 << ISC00); --licznik; return;}
  22. int main(void)
  23. {
  24.     DDRD = 0b11110000;     
  25.     DDRD &= ~(1 << 0); 
  26.     EICRA |=  (1 << ISC00);  
  27.     EICRA |=  (1 << ISC01);  
  28.     EIMSK |= (1 << INT0);    
  29.     sei();
  30.     while(1) {}
  31. }

Algorytm specjalnie tak napisałem bym mógł łatwo i obrazowo wytłumaczyć jak to działa. W necie można znaleść sporo przykładów na obsługę impulsatora, większość tych przykładów które znalazłem korzysta z dwóch przerwań INT0 i INT1.
Postanowiłem zaoszczędzić jedno przerwanie i tak powstał ten algorytm.


Przebiegi encodera
  1.    if ((((PIND & 4)==4) & ((EICRA & 1) == 1 )) & ((PIND & 2)==0)) 
  2.               {  EICRA &= ~(1 << ISC00); ++licznik; return;}

Po wejściu w przerwanie sprawdzamy piny PD2=1 ( wejście INT0 ) i PD1=0 oraz czy przerwanie EICRA=1 jest ustawione na 1 (reaguj na zbocze narastające) jeżeli tak to, zmień reakcję przerwania na zbocze opadające oraz zwiększamy zmienną licznik o jeden.


Przebiegi encodera
  1.      if ((((PIND & 4)==0) & ((EICRA & 1) == 0 )) & ((PIND & 2)==2)) 
  2.                 {  EICRA |=  (1 << ISC00); ++licznik; return;}

Po wejściu w przerwanie sprawdzamy piny PD2=0 ( wejście INT0 ) i PD1=1 oraz czy przerwanie EICRA=0 jest ustawione na 0 ( reaguj na zbocze opadające ) jeżeli tak to, zmień reakcję przerwania na zbocze narastające oraz zwiększamy zmienną licznik o jeden.


Przebiegi encodera
  1.     if ((((PIND & 4)==4) & ((EICRA & 1) == 1 )) & ((PIND & 2)==2)) 
  2.                    {  EICRA &= ~(1 << ISC00); --licznik; return;}

Po wejściu w przerwanie sprawdzamy piny PD2=1 ( wejście INT0 ) i PD1=1 oraz czy przerwanie EICRA=1 jest ustawione na 1 ( reaguj na zbocze narastające ) jeżeli tak to, zmień reakcję przerwania na zbocze opadające oraz zmniejszamy zmienną licznik o jeden.


Przebiegi encodera
  1.     if ((((PIND & 4)==0) & ((EICRA & 1) == 0 )) & ((PIND & 2)==0)) 
  2.                  {  EICRA |=  (1 << ISC00); --licznik; return;}

Po wejściu w przerwanie sprawdzamy piny PD2=0 ( wejście INT0 ) i PD1=0 oraz czy przerwanie EICRA=0 jest ustawione na 0 ( reaguj na zbocze opadające ) jeżeli tak to, zmień reakcję przerwania na zbocze narastające oraz zmniejszamy zmienną licznik o jeden.

Końcowa wersja czterech najważniejszych lini.
  1. if (   (PIND & _BV(PD2))  &&   (EICRA & _BV(ISC00))  && (!(PIND & _BV(PD1))) )  
  2.                     { EICRA &= ~_BV(ISC00); ++licznik; return;}
  3. if ( (!(PIND & _BV(PD2))) && (!(EICRA & _BV(ISC00))) &&   (PIND & _BV(PD1))  )  
  4.                     { EICRA |=  _BV(ISC00); ++licznik; return;}
  5. if (   (PIND & _BV(PD2))  &&   (EICRA & _BV(ISC00))  &&   (PIND & _BV(PD1))  )  
  6.                     { EICRA &= ~_BV(ISC00); --licznik; return;}
  7. if ( (!(PIND & _BV(PD2))) && (!(EICRA & _BV(ISC00))) && (!(PIND & _BV(PD1))) )  
  8.                     { EICRA |=  _BV(ISC00); --licznik; return;}

Przy tej formie zapisu program jest mniejszy o 156 bajtów.
Tak wykazuje w moim przypadku AvrStudio.


Artykuł jest opublikowany na elektrodzie gdzie można poczytać komentarze.



Dasej (C) 2019 : 5083