RTV forum PL | NewsGroups PL

Czemu pętla for na Atmega32 z kwarcem 12MHz działa tak wolno? Jak ustawić poprawne opóźnienia?

atmega32 i czestotliwość pracy...

NOWY TEMAT

elektroda NewsGroups Forum Index - Elektronika Polska - Czemu pętla for na Atmega32 z kwarcem 12MHz działa tak wolno? Jak ustawić poprawne opóźnienia?

nuclear
Guest

Tue Feb 20, 2007 7:24 pm   



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 Wink
powiedzcie co tu jest zle, i ewentualnie jak inaczej sensownie zrobić
kontrolowane opoznienie?

Kamillos
Guest

Tue Feb 20, 2007 9:51 pm   



i ewentualnie jak inaczej sensownie zrobić
Quote:
kontrolowane opoznienie?


http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html

Dykus
Guest

Tue Feb 20, 2007 11:03 pm   



Witam,

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

Quote:
http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html

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. Smile
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...


--
Pozdrawiam,
Dykus.

Patryk Sielski
Guest

Wed Feb 21, 2007 12:36 am   



Dykus <dykus.grupy@spamywp.pl> pisze:
Quote:
Dnia 20.02.07 (wtorek), 'Kamillos' napisał(a):

http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html

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. Smile
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...

Dziwne, u mnie wszystko jest ok.

--
Pozdrawiam,
Patryk Sielski

Maksymilian Dutka
Guest

Wed Feb 21, 2007 9:23 am   



nuclear napisał(a):
Quote:
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....

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

--
Pozdrawiam
Maksymilian Dutka

nuclear
Guest

Wed Feb 21, 2007 1:22 pm   



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

--
Pozdrawiam
Maksymilian Dutka

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 Wink
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ń?

Krzysiek
Guest

Wed Feb 21, 2007 2:06 pm   



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

Quote:
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. Smile
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...

Się czyta dokumentacje, się wie Smile 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.

--
Pozdrawiam
Krzysiek

Maksymilian Dutka
Guest

Wed Feb 21, 2007 2:17 pm   



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

--
Pozdrawiam
Maksymilian Dutka

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 Wink
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ń?



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.


--
Pozdrawiam
Maksymilian Dutka

Marek Wodzinski
Guest

Wed Feb 21, 2007 3:13 pm   



Maksymilian Dutka wrote:
Quote:
nuclear napisał(a):
Zapewne została zoptymalizowana przez kompilator, i tak cud że
cokolwiek trwa Wink.
Jakiego rzędu chcesz robić opóźnienia?

--
Pozdrawiam
Maksymilian Dutka

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 Wink
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ń?

Daj volatile przed long int timer;

Ja bym jednak timera nie pchał do tego.

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
--
"If you want something done...do yourself!"
Jean-Baptiste Emmanuel Zorg

Dykus
Guest

Wed Feb 21, 2007 3:52 pm   



Witam,

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

Quote:
Się czyta dokumentacje, się wie Smile

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... ;)


--
Pozdrawiam,
Dykus.

nuclear
Guest

Wed Feb 21, 2007 4:41 pm   



Quote:

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


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?

Marek Wodzinski
Guest

Wed Feb 21, 2007 9:53 pm   



nuclear wrote:
Quote:
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?

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
--
"If you want something done...do yourself!"
Jean-Baptiste Emmanuel Zorg

elektroda NewsGroups Forum Index - Elektronika Polska - Czemu pętla for na Atmega32 z kwarcem 12MHz działa tak wolno? Jak ustawić poprawne opóźnienia?

NOWY TEMAT

Regulamin - Zasady uzytkowania Polityka prywatnosci Kontakt RTV map News map