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] ATmega8: Nieprawidłowy odczyt ADC0 i ADC1 w trybie single conversion

teel 21 Lip 2012 22:32 1206 5
REKLAMA
  • #1 11130876
    teel
    Poziom 10  
    Witam,
    Zdecydowałem się na napisanie tego posta z prośbą o podpowiedź, przegrzebałem kod, który jest prosty ale błędu nie mogę dostrzec.

    Krótko: odczytuję w trybie single conversion wartość z ADC0, wrzucam do zmiennej int, potem UART. Jak robię jeden odczyt to wszystko jest ok.
    Ale jak robię jeden po drugim (nawet z opóźnieniem 50ms), to wynik z ADC1 trafia mi do zmiennej, która zczytała z ADC0, a wartość z ADC0 trafia do zmiennej od ADC1. Kompletnie tego nie rozumiem.
    Założenia: 10 bitów rozdzielczości, na ADC0 dzielnik napięcia 1:1 (spodziewam się wartości 512), na ADC1 dzielnik 1:10, czyli oczekiwana wartość to 93.

    Jeśli odczytuję sam adcVal_N, dostaję ADC_N:512.
    Jak odczytuję dodatkowo adcVal_E, dostaję ADC_N:93 ADC_E:512.

    Oto kod, bardzo proszę o rzucenie okiem, jestem początkujący w mikrokontrolerach, może łamię jakieś podstawowe założenie.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #2 11131010
    tmf
    VIP Zasłużony dla elektroda
    Masz co najmniej dwa błędy:
    1. twoja tablica buffer jest za krótka - na 16-bitów potrzebujesz w najgorszym przypadku 5 bajtów na cyfry i jeden na null, w sumie 6 bajtów, a nie 4.
    2. Przed odczytem wartości z ADC musisz poczekać na zakończenie konwersji, w przeciwnym przypadku odczytujesz poprzenią wartość (ADC nie został uaktualniony). Dla dwóch odczytów efekt jest taki jakby ich kolejność uległa odwróceniu.
    A poza tematem - niepotrzebne kombinacje robisz z odczytem dwóch połówek ADC, można po prostu czytać 16-bitowy rejestr ADC (ADCW).
  • REKLAMA
  • #3 11131055
    teel
    Poziom 10  
    tmf napisał:
    Masz co najmniej dwa błędy:
    1. twoja tablica buffer jest za krótka - na 16-bitów potrzebujesz w najgorszym przypadku 5 bajtów na cyfry i jeden na null, w sumie 6 bajtów, a nie 4.
    2. Przed odczytem wartości z ADC musisz poczekać na zakończenie konwersji, w przeciwnym przypadku odczytujesz poprzenią wartość (ADC nie został uaktualniony). Dla dwóch odczytów efekt jest taki jakby ich kolejność uległa odwróceniu.
    A poza tematem - niepotrzebne kombinacje robisz z odczytem dwóch połówek ADC, można po prostu czytać 16-bitowy rejestr ADC (ADCW).


    Dziękuję za odpowiedź!
    Ad 1. poprawione, ale oczywiście to nie jest przyczyną błędu.
    Ad 2. właśnie z uwagi na ten fakt ten _delay_ms(50), wydawało mi się, że to wystarczająco, spróbowałem też z 200ms (to jest już wieczność), niestety ten sam prrblem. Poza tym czytałem, że konwersja zajmuje 50-100 tyś taktów zegara i po to ustawiamy preskaler, czyli spodziewałbym się, że na ten czas odczyt z rejestru (ADCval = ADCW) będzie zablokowany.
    W jaki sposób mogę się dowiedzieć, że konwersja w trybie single conversion się zakończyła?
    A o ADCW nie wiedziałem, dzięki! Też już poprawione.
  • REKLAMA
  • #4 11131093
    LordBlick
    VIP Zasłużony dla elektroda
    teel napisał:
    W jaki sposób mogę się dowiedzieć, że konwersja w trybie single conversion się zakończyła?
    Badając ten sam bit, który ustawiasz przy starcie(ADSC), lub ustawiając przerwanie bitem ADIE i obsługując je w procedurze ISR(ADC_vect).
  • REKLAMA
  • #5 11131138
    tmf
    VIP Zasłużony dla elektroda
    teel napisał:

    Ad 2. właśnie z uwagi na ten fakt ten _delay_ms(50), wydawało mi się, że to wystarczająco, spróbowałem też z 200ms (to jest już wieczność), niestety ten sam prrblem. Poza tym czytałem, że konwersja zajmuje 50-100 tyś taktów zegara i po to ustawiamy preskaler, czyli spodziewałbym się, że na ten czas odczyt z rejestru (ADCval = ADCW) będzie zablokowany.


    Zauważ, że potrzebujesz odstęp pomiędzy startem konwersji a odczytem ADCW, a nie pomiędzy kolejnymi startami konwersji. Stąd też jak pisze LordBlick starujesz konwersję, czekasz aż ADSC się wyzeruje i dopiero czytasz ADCW.
  • #6 11131185
    teel
    Poziom 10  
    Dziękuję Panowie, problem prawdopodobnie rozwiązany, odczyty są prawidłowe.
    Oto kod, dodałem while(...):

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
REKLAMA