deshipu Napisano Grudzień 30, 2016 Udostępnij Napisano Grudzień 30, 2016 Muszę przyznać, że trochę utknąłem. Przeczytałem już datasheet 4 razy, porównałem swój kod z przykładami w Internecie i nadal nie mogę zrozumieć co jest nie tak. Może ktoś z was ma z tym jakieś doświadczenie albo zauważy oczywisty błąd. Zatem do rzeczy. Próbuję odczytać przy pomocy ADC na ATtiny85 wartość z nóżki ADC3 (czyli przypadkiem akurat PB3). Niestety, wydaje się, że odczyt jest robiony tylko raz (o ile jest robiony) i cały czas dostaję tę samą wartość w okolicach 512, inną po każdym restarcie, niezależną od tego czy nóżka sobie wisi, jest podpięta do masy czy do zasilania. Mój kod wygląda obecnie tak: #include <util/delay.h> #include <avr/io.h> void TxByte(char); void uart(const char* str) { while (*str)TxByte(*str++); } uint16_t adc() { ADCSRA |= 1<<ADSC; while (ADCSRA & (1<<ADSC)); return ADCH<<8 | ADCL; } int main() { char buf[100] = {}; // Init ADC. ADMUX = 1<<MUX1 | 1<<MUX0; // pin ADC3 DIDR0 |= 1<<ADC3D; // disable PB3 ADCSRA = 1<<ADEN | 1<<ADPS2 | 1<<ADPS1 | 1<<ADPS0; // /128 prescaler while (1) { itoa(adc(), buf, 10); uart(buf); uart("\r\n"); _delay_ms(200); } } Uprościłem go ile się dało. Używam seriala z http://nerdralph.blogspot.ch/2013/12/writing-avr-assembler-code-with-arduino.html więc żeby to skompilować, trzeba dodać ten plik assemblerowy. Ale to nie powinno mieć znaczenia. Jakiekolwiek pomysły? Link do komentarza Share on other sites More sharing options...
marek1707 Grudzień 30, 2016 Udostępnij Grudzień 30, 2016 Ten ADC nie odda nowego wyniku dopóki nie skasujesz flagi ADIF. Normalnie robi to sprzęt po wejściu do obsługi przerwania, ale jeśli obsługujesz ADC "ręcznie" to musisz po odczycie wyniku wpisać 1 do bitu ADIF (co go kasuje). Jeśli robię pooling czekam właśnie na zapalenie ADIF a nie na koniec ADSC. Acha, nie musisz kombinować z przesuwaniem przy odczytach bo to jest groźne. Biblioteka ma wbudowane operacje (makra) na rejestrach 16-bitowych, które nota bene robią to w odpowiedniej kolejności, bo to nie jest dowolne: uint16_t wynik = ADC; // 🙂 Link do komentarza Share on other sites More sharing options...
deshipu Grudzień 30, 2016 Autor tematu Udostępnij Grudzień 30, 2016 No właśnie jeden problem znalazłem -- czytanie ADCL musi być przed ADCH. Po poprawieniu tego zacząłem dostawać różne odczyty -- niestety nieskorelowane z pinem ADC3, tylko takie bardziej sobie losowo falujące. Spróbuję wyczyścić flagę ADIF, choć przerwań nie mam włączonych. Link do komentarza Share on other sites More sharing options...
marek1707 Grudzień 30, 2016 Udostępnij Grudzień 30, 2016 Być może opadnięcie ADSC oznacza jedynie koniec konwersji. Za to ustawienie ADIF oznacza na pewno koniec konwersji i uaktualnienie rejestrów wyjściowych. To nie musi być ten sam moment w czasie z dokładnością do taktu zegara więc możesz czytać jakieś śmiecie. Czekaj na ADIF i kasuj go. I nie używaj operacji read-modify-write (np. ADSRA |= cośtam) bo to niechcący niszczy takie bity kasowane przez zapis jedynki. Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
deshipu Grudzień 30, 2016 Autor tematu Udostępnij Grudzień 30, 2016 I nie używaj operacji read-modify-write (np. ADSRA |= cośtam) bo to niechcący niszczy takie bity kasowane przez zapis jedynki. To czego mam używać? Datasheet twierdzi, że SBI też ma ten problem. Link do komentarza Share on other sites More sharing options...
Wojciech Grudzień 30, 2016 Udostępnij Grudzień 30, 2016 deshipu, a jaką masz częstotliwość CPU? Bo zalecane f_ADC to 50 - 200 kHz, czyli w Twoim przypadku f_CPU powinno się mieścić w przedziale: 6.4 - 25.6 MHz Link do komentarza Share on other sites More sharing options...
deshipu Grudzień 30, 2016 Autor tematu Udostępnij Grudzień 30, 2016 Dobra, rozwiązane, bardzo dziękuję za pomoc. Problemy były dwa. Pierwszy, to odczytywanie ADCL i ADCH w odwrotnej kolejności, co powodowało, że się zapadka na nich nie zwalniała. Drugi, to biedny ATtiny85 którego mam do tych eksperymentów wlutowanego w płytkę z nóżkami, dla wygody, i którego używam już od 2 lat do różnych dziwnych rzeczy. Najprawdopodobniej uszkodziłem mu w pewnym momencie w jakiś sposób ADC. Ten sam program wgrany na inny chip działa bez problemów. Link do komentarza Share on other sites More sharing options...
marek1707 Grudzień 30, 2016 Udostępnij Grudzień 30, 2016 Czyli raczej pin, bo samego ADC w środku trudno popsuć. Hm, może jakoś przez VREF? Spróbuj na innym pinie - tak z ciekawości 🙂 Wojciech: ten zakres musisz spełnić gdy chcesz uzyskać parametry ADC podawane przez producenta. Zupełnie spokojnie możesz ADC puścić na 1MHz - dostaniesz wtedy może 7-8 bitów znaczących a reszta to śmieci. Za to masz wtedy ponad 70ksps 🙂 W drugą stronę (przy mniejszych częstotliwościach taktowania niż 50kHz) błędy mogą być bardziej subtelne i trudniejsze do korekcji, bo część toru analogowego opiera się na pojemnościach a te nie mogą ładunku utrzymywać zbyt długo z uwagi na upływności. Na szczęście ATMEL musi gwarantować działanie w całym zakresie temperatur a technologia łamie się najbardziej przy wysokich. Dlatego w normalnych warunkach ADC będzie działał nawet przy taktowaniu procka z zegarkowego kwarcu 32kHz (próbowałem). Link do komentarza Share on other sites More sharing options...
deshipu Grudzień 30, 2016 Autor tematu Udostępnij Grudzień 30, 2016 Niestety albo poszedł ADC, albo mux, bo ten sam efekt na wszystkich pinach. Nie szkodzi, czip pójdzie do nyan cata grać melodyjki... Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »