atmega32 i czestotliwość pracy...

Feb 20, 2007 11 Replies

witam, w swoich walkach z tymze prockiem, doszedłem do problemu, z którym nie potrafie sobie poradzić, i który mnie szczerze zadziwia. otóż, zamontowałem zewnetrzny kwarc 12MHz, odpowiednio ustawilem fusebity , no i myslałem ze teraz juz bede mial stabilny pomiar czasu... no ale lipa - nie jestem w stanie sensownie zaprogramować delay-a. pomijajac rózne pomysły z timerem, z których niewiele mi sie udalo wykrzesać, doszedłem do wniosku ze do pomiaru opóźnień rzedu kilkudziesieciu us, wysatrczy pętla for. no i zrobiłem petle: for(int x=0;x<120;x++); ale niebardzo mi to chcialo to działać, więc postanowilem to przebadać, i wsadziłem to w pętle for(int y=0;y<10000;y++) { for(long int x=0;x<120000;x++); } i okazało się ze czas wykonywania takiej operacji trwa ok 13sek....



o co tu chodzi? nie powinienem raczej przepełniać zmiennych, nie mam pojęcia ile cykli trwa wykonywanie pętli for(long int x=0;x<120000;x++); ale wydaje mi się ze gdyby to był 1 cykl, to wtedy całość powinna trwać jakies 1200000000 cykli a to chyba jest niemozliwe na takim kwarcu w tym czasie ;) powiedzcie co tu jest zle, i ewentualnie jak inaczej sensownie zrobić kontrolowane opoznienie?



i ewentualnie jak inaczej sensownie zrobić

formatting link

Witam,

Dnia 20.02.07 (wtorek), 'Kamillos' napisał(a):

Funkcja _delay_ms jest niezła - kiedyś miałem gotowy prosty program i chciałem dodać tylko opóźnienie, użyłem jej i mi 2kB flasha zabrakło. :) Jak się później okazało (zerknąłem w kod), wykonuje ona zmiennoprzecinkowe operacje na argumencie, a to sporo miejsca zabiera. Może po włączeniu jakiś optymalizacji kompilator (GCC) wrzuciłby gotowe wartości, bo argumenty funkcji były zawsze stałe i takie same...

Dykus snipped-for-privacy@spamywp.pl pisze:

Dziwne, u mnie wszystko jest ok.

nuclear napisał(a):

Zapewne została zoptymalizowana przez kompilator, i tak cud że cokolwiek trwa ;). Jakiego rzędu chcesz robić opóźnienia?

wymagane czasy to 10-300us, z dokladkoscia kilku us, w sumie to mogłem takm wsadzisć jakąś nic nie robiącą funkcję pod tą pętlą, to by juz chyba nie optymalizował tego ;) no ale teraz doszedłem do wniosku ze zaprzęgnę do tego timer, tylko jeszcze nie udało mi sie tego zrobić. zaożenie ejst takie, ze mam zmienną timer; przerwaniami z timera ją incrementuję, w celu zmierzenia czasu zerję zmienną i czekam az osiagnie wymaganą wartość. no i jakoś mi sie tego jeszczenie udało osiągnąć.. oto co napisałem

long int timer;

///////////////////////////////timer2 ustawienia // wpisanie wartosci koncowej OCR2=60; // ustawienie trybu pracy licznika TCCR2 = 0b00001001; // odblokowanie przerwania od licznika TIMSK = 0b10000000; // globalne odblokowanie przerwań sei(); //////////////////////////timer2 ustawienia end

SIGNAL (SIG_OUTPUT_COMPARE2) { timer++; }

no i po takich założeniach nie przechodzi pętli

while(timer<50000);

wiecie dlaczego tem licznik nie chce ruszyc i dawać przerwań?

W dniu 20-02-2007 23:03, Dykus napisał:

Się czyta dokumentacje, się wie :-) Bo dokumentacja jasno mówi, że rzeczywiście obliczenia na floatach są, ale tylko wtedy, kiedy optymalizacje ustawione są na o0, czyli żadne. Włączenie któregokolwiek z poziomów dramatycznie redukuje rozmiar kodu wynikowego.

nuclear napisał(a):

Daj volatile przed long int timer;

Ja bym jednak timera nie pchał do tego. Zrób raczej coś w stylu:

void Delay_uS(int us) { for(;us>0;us--) { asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); } }

liczbę nop-ów musisz dobrać eksperymentalnie.

A dlaczego? Zachce mu się zrobić coś na przerwaniach i cały koncept się rozsypie. Poza tym w międzyczasie można robić też inne rzeczy, np

  1. ustaw timer
  2. zrób coś niewielkiego
  3. sprawdź czy już, jak nie, to goto 1

pozdrawiam

majek

Witam,

Dnia 21.02.07 (środa), 'Krzysiek' napisał(a):

Dzięki za informacje. To było moje pierwsze starcie z C na AVR, bardzo prosty układ (na dowolny procek pod ręką) i nawet nie chciało mi się czytać dokumentacji do tych delay-ów, szybciej było zrobić swoje... ;)

zrobiłem to na timerze, pięknie liczy, dokładnie itp, jest jedno ale - w innym przerwaniu (int1) mam funkcje która wykorzystuje delay-a, w momenicie wyzwolenia tegoż przerwania, cały program ulega zawieszeniu - dobrze wnioskuje ze w trakcie działania int1, przerwanie z licznika nie zostanie obsłużone? czyli jednak zostaje mi zrobić to mniej dokladnie - na nopach?

Dobrze. Niedobrze, że wykorzystujesz delay w przerwaniu. Przerwanie powinno być jak najkrótsze. Jak potrzebujesz robić jakieś cudactwa, to zastanów się nad tym, żeby tylko w przerwaniu zapamiętać początek liczenia, ustawić flagę, a resztę już zrobić w głównej pętli. Możesz jeszcze odblokować przerwania i pozwolić na przerwanie przerwania, ale wtedy powinieneś mieć jakiś sheduler, bo jak dostaniesz kolejne przerwanie od INT1, to może Ci się wszystko pokiełbasić. Nie wiem co robisz w tym przerwaniu, ale pewnie da się to zrobić bez tego delaya:-)

pozdrawiam

majek

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required