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

ATMEGA - kilka ADC na przerwaniu

kojot901 04 Lut 2015 23:09 1815 17
  • #1 14405064
    kojot901
    Poziom 9  
    Witam
    Programuje 2x ADC które szczytuje mi wartości z potencjometrów podłączonych przez dzielnik napięcia do portów PC0 PC1, za pomocą przerwania ADCSRA ( ADIE
    -Kiedy ten bit jest ustawiony wraz z I-bitem w rejestrze SREG wtedy aktywne jest
    przerwanie od zakończenia konwersji.)
    Robię tak za pomocą przerwania a nie timera bo nie chce aby mi ciągle czytał wartość z potencjometry tylko wtedy kiedy coś się zmieni, jak jest stała to będzie robić co innego, atmega8 będzie miała inne jeszcze zadania.

    Nie wiem czemu on mi nie wchodzi w te przerwanie z tego co widzę w debugging. Jeśli chodzi o cześć analogowa jest OK. Z góry dziękuje za podpowiedzi co może być nie tak.

    Kod programu


    Kod: text
    Zaloguj się, aby zobaczyć kod
  • #2 14405148
    BlueDraco
    Specjalista - Mikrokontrolery
    Ciekawe, jak Ci ten ADC "szczytuje"... ;)

    Przerwanie z ADC nie przychodzi "jak się coś zmieni", więC jednak trzeba to zrobić na timerze. zastanów się, jak często chciałbyś rejestrować zmiany położenie potencjometrów - wydaje mi się, że 10..100 razy na sekundę. Odpalaj konwersję obu kanałów na przemian w przerwaniu timera, a w następnym przerwaniu odczytuj wynik.
  • #3 14405171
    Konto nie istnieje
    Poziom 1  
  • #4 14406799
    kojot901
    Poziom 9  
    Panie Marku_Skalski ale w dokumentacji pisze że ma
    Bit 3 – ADIE: ADC Interrupt Enable
    Free Running jest ustawione w kodzie

    Nie udało mi się to zrobić na przerwaniu, ale zrobiłem to na dwóch podprogramach w których są umieszczone dwa ADC. Jedyna wada na wyświetlaczu miga wartość.

    KOD
    Kod: text
    Zaloguj się, aby zobaczyć kod

    To ma być generator korzystający z timera CTC, wartość częstotliwość zmienia się w zależności od ustawienia 1 potencjometru, drugi potencjometr jest do regulacji amplitudy.
  • #5 14407141
    BlueDraco
    Specjalista - Mikrokontrolery
    Free run i ręczny stan konwersji - coś się Koledze pomyliło.

    Będę nudny - zacznij od przerwania timera.
  • #7 14432373
    kojot901
    Poziom 9  
    zrobiłem pomiar ADC na 2 kanałach a wynik wyświetlam na LCD mam ale problem z tym że adc jest 10 bitowy i gdy chce wyświetlić wynik licząć na to że bedzie od 0 do 1023 okazuje sie że wyświetlą jakies brednie powyżej 4200 ... nie rozumie czemu. jezeli wyswietle sobie wynik
    tylko z ADCH ( rejest 8 bitowy 0-255) to pokazuje poprawie od 0 do 255 na lcd

    Kod: text
    Zaloguj się, aby zobaczyć kod



    Czy ktos mi może powiedzieć jak to zrobić aby był wynik 10 bitowy ??
  • #8 14432434
    gaskoin
    Poziom 38  
    Marek_Skalski napisał:
    Zamiast SIGNAL, używaj ISR.
    Program napisałeś tak, że przeskoczy go raz i się wywali, a może zresetuje.


    Po mainie jest nieskończona pętla :)

    adc1 i adc2 powinny być typu uint16_t i powinieneś czytać z "rejestru" ADC a nie ADCH
  • #9 14432549
    kojot901
    Poziom 9  
    nie wywala się...
    zmieniłem na
    uint16_t i na ADC i nie pomogło, już probowałem tą opcje.
  • #10 14432751
    BlueDraco
    Specjalista - Mikrokontrolery
    Oczywiście przeczytałeś stronę 201 z datasheet, prawda?
  • #11 14432768
    kojot901
    Poziom 9  
    GAIN ERROR ?? widziałem to ale przecież... nie rozumie to niema nic do rzeczy ? szukałem zdania w datasheet gdzie pisze że dla kilku kanałów jest 8 bitowy ale niema nic takiego

    a dobra kukam sobie na 200 i widze

    An n-bit single-ended ADC converts a voltage linearly between GND and VREF in 2n
    steps (LSBs). The lowest code is read as 0, and the highest code is read as 2n-1.

    czyli

    Konwersja n-bitowa polega na przekształceniu napięcia o wartości miedzy 0 (masą) a Vref w 2^n krokach. Najniższy kod wynosi 0, najwyższy 2^n-1.

    czyli powinienem miec max 512.

    chyba zostane przy ADCH czyli 8 bitach
  • #12 14432850
    BlueDraco
    Specjalista - Mikrokontrolery
    Format rejestru ADC!!!
  • #13 14432941
    kojot901
    Poziom 9  
    ATMEGA - kilka ADC na przerwaniu

    przecież mam ustawione

    volatile uint16_t adc2

    albo czegos nie rozumie albo nie wiem :P
    wybacz
  • #14 14432966
    BlueDraco
    Specjalista - Mikrokontrolery
    Przecież masz w kodzie powyżej ustawiony bit ADLAR, inaczej nie mógłbyś czytać 8-bitowego wyniku z ADCH. Masz "ten drugi" format, więc nic dziwnego, że odczyt ADC daje Ci wartości 0..64512, a nie 0..1023
  • #15 14433259
    kojot901
    Poziom 9  
    dziekuje BluDraco za pomoc.
    Pomogło
  • #16 14442889
    kojot901
    Poziom 9  
    Ma pytanko

    Czy podczas pracy timera można mu zmienić prescaler mianiowicie do jakiegos pinu podłacze sobie klawisz i jezeli on jest wcisniety to zmieniam rejest TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10); i w nim prescaler na inny.

    Jesli tak to moje pytanie czy musze wpisywać WGM ?? bo tylko CS odpowiada za prescaler to może pozostałe wartości nie warto wpisywać

    Dodano po 2 [minuty]:

    taki przykład dam, który teraz napisałem i cos nie zmienia te trybi
    Kod: text
    Zaloguj się, aby zobaczyć kod
  • #17 14443499
    BlueDraco
    Specjalista - Mikrokontrolery
    Użycie |= powoduje, że ustawisz w końcu oba bity - CS10 i CS12.

    Sens całości jest taki sobie, ale jeżeli chcesz, żeby to działało wg. Twojego pomysłu, t musisz po prostu zapisywać rejestr instrukcją podstawienia (wszystkie bity), a nie wykonywać na nim sumy logicznej |=.
  • #18 14443581
    kojot901
    Poziom 9  
    Własnie sie zastanawiam w jaki sposób zmieniać prescaler timera jesli klawisz jest wciśnięty.

    nie podoba mi sie to że za każdym razem czyta tą instrukcje if else dlatego zrobiłem to tak. ale cos nie do końca działa

    DDRD = (1<<4); // dioda do testów
    sei();
    GICR=_BV(INT1);
    MCUCR =_BV(ISC11);
    DDRD &=~_BV(PORTD3);
    PORTD = (1<<3);


    DDRB =(1<<PORTB1);
    TCCR1A =(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11); //
    CCR1B =(1<<WGM13)|(1<<WGM12)|(1<<CS12); //PRESCALER=1024 MODE 14(FAST PWM)

    while(1)
    {
    ICR1=62499 ;
    OCR1A=30000;

    PORTD &=~(_BV(4)); // dioda do testów
    }



    ISR(INT1_vect)
    {

    DDRB =(1<<PORTB1);
    TCCR1A =(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11); //
    TCCR1B =(1<<WGM13)|(1<<WGM12)|(1<<CS10); // prescaler 1
    PORTD =(1<<4);

    }




    ale teraz mam problem że nie moge wrócić do prescalera 1024. no nie wiem za bardzo jak to zrobic aby było dobrze ;/


    Moderowany przez dondu:

    Ponieważ pomimo działań moderatorów nadal nie przestrzegasz zasad pisowni oraz używania znacznika SYNTAX, jestem zmuszony nadać Ci ostrzeżenie.

    Popraw poprzedni post, bym nie musiał nadać drugiego ostrzeżenia.

REKLAMA