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

[Atmega8][C] Jak pobrać informacje w czasie wykonuwania funk

nelik1987 29 Paź 2008 18:02 2316 21
  • #1 5680430
    nelik1987
    Poziom 31  
    Jak pobrać dane podczas wykonywania funkcji

    może i dla was będzie to banalne pytanie ale dla mnie stanowi dość duży problem, mianowicie napisałem sobie program który ustawia na wyjściach uC stany wysokie i niskie, w kolejności od prawej do lewej tak ma się to na przykład w rejestrze pierścieniowym, z konkretnym opóźnieniem

    przedstawię to na tablicy:

    
    Q0    Q1    Q2    Q3
    =================
     1    0     0     0
     0    1     0     0
     0    0     1     0
     0    0     0     1
    
    


    czas po jakim nastąpi zmiana został zrealizowane w taki sposób:



    gdzie "i" okresla po ilu sekndach ma nastapić zmiana

    no teraz moje pytanie jak pobrać informacje od użytkownika (chodzi o to czy przycisk jest wciśnięty czy nie w czasie działa tej funkcji) bo jezeli czasy zwłoki są duże to trzeba długo czekać i na dodatek dokładnie trafić na początek programu gdzie czytana jest wartość na pinie.
  • #2 5680487
    KowalD
    Poziom 17  
    np. przerwanie zawnetrzne :)... lub od timera :)... generalnie poczytaj o przerwaniach :)...
  • #3 5680538
    nelik1987
    Poziom 31  
    no i o przerwania pytałem już w innym poście ale sensownej odpowiedzi nie dostałem bo zaczęli debatować o tym ile zajmuje funkcja _delay_ms(i) i niestety prawie nic mi nie pomogli, czy gdzieś mogę poczytać na temat przerwań, ale w takiej przystępnej formie no i po polsku najlepiej
  • #5 5680799
    nelik1987
    Poziom 31  
    no działa znakomicie ale przeszukałem bardzoooo wiele stron i nie znalazłem podstawowych informacji na ten tema, jak już znalazłem problemy zwiazane z przerwaniami ale tam się nie tłumaczy jak działają przerwania tylko od razu rzucają fachowymi terminami których nie rozumiem.

    Szukam prostego opisu dla początkującego programisty
  • #7 5681350
    szeryf.rm
    Poziom 22  
    Nie wiem czy dobrze zrozumiałem, ale zobacz przerwania. Kwestia ile czasu będzie trwać delay_ms to jak zwykle geniusze wymyślili, bo jak się domyślam wielkiego problemu z tym czasem nie ma a jeśli będzie to polecam zastosować timer to odmierzania czasu i również posłużyć się przerwaniem dla niego. Uzyskasz wówczas bardzo dobry kod, ale jest nieco bardziej skomplikowany.

    A teraz ad. twojego rozwiązania z delay. Ustaw sobie przerwanie tak aby wyzwalało się zboczem narastającym lub opadającym (jak wolisz). W przerwaniu obsłużysz przycisk i powrócisz do programu. Wadą rozwiązania będzie zachwianie działania ms ale w niewielkim stopniu, jeśli w przerwaniu nie będzie wielu operacji. Jeśli zaś wciśnięcie przycisku może mocno zachwiać opóźnienie to, to opóźnienie zrealizuj na timerze, a przycisk zrób w programie głównym lub też na przerwaniu.

    .....
    Słusznie, przerwanie a nie przerywanie. Literówki z pośpiechu.
  • #9 5682006
    Teodor Otulak
    Poziom 13  
    Najprościej i najskuteczniej możesz to zrobić tak:

    - czytanie stanu klawiatury przenieś do pętli w funkcji delay_klawiatury(), którą sobie zrób z oryginalnego delay(), oczywiście trochę zmniejsz ilość przejść pętli aby zachować zgodność opóźnień.

    - po wejściu w obsługę klawisza korzystaj z normalnej funkcji delay()

    - nie baw się w obsługę klawiszy w przerwaniach, bo w rzypdku ATM8 zabraknie pamięci na stos

    Łopatologicznie o przerwaniach możesz poczytać w tutorialu, którego paęrę lat temu zamieściłem w sieci (przykłady były na Mega8).

    Pozdrawiam :-)
  • #10 5682107
    nelik1987
    Poziom 31  
    Dobra teraz powiem co dokładnie chcę zrobić,

    chce napisac program sterujący pracą silnika krokowego
    założenia:
    - przycisk START/STOP do zatrzymania i wznawiania pracy silnika
    -przyciski LEWO/PRAWO do zmiany kierunku obrotów
    -przyciski SZYBCIEJ/WOLNIEJ do zmiany prędkości obrotów

    planuję wykorzystać ten projekt na koniec semestru jako program na zaliczenie, dlatego zabrałem się już teraz bo moja wiedza jest jeszcze bardzo mała.

    na razie napisałem program który steruje prędkością, jest bardzo prymitywny ale proszę się nie śmiać tylko mi pomóc. Tak jak się spodziewałem program ma jedną poważną wadę, mianowicie podczas wolnych obrotów zmiana prędkości na większa odbywa się wolno bo są długie "zatrzymania" programu, dlatego też się pytam jak to rozwiązać


    #include <avr/io.h>                        // dostęp do rejestrów
    #include <util/delay.h>
    
    #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
    #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
    
    
    int main( void )                        // program główny
    {
    
    unsigned int i = 200, a=12,max=1000,min=4;                  // czas w milisekundach
    
      sbi(DDRB,0);                      // użyj linii PA0 jako wyjście
      sbi(DDRB,1);                    // użyj linii PA1 jako wyjście
      sbi(DDRB,2);                      // użyj linii PA2 jako wyjście
      sbi(DDRB,3);                    // użyj linii PA3 jako wyjście   
      DDRD  &= ~_BV(0);
      PORTD |=  _BV(0);
      DDRD  &= ~_BV(1);
      PORTD |=  _BV(1);
                     
    
    
      while(1)                               // pętla nieskończona
      {
    
         for(a=0;a<12;a++)
    	   {
      
    		sbi(PORTB,0);                        // zapal diodę LED podłączoną do linii PB0
       
    		_delay_ms(i);                      		// czekaj i milisekund
    		
    if(bit_is_clear(PIND, PD1)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD1)) 
    	  {
    	     i=i+10;
    	  }
       }   
    } 
    
    
    if(bit_is_clear(PIND, PD0)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD0)) 
    	  {
    	     i=i-10;
    	  }
       }   
    } 
       
    		cbi(PORTB,0);                        // zgaś  diodę LED podłączoną do linii PB0
    //===================================================================================   
    		sbi(PORTB,1);                        // zapal diodę LED podłączoną do linii PB1
    
    		_delay_ms(i);                      		// czekaj i milisekund
    		
    if(bit_is_clear(PIND, PD1)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD1)) 
    	  {
    	     i=i+10;
    	  }
       }   
    } 
    
    
    if(bit_is_clear(PIND, PD0)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD0)) 
    	  {
    	     i=i-10;
    	  }
       }   
    } 
    
    		cbi(PORTB,1);                        // zgaś  diodę LED podłączoną do linii PB1
    //===================================================================================  
    		sbi(PORTB,2);                        // zapal diodę LED podłączoną do linii PB2
    
    		_delay_ms(i);                      		// czekaj i milisekund
    		
    if(bit_is_clear(PIND, PD1)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD1)) 
    	  {
    	     i=i+10;
    	  }
       }   
    } 
    
    
    if(bit_is_clear(PIND, PD0)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD0)) 
    	  {
    	     i=i-10;
    	  }
       }   
    } 
    
    		cbi(PORTB,2);                        // zgaś  diodę LED podłączoną do linii PB2
    //===================================================================================  
    		sbi(PORTB,3);                        // zapal diodę LED podłączoną do linii PB3
    
    		_delay_ms(i);                      		// czekaj i milisekund
    		
    if(bit_is_clear(PIND, PD1)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD1)) 
    	  {
    	     i=i+10;
    	  }
       }   
    } 
    
    
    if(bit_is_clear(PIND, PD0)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD0)) 
    	  {
    	     i=i-10;
    	  }
       }   
    } 
    
    		cbi(PORTB,3);                        // zgaś  diodę LED podłączoną do linii PB3
    //===================================================================================  
    
    if(bit_is_clear(PIND, PD1)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD1)) 
    	  {
    	     i=i+10;
    	  }
       }   
    } 
    
    
    if(bit_is_clear(PIND, PD0)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD0)) 
    	  {
    	     i=i-10;
    	  }
       }   
    } 
    
    
    
           }
      }
    } 



    potem wymyśliłem że zrobię tak że program sprawdzi czy bit jest ustawiony na 0 poczekaj chwilę na puszczenie przycisku (30ms) a potem sprawdzi czy byt jest ustawiony na 1 (czyli czy przycisk zwolniono)

    wszystko fajnie tylko że jak się trzyma przycisk ciągle przyciśnięty do obroty spadają przez to że ciągle za każdym razem czeka te 30 ms :(

    #include <avr/io.h>                        // dostęp do rejestrów
    #include <util/delay.h>
    
    #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
    #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
    
    
    int main( void )                        // program główny
    {
    
    unsigned int i = 200, a=12,max=1000,min=4;                  // czas w milisekundach
    
      sbi(DDRB,0);                      // użyj linii PA0 jako wyjście
      sbi(DDRB,1);                    // użyj linii PA1 jako wyjście
      sbi(DDRB,2);                      // użyj linii PA2 jako wyjście
      sbi(DDRB,3);                    // użyj linii PA3 jako wyjście   
      DDRD  &= ~_BV(0);
      PORTD |=  _BV(0);
      DDRD  &= ~_BV(1);
      PORTD |=  _BV(1);
                     
    
    
      while(1)                               // pętla nieskończona
      {
    
         for(a=0;a<12;a++)
    	   {
      
    		sbi(PORTB,0);                        // zapal diodę LED podłączoną do linii PB0
       
    		_delay_ms(i);                      		// czekaj i milisekund
    		
    if(bit_is_clear(PIND, PD1)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD1)) 
    	  {
    	     i=i+10;
    	  }
       }   
    } 
    
    
    if(bit_is_clear(PIND, PD0)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD0)) 
    	  {
    	     i=i-10;
    	  }
       }   
    } 
       
    		cbi(PORTB,0);                        // zgaś  diodę LED podłączoną do linii PB0
    //===================================================================================   
    		sbi(PORTB,1);                        // zapal diodę LED podłączoną do linii PB1
    
    		_delay_ms(i);                      		// czekaj i milisekund
    		
    if(bit_is_clear(PIND, PD1)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD1)) 
    	  {
    	     i=i+10;
    	  }
       }   
    } 
    
    
    if(bit_is_clear(PIND, PD0)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD0)) 
    	  {
    	     i=i-10;
    	  }
       }   
    } 
    
    		cbi(PORTB,1);                        // zgaś  diodę LED podłączoną do linii PB1
    //===================================================================================  
    		sbi(PORTB,2);                        // zapal diodę LED podłączoną do linii PB2
    
    		_delay_ms(i);                      		// czekaj i milisekund
    		
    if(bit_is_clear(PIND, PD1)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD1)) 
    	  {
    	     i=i+10;
    	  }
       }   
    } 
    
    
    if(bit_is_clear(PIND, PD0)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD0)) 
    	  {
    	     i=i-10;
    	  }
       }   
    } 
    
    		cbi(PORTB,2);                        // zgaś  diodę LED podłączoną do linii PB2
    //===================================================================================  
    		sbi(PORTB,3);                        // zapal diodę LED podłączoną do linii PB3
    
    		_delay_ms(i);                      		// czekaj i milisekund
    		
    if(bit_is_clear(PIND, PD1)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD1)) 
    	  {
    	     i=i+10;
    	  }
       }   
    } 
    
    
    if(bit_is_clear(PIND, PD0)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD0)) 
    	  {
    	     i=i-10;
    	  }
       }   
    } 
    
    		cbi(PORTB,3);                        // zgaś  diodę LED podłączoną do linii PB3
    //===================================================================================  
    
    if(bit_is_clear(PIND, PD1)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD1)) 
    	  {
    	     i=i+10;
    	  }
       }   
    } 
    
    
    if(bit_is_clear(PIND, PD0)) 
    {
      if(i<max)
       {
    	  _delay_ms(30);
          if(bit_is_set(PIND, PD0)) 
    	  {
    	     i=i-10;
    	  }
       }   
    } 
    
    
    
           }
      }
    } 
  • Pomocny post
    #11 5682283
    Dr.Vee
    VIP Zasłużony dla elektroda
    Już Ci ktoś tłumaczył w innym temacie, że _delay_ms(i) gdzie i się zmienia nie zadziała tak jak trzeba. Jak widać nauka poszła w las...

    W Twoim przypadku dzieją się tylko 2 rzeczy równolegle:
    1) sterujesz silnikiem (z odpowiednim opóźnieniem między impulsami, od 4 do 1000 ms)
    2) sprawdzasz stan przycisków (co 30 ms).

    Dlatego ustawiasz sobie timer na przerwanie powiedzmy co 1ms i jazda.

    Do rzeczy:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/sleep.h>
    
    #define INTERWAL_PRZYCISKOW 30
    #define INTERWAL_SILNIKA_MIN 4
    #define INTERWAL_SILNIKA     200
    #define INTERWAL_SILNIKA_MAX 1000
    
    volatile unsigned int g_aktualny_czas;  /* w ms */
    unsigned int g_nastepny_test_przyciskow;
    unsigned int g_nastepne_sterowanie_silnika;
    unsigned int g_okres_sterowania_silnika = INTERWAL_SILNIKA;
    
    ISR(TIMER1_COMPA_vect) {
        g_aktualny_czas += 1;
    }
    
    uint8_t czy_testowac_przyciski(void) {
        if (g_aktualny_czas == g_nastepny_test_przyciskow) {
            g_nastepny_test_przyciskow = g_aktualny_czas + INTERWAL_PRZYCISKOW;
            return 1;
        }
        return 0;
    }
    
    uint8_t czy_sterowac_silnik(void) {
        if (g_aktualny_czas == g_nastepne_sterowanie_silnika) {
            g_nastepne_sterowanie_silnika = g_aktualny_czas + g_okres_sterowania_silnika;
            return 1;
        }
        return 0;
    }
    
    void inicjalizacja(void) {
    
        /* ustaw porty */
        /* ustaw timer 1 w trybie CTC */
        /* ustaw przerwanie timera 1 co 1 ms */
        /* uruchom timer 1 */
    
        /* ... */
    
        /* zaczynamy zabawę za 1 ms */
        g_nastepny_test_przyciskow = g_aktualny_czas + 1;
        g_nastepne_sterowanie_silnika = g_aktualny_czas + 1;
    
        /* ustaw tryb sleep */
        set_sleep_mode(SLEEP_MODE_IDLE);
    
        /* wlacz przerwania */
        sei(); 
    }
    
    int main(void) {
    
        inicjalizacja();
    
        for (;;) {
            /* idz spac */
            sleep_enable();
            sleep_cpu();
    
            /* tutaj przerwanie obudzilo procesor */
            sleep_disable();
    
            if (czy_testowac_przyciski()) {
                /* testuj przyciski */
            }
    
            if (czy_sterowac_silinik()) {
                /* steruj silnikiem */
            }
        }
    
        /* tutaj nigdy nie dochodzimy */
        return 0;
    }
    
  • #13 5697143
    nelik1987
    Poziom 31  
    bardzo sie ciesze że napisałem dla mnie taki kawał programu lecz ja nadal nie rozumiem o co tu biega, wierzcie mi że szukałem wszelkiej pomocy czytałem o tym w książce, szukałem w internecie ale ja nie rozumiem jak właściwie działa takie przerwanie. Program chciałem napisać na zajęcia ale widać że jestem chyba za słaby żeby go wykonać, jeżeli ktoś był by skory żeby mi to wytłumaczyć łopatologicznie będę naprawdę wdzięczny bo wtedy będę mógł dalej rozszerzać swoją wiedzą a tak stoję w miejscu
  • #14 5697396
    szeryf.rm
    Poziom 22  
    No to jazda, czyli łopatologicznie.
    Wyobraź sobie, że odrabiasz lekcję, ale dostajesz łopatą w łeb od ojca, który w ten sposób informuje cię, że woda się gotuje. Więc ty natychmiast przerywasz pracę i biegniesz ją wyłączyć, zrobić herbatę, a potem wracasz do lekcji.
    I teraz tak:
    1. Lekcje które odrabiasz to jakiś kod, który sobie leci
    2. Łopata w łeb to zgłoszenie przerwania
    3. Idziesz wyłączyć wodę i zrobić herbatę, to obsługa przerwania
    4. Powrót do lekcji, to powrót do wcześniej wykonywanej czynności, czyli powrót z przerwania.

    Dr.Vee dał ci kod, gdzie trochę musisz dopisać, ale ma to działać mniej więcej w ten sposób, że ustawiasz timer tak, aby generował przerwanie co 1ms (czyli tryb CTC itd. - patrz dokumentacja, tam jest wszystko, kody inne też znajdziesz itd.). Po ustawieniu wszystkiego usypasz procesor, a timer sobie sam odlicza. Po osiągnięciu odpowiedniej wartości którą ustawiłeś, timer wygeneruje przerwanie, którego obsługę masz:
     ISR(TIMER1_COMPA_vect) {...} 


    Co do reszty to najlepiej jak sobie pokombinujesz z jakimiś prostymi przerwaniami np. INT0, podpiętym przyciskiem i diodką itp. Tego już łopatologiczniej się chyba nie da wytłumaczyć.

    Dodano po 3 [minuty]:

    Polecam także:

    http://avr.elektroda.eu/?q=node/25
    http://atmega32.republika.pl/19.htm (co prawda inny procesor, ale warto poczytać)
  • #15 5697968
    nelik1987
    Poziom 31  
    znalazłem bardzo interesujący opis !!

    http://wkretak.pl/readarticle.php?article_id=3

    i już teraz mam pytanie czy dobrze rozumiem, przerwanie możne być wywołane wewnętrznie albo zewnętrznie i teraz zewnętrzne to poprzez te porty INT0 INT1 a wewnętrzne mogą być wywoływane na przykład cyklicznie poprzez użycie timera i w czasie kiedy się przepełni lub osiągnie jakąś wartość moze wywołać przerwanie?

    no i jeszcze jedna sprawa mnie nurtuje, czy przerwanie nie jest po prostu funkcją wywołaną z głównego programu? czy gdy działa przerwanie nawet długo to porgram główny cały czas się wykonuje
  • #16 5698558
    teedd
    Poziom 19  
    Witaj.
    W opisywanym przypadku przerwanie przerywa działanie głównego programu i powoduje skok do podprogramu obsługującego przerwanie. Dopóki podprogram obsługujący przerwanie nie skończy działania, to główny program nie będzie się wykonywał - no chyba, że zezwolimy na przerwanie podczas obsługi przerwania - ale to już inna para kaloszy.
    teedd
    P.S. Dlatego też celowym jest stosowanie timerów do odmierzania czasu, gdyż działają one "równolegle" do wykonywanego programu czy też przerwania.
  • #17 5699364
    szeryf.rm
    Poziom 22  
    A mi wydaje się, że kolega nelik1987 powinien w końcu dostać OPR za to, że nie przetestuje nic nawet w symulatorze tylko siedzi i pyta po raz setny na forum. nelik1987 bez urazy, ale AVRstudio ma bardzo prosty symualtor. Napisz byle co i zasymuluj, zobacz jak działa timer, to jak odlicza, sprawdź jak z poziomu symulatora zmieniać wartości portów itd itd. Potem ustaw przerwanie np. INT0 zasymuluj zmianę stanu na odpowiednim porcie, ustaw obsługę przerwania, zobacz jak się wykonuje itd itd itd. Ile godzin już szukasz? Ile czasu kombinujesz bez celu? Przecież mając symulator to dosłownie w 1-3 godziny (w zależności od doświadczenia) mógłbyś to wszystko sam prześledzić bez pytania się o nic. Tu nie chodzi o to, że pytać ci nie wolno, ale wypada zapoznać się z największym twoim przyjacielem (o ile nie jedynym), czyli debuggerem z AVRstudio. Gdyby nie on, to wiele rzeczy sam bym dzisiaj nie wiedział, ale on skutecznie pomaga zrozumieć co z czym, prześledzić itd. bez czekania na innych. Tylko przy pracy z debuggerem polecam kompilować bez optymalizacji (ustawienia projektu -> -O0 a nie -Os itp).

    Reasumując. Przysiądź trochę i nie rzucaj się na głęboką wodę, nie poznając podstawowego narzędzia z którego korzystasz, a które w zasadzie z perspektywy programowania powinno rozwiązać wieeeeeeeele problemów z jakimi teraz i jutro się spotkasz.
  • #18 5699382
    nelik1987
    Poziom 31  
    To nie jest tak ze tylko pytam i nic nie robię, nie korzystam z symulatora bo od razu ładuję projekt do procka i patrze jak działa w rzeczywistości. Żeby nie było że jestem gołosłowny to na razie wykombinowałem takie coś, może i jest to metoda zła, mało optymalna i nie do końca prawidłowa to jak narazie działa :D (aha i proszę sie nie śmiać z tak zwanego zaifowania, ale na razie nie wiedziałem jak to inaczej rozwiązać )



    
    #include <avr/io.h>
    #define LED0_ON  PORTB  |=  _BV(0); 
    #define LED0_OFF PORTB  &= ~_BV(0); 
    #define LED1_ON  PORTB  |=  _BV(1); 
    #define LED1_OFF PORTB  &= ~_BV(1);
    #define LED2_ON  PORTB  |=  _BV(2); 
    #define LED2_OFF PORTB  &= ~_BV(2);
    #define LED3_ON  PORTB  |=  _BV(3); 
    #define LED3_OFF PORTB  &= ~_BV(3);
    
    
    
    void inicjalizacja(void)
    {
      //---Ustawienia portów wyjścia---
      DDRB  |= _BV(0);    //Ustaw PB0 jako wyjscie
      DDRB  |= _BV(1);    //Ustaw PB1 jako wyjscie
      DDRB  |= _BV(2);    //Ustaw PB2 jako wyjscie
      DDRB  |= _BV(3);    //Ustaw PB3 jako wyjscie
      
      //---Ustawienie portów wejściowych---
      DDRD  &= ~_BV(0);   //Ustaw PD0 jako wejście
      DDRD  &= ~_BV(1);   //Ustaw PD1 jako wejście
      PORTD |=  _BV(0);   //Ustaw PD0 w stan wysoki
      PORTD |=  _BV(1);   //Ustaw PD1 w stan wysoki
    
      //---Ustawienia Timera
      TCCR1B |= (1 << CS10); // Ustaw timer 
    }
    int main(void)
    {
      inicjalizacja();
      unsigned char a=0,Tsw=30,sw_delay=0;
      LED0_ON;   //Ustaw stan wysoki  PB0
      while(1)
      { 
    	//---Program glowny---
    	// Sprawdzenie przyciskow
    	if(TCNT1>=5000) 
    	{
    	  sw_delay++;
    	  if(sw_delay>=20)
    		{
    		  if(bit_is_clear(PIND, PD0))
    		  {
    			Tsw++;
    			sw_delay=0;
    		  }
    		}  
    	  if(sw_delay>=2)
    		{
    		  if(bit_is_clear(PIND, PD1))
    		  {
    			Tsw--;
    			sw_delay=0;
    		  }
    		}  
    	}
    	// Obroty silnika w lewo
    	if(TCNT1>=5000)
    	{
    	  TCNT1 = 0;         //Wyzeruj licznik
    	  a++;
    	  if(a>=Tsw)
    	  {
    	    LED0_OFF;   //Ustaw stan niski  PB0
    		LED1_ON;   //Ustaw stan wysoki  PB1
    		//a=0;
    	  }
    	  if(a>=2.0*Tsw)
    	  {
    	    LED1_OFF;   //Ustaw stan niski  PB1
    		LED2_ON;   //Ustaw stan wysoki  PB2	
    	  }  
    	  if(a>=3.0*Tsw)
    	  {
    	    LED2_OFF;   //Ustaw stan niski  PB2
    		LED3_ON;   //Ustaw stan wysoki  PB3
    	  }  
    	  if(a>=4.0*Tsw)
    	  {
    	    LED3_OFF;   //Ustaw stan niski  PB3
    		LED0_ON;   //Ustaw stan wysoki  PB0
    		a=0;
    	  }
    	}
      }
      return 0;
    }
    
  • #19 5699529
    Dr.Vee
    VIP Zasłużony dla elektroda
    Może szkoda że nie korzystasz z symulatora - w ten sposób w dochodzeniu do rozwiązania może Ci pomóc tylko łut szczęścia :)

    nelik1987 napisał:
      //---Ustawienia Timera
      TCCR1B |= (1 << CS10); // Ustaw timer 
    To ciekawe, za 3 dni zapomnisz o co tutaj chodzi. Jak masz pisać takie komentarze to lepiej nic nie pisz :)

    Nie sprawdzasz czy Tsw nie przekracza zakresów (w górę i w dół).

    W części "obroty silnika w lewo" jest poważny błąd, którego po "miganiu diodek" nie jesteś w stanie zauważyć - np. gdy a == 2.5*Tsw to wykona się sekwencja LED0_OFF LED1_ON LED1_OFF LED2_ON, czyli generujesz impuls na LED1 mimo, że gołym okiem go nie widać. Ciekawe co na to Twój silnik krokowy powie :]

    Naucz się nie dotykać mikrokontrolera dopóki nie jesteś pewien, że kod jest poprawny i w symulacji działa jak trzeba.

    PS. Dostałeś prawie gotowy kod, jeszcze Ci go inni wytłumaczyli, ale Ty zamiast zrozumieć dlaczego tak a nie inaczej, to wykazujesz oznaki syndromu NIH.

    Pozdrawiam,
    Dr.Vee
  • #21 5700944
    nelik1987
    Poziom 31  
    Dr.Vee napisał:

    nelik1987 napisał:
      //---Ustawienia Timera
      TCCR1B |= (1 << CS10); // Ustaw timer 
    To ciekawe, za 3 dni zapomnisz o co tutaj chodzi. Jak masz pisać takie komentarze to lepiej nic nie pisz :)


    Tą linie skopiowałem z innego gdzie w podobny sposób obsługiwane były timery

    Cytat:
    Nie sprawdzasz czy Tsw nie przekracza zakresów (w górę i w dół).


    Tak wiem doskonale o tym, bo program nie jest skończony, sprawdzanie zakresu minimalnego i maksymalnego jest konieczne ponieważ silnik kręci się albo bardzooo wolno skok na przykład co sekundę (po co to komu), albo sygnały są tak szybko zmieniane, że silnik już nie może się kręcić, dokonale o tym wiem i to poprawię


    Cytat:
    W części "obroty silnika w lewo" jest poważny błąd, którego po "miganiu diodek" nie jesteś w stanie zauważyć - np. gdy a == 2.5*Tsw to wykona się sekwencja LED0_OFF LED1_ON LED1_OFF LED2_ON, czyli generujesz impuls na LED1 mimo, że gołym okiem go nie widać. Ciekawe co na to Twój silnik krokowy powie :]


    tak wiem o co Ci chodzi , zauważyłem to dopiero po jakimś czasie ponieważ wszystko mi działało doskonale, tzn działa nadal, ale wiem w czym problem, po prostu dla pierwszego IFa od obrotów silnika dodam jeszcze jeden warunek żeby nie wchodził do pierwszej funkcji jeżeli a jest już większe od np. 1,5*Tsw

    Zawsze można napisać warunek if(a=Tsw) potem if(a=2.0*Tsw) ale czytałem ze takie rozwiązanie nie jest dobre ponieważ gdyż możne zdarzyć się taka sytuacja, że przekroczymy w nieoczekiwany sposób Tsw i funkcja w ogóle nie zadziała, dlatego założyłem taki margines błędy ale jeszcze nad tym popracuję

    Silnik działa doskonale nawet pomimo tych bardzo krótkich impulsów
  • #22 5707815
    nelik1987
    Poziom 31  




    oto efekt jaki chciałem osiągnąć, moze i program do procka nie jest doskonały i zawiera wiele niedociągnięć jakie wytknął mi mój prowadzący ale działa tak jak powinno, prace zaliczyłem na 5,5 i o to chodziło :P:P:P

    dzięki wszystkim za pomoc
REKLAMA