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

[Atmega8] Przetwornik ADC - przerwanie

jacobs242 01 Kwi 2010 02:19 4857 10
REKLAMA
  • #1 7905637
    jacobs242
    Poziom 18  
    Muszę powrócić do tematu o którym częściowo już kiedyś pisałem. Piszę aktualnie obsługę przetwornika przez przerwanie, dane z pięciu czujników.

    Przetwornik inicjowany w następujący sposób
    void adc_init(void)
    {
    	ADMUX = currentadc;
    	ADCSRA = (_BV(ADEN)|_BV(ADIE)| _BV(ADFR)|_BV(ADSC)|_BV(ADPS1)|_BV(ADPS2));
    }

    Gdzie currentadc jest zmienną
    volatile uint8_t currentadc =0;
    .
    Przerwanie obsłużone tak:
    ISR(ADC_vect)
    {
    	adcvalue[currentadc] = ADCW;
    
    	if(++currentadc == 5)
    	{
    		currentadc = 0;
    		for(int i=0; i <5; i++)
    			sensory[i] = adcvalue[i];
    	}	
    	ADMUX = currentadc;
    }
    

    adcvalue przechowuje aktualnie sczytane dane, które są kopiowane do tablicy sensory po każdej serii.

    Wynik jest taki, że dane w tablicy sensory są jakieś dziwne - odczytując sensory[4] otrzymuję sensory[3], reszta też pomieszana lub w ogóle nic nie zapisane.

    Gdzie tkwi błąd? Przejrzałem już masę artykułów, postów, próbowałem na różne sposoby i nie działa.
  • REKLAMA
  • #2 7906446
    tadzik85
    Poziom 38  
    ADCW?? A po co pętla for w przerwaniu?? Nie widzę oczekiwanie na flagę końca konwersji.
  • REKLAMA
  • #3 7906534
    dj_west
    Poziom 17  
    Wyjaśnienie jest bardzo proste i nieskomplikowane :)

    Otóż, gdy program wchodzi w ISR, zgłasza zakończenie przetwarzania. Ale równocześnie zaczyna kolejne przetwarzanie (w trybie Free Running). I nim zdążysz przetwornikowi przełączyć źródło pomiaru, to zacznie przetwarzać jeszcze raz wartość z poprzedniego źródła. Najlepszym sposobem na to jest odrzucić pierwszy wynik przetwarzania po zmianie sensora i brać pod uwagę tylko drugi. Ewentualnie wprowadzać ADC w tryb Single Conversion, a wtedy po zmianie źródła ponownie startujesz przetwarzanie i masz co chcesz :) Ja stosuję ten drugi sposób w układzie zdalnego sterowania modelem latającym, zatem musi być on niezawodny.

    Datasheet wyjaśnia te kwestie ponad wszelką wątpliwość :)

    Pozdrawiam serdecznie!
  • #4 7906544
    tadzik85
    Poziom 38  
    No też właśnie, lecz obsługa przerwania kolegi wygląda co najmniej dziwnie.
  • Pomocny post
    #5 7906565
    dj_west
    Poziom 17  
    Czy ja wiem? O ile dobrze pamiętam, ja zrobiłem prawie identyczną obsługę. Nawet zaraz to sprawdzę.
    Kolega chce po prostu bieżące wartości uzyskane z pomiarów przenieść do innej tablicy - aktualizowanej po "przeskanowaniu" wszystkich sensorów. Myślę, że wie co robi :) Niech tylko przełączy się w tryb Single Conversion i będzie po kłopocie - po zmianie źródła wykonać (uprzednio odpowiednio konfigurując ADC dla trybu Single Conversion):
    ADCSRA |= (1<<ADSC);


    EDIT:
    Ja jednak aktualizowałem tablicę przetwarzania w innym momencie programu. Ale to nie przeszkadza. Oczywiście to ADCW to "przejęzyczenie"? :)
  • #6 7907566
    jacobs242
    Poziom 18  
    Generalnie co do tej pętli to jestem pewien, że jest ok. Po prostu chcę mieć tablicę która daje wyniki z jednej "serii" odczytów.

    ADCW to też nie błąd, nie wiem skąd to się wzięło, ale da się z tego odczytać 10 bitów wyniku. Wiem, że według datasheetu trzebaby to zrobić (ADCL | ADCH<<8), ale ten sposób też działa. W ogóle widziałem przypadki w których odczytywano wynik z "rejestru" ADC - sprawdziłem, też działa.

    Myślałem, że następna konwersja nastąpi dopiero po zakończeniu obsługi przerwania, a nie od razu. Poprawię i sprawdzę wieczorem.

    Pytanie dodatkowe - czy obsługa przerwania za pomocą ISR blokuje inne przerwania? Do tej pory zawsze korzystałem z SIGNAL i INTERRUPT, z którego teraz się odchodzi...
  • REKLAMA
  • Pomocny post
    #7 7907608
    tadzik85
    Poziom 38  
    Blokuje.
    Cytat:
    Introduces an interrupt handler function (interrupt service
    routine) that runs with global interrupts initially disabled
    by default with no attributes specified.

    The attributes are optional and alter the behaviour and resultant
    generated code of the interrupt routine. Multiple attributes may
    be used for a single function, with a space seperating each
    attribute.

    Valid attributes are ISR_BLOCK, ISR_NOBLOCK, ISR_NAKED and
    ISR_ALIASOF(vect).

    A co do ADCW przeglądałem dokumentację później zdałem sobie sprawę, że GCC inaczej nazywa ten rejestr, sorki.
  • #8 7908828
    jacobs242
    Poziom 18  
    Działa! Dziękuję :)
  • REKLAMA
  • #9 7909932
    dj_west
    Poziom 17  
    Cieszy nas to niezmiernie :)

    Właśnie przejrzałem plik nagłówkowy iom8.h z AVR-GCC i... faktycznie, istnieją 16-bitowe rejestry ADC oraz ADCW! Nigdy wcześniej z nich nie korzystałem :) Zatem i ja się czegoś nauczyłem :D

    Pozdrawiam!
  • #10 7920037
    regrom
    Poziom 16  
    jacobs242 napisał:
    Działa! Dziękuję :)


    Skoro działa to czy mógłbyś się podzielić rozwiązaniem? Sam miałem problem z mieszaniem się kanałów,ale odstawiłem go na półkę z braku czasu.

    Używałem trybu free runing oraz flagi od zakończenia konwersji ale pomimo tego nie dość że miałem przesunięte odczyty z poszczególnych kanałów to także się one mieszały co jakiś pomiar..

    Będę wdzięczny jeśli się podzielisz swoim kodem.
    Pozdrawiam
  • #11 7921922
    jacobs242
    Poziom 18  
    Zrezygnowałem z trybu free running. Po obsłużeniu przerwania, w jego ostatniej linijce włączam kolejne przetwarzanie.

    Nie chciało mi się już bawić z trybem FR, trzeba by wybierać wyniki przetwarzań, które wystartowały po zmianie kanału i wydaje mi się że byłoby to nawet wolniejsze, niż odczyt bez FR.
REKLAMA