logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[atmega16][C] impulsator (przepisanie programu z Bascoma)

professor1234 11 Maj 2009 18:32 1652 6
REKLAMA
  • #1 6517369
    professor1234
    Poziom 12  
    Koledzy,

    Jestem szczęśliwym posiadaczem impulsatora i walczę żeby go obsłużyć w C... Paranoja tkwi w tym, że w bascomie impulsator działa, a praktycznie ten sam program przepisany do C nie działa...
    Impulsator mam podłączony środkiem do GND jeden PIN na INT0(PD2) trzeci na(PD7). Na porcie C linijka diod. Poniżej listing programu:
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #define F_CPU 8000000
    
    void init(){
    
    DDRC = 0xFF;
    PORTC = 0xFF;
    
    DDRD &=~(_BV(2) | _BV(7));
    PORTD |=(_BV(2) | _BV(7));
    
    MCUCR |=_BV(ISC00);
    MCUCR &=~_BV(ISC01);
    GICR |= (_BV(INT0));
    
    _delay_ms(100);
    PORTC ^=0xFF;
    _delay_ms(100);
    PORTC ^=0xFF;
    };
    
    ISR(INT0_vect) {
    cli();
    if ((PIND&_BV(2)) ^ (PIND&_BV(7))==0) PORTC++; else PORTC--;
    sei();
    }; 
    
    int main(){
    init();
    sei();
    while(1);
    };
    
    


    Kierunek kręcenia impulsatorem rozpoznaję tutaj za pomocą XOR-a.
    Kręcenie impulsatorem w jedną stronę powoduje dekrementację natomiast kręcenie w drugą stronę powoduje naprzemienną dekrementację i inkrementację, dioda na LSB (PC0) naprzemian zapala się i gaśnie.

    Pomóżcie, bo nie mam pomysłu co jest nie tak :(
  • REKLAMA
  • #2 6517510
    BoskiDialer
    Poziom 34  
    Kompletnie zły zapis z tym xor'em. Zauważ, że (PIND&_BV(2)) przyjmuje wartości 0x00 oraz 0x04, podczas gdy (PIND&_BV(7)) 0x00 oraz 0x80. W jednym kierunku (przy zmianie stanu na PD2) stany są przeciwne, więc cały warunek zawsze jest fałszywy i występuje zmniejszanie. W drugą stronę albo oba są równe 0 albo jedno jest równe 0x04 a drugie 0x80. Sam xor tutaj nie wystarczy - warto by dać jakieś przesuwanie bitów.

    Dodano po 4 [minuty]:

    ps. W przerwaniu NIE używaj cli oraz sei.
  • REKLAMA
  • #3 6517619
    professor1234
    Poziom 12  
    Faktycznie,

    Masz całkowitą rację. Przy takim zapisie operujemy na byte'ach a nie bitach.
    Najpierw należy przesunąć "(PIND&_BV(7))" o 5 bitów w lewo, a następnie zastosować XOR z "(PIND&_BV(2))". Zgadza się ??

    Właśnie walczę żeby to zapisać :)

    I wypełzło coś takiego :
    
    ISR(INT0_vect) {
    buf = PIND&_BV(7);
    buf >>=5;
    if ((buf ^ PIND&_BV(2))==0) PORTC++; else PORTC--;
    }; 
    

    buf - zadeklarowany przed int main() jako char.

    Chyba, że da się to zrobić krócej , to jeżeli można pokazać... :)
  • #4 6517649
    BoskiDialer
    Poziom 34  
    (PIND&_BV(7)) jak już, to trzeba będzie przesunąć o 5 bitów w prawo (">>").
  • REKLAMA
  • Pomocny post
    #5 6519661
    BoskiDialer
    Poziom 34  
    Ten kod można zapisać na co najmniej n sposobów, podam tylko najlepszy (wg mnie):
    ISR(INT0_vect)
    { 
      unsigned char pintemp = PIND & (_BV(7)|_BV(2)); 
      if (pintemp == 0 || pintemp == (_BV(7)|_BV(2)))
        PORTC++;
      else
        PORTC--; 
    }
  • REKLAMA
  • #6 6520575
    Pawel1812
    Poziom 26  
    A ja impulsator obsługuję (z powodzeniem) tak:
    W tym wypadku enkoder steruje przewijanym menu, user ma nacisnąć przycisk enkodera, aby potwierdzić wybór jednej pozycji i ją edytowac. Przesunięcie kursora poza ekran przewija menu.
    Skopiowałem dokładnie mój aktualnie pisany program, ale idea jest chyba widoczna jak to ładnie można rozwiązać.
    
    while (!(bit_is_clear(PINE,0)))   //dopóki klawisz potwierdzenia nie jest wciśnięty
    	 {
    	
    	    if (bit_is_clear(PINB,ENKODER_A)) //jeśli enkoder jest obracany
    	     { 
    		 
    		  lcd_zgas_kursor(odl,0);
              lcd_zgas_kursor(odl,1);
              lcd_zgas_kursor(odl,2);
              lcd_zgas_kursor(odl,3);
              lcd_zgas_kursor(odl,4);
              lcd_zgas_kursor(odl,5);
              lcd_zgas_kursor(odl,6);
    
             //w tym momencie wiemy,  ze kursor będzie przesuwany więc gasimy na starym miejscu
    		 
              if(!(bit_is_clear(PINB,ENKODER_B)))   //jeżeli drugi bit enkodera ustawiony
               {
    		   
    		      
    	   	         if ((wybor<15)&&(yw>4))
    			      {  
    				     gr_g++;
    			         gr_d++;
    				     wybor++;
    					 yw=5;
    				     ekran_parametry_zaawansowane(gr_d,gr_g); //wyświetl nowy ekran
    				     lcd_zapal_kursor(odl,yw);    //kursor na nowych współrzędnych
    					 _delay_ms(200);
    			      }
    			     if ((wybor<15) && (yw<5))
    			      {
    			        yw++;
    				    wybor++;
    				  }
    				  lcd_zapal_kursor(odl,yw);    //kursor na nowych współrzędnych
    				   _delay_ms(200);
               }
    		  
    		   else
    		    {    
    		  
    	   	         if ((wybor>1)&&(yw<2))
    			     {  
    				  --gr_g;
    			      --gr_d;
    				  --wybor;
    				  ekran_parametry_zaawansowane(gr_d,gr_g); //wyświetl nowy ekran
    				 lcd_zapal_kursor(odl,yw);    //kursor na nowych współrzędnych
    				  _delay_ms(200);
    			     }
    			     if ((wybor>1) && (yw>1))
    			      {
    				  --yw;
    				  --wybor;
    				  }
    				lcd_zapal_kursor(odl,yw);    //kursor na nowych współrzędnych
    				 _delay_ms(200);
                }
    		 }   
    
    
    
  • #7 6521166
    professor1234
    Poziom 12  
    Dzięki za pomoc,

    Temat uważam za zamknięty,

    Jeszcze raz thx,
REKLAMA