Panowie, panowie - nie rozpędzajcie się w tych wyjaśnieniach o rdzeniach 8-bitowych i dziwnych myślach programistów tworzących funkcje typu _delay_ms()
nsvinc napisał:
Jak dla mnie - bezsens. Nawet marnowanie czasu powinno być zrealisowane
prosto, a nie w oparciu o software'owe biblioteki umożliwiające
przetwarzanie double....
Bo jest prosto, i to bardzo prosto -
mega prosto - czytaj dalej ....
dziechu napisał:
To raczej chyba anie nie błąd, ani głupota programistów, dlatego drążę temat:)
I to się nazywa podejście, zamiast od razu jak niektórzy narzekać, że ktoś źle pomyślał tworząc funckje z takimi argumentami
To jest bardzo dobry pomysł a na dodatek dzięki takiemu rozwiązaniu , uwaga!!! wcale wbrew pozorom nie używa się liczb typu double o ile ma się pojęcie jak należy używać tych funkcji: _delay_us() oraz _delay_ms()
Podałeś link do definicji gnu a tam jest jasno napisane:
Cytat: The idea behind is that compile-time constant expressions will be eliminated by compiler optimization so floating-point expressions can be used to calculate the number of delay cycles needed based on the CPU frequency passed by the macro F_CPU.
co oznacza ni mniej ni więcej, że można używać jako argumenty "stałych dosłownych" typu double, które zostaną w wyniku optymalizacji zmienione na odpowiednią stałą i nie zmiennoprzecinkową

liczbę cykli zegara. Dzięki temu można sobie w zakresie
od 0 do 262.14 ms super dokładnie regulować opóźnienie korzystając ze stałych podkreślam stałych zmiennoprzecinkowych. Zatem jeśli wpiszę sobie np tak:
to rzućcie sobie panowie przeciwnicy ych funkcji okiem na asemblerowy kod, to powinno wszystko chyba jendoznacznie wyjaśnić i pokazać, że po drodze nie została użyta ŻADNA LICZBA ZMIENNOPRZECINKOWA
caa: 8a ee ldi r24, 0xEA ; 234
cac: 93 e0 ldi r25, 0x03 ; 3
cae: 24 e1 ldi r18, 0x14 ; 20
cb0: 31 e0 ldi r19, 0x01 ; 1
cb2: f9 01 movw r30, r18
cb4: 31 97 sbiw r30, 0x01 ; 1
cb6: f1 f7 brne .-4 ; 0xcb4 <main+0x20>
cb8: 01 97 sbiw r24, 0x01 ; 1
cba: d9 f7 brne .-10 ; 0xcb2 <main+0x1e>
A jednocześnie można z precyzją zmiennoprzecinkową choć najlepiej w postaci stałych robić super dokładnie opóźnienia co do pojedynczych taktów zegara, szczególnie gdy masz wyłączone przerwania w tym czasie.
....ale jeśli użyjesz jako argumentu takiej funkcji zmiennej, co do której kompilator nie może się domyśleć jaką będzie miała wartość gdyż po drodze np w jakiejś pętli ulega ona obliczeniom to już nie ważne czy będzie taka zmienna typu double czy int - to i tak kompilator zaprzęgnie całe swoje biblioteki do obliczeń zmiennoprzecinkowych (ok 2kb kodu) i o tyle od razu wzrośnie cały kod wynikowy a w asemblerze nie będę tu zamieszał listingu takiej funkcji bo za długi byłby
Dziwią się czasem ludzie piszący np na procku ATtiny, że nagle kod po kompilacji nie mieści się w procku - co się stało ?!?!? .... auto muchę przejechało - bo się zmienną doble jako argument zapodało
czyli :
uint8_t a=50;
uint8_t i;
for(i=0;i<10;i++) _delay_ms(a*i);
już ci zrobi masakrę w kodzie tzn może nie masakrę - po prostu trzeba o tym wiedzieć bo czasem jak masz duuużo pamięci to może cię czochrać takie coś
ale jeśli dasz tak:
uint8_t a=50;
_delay_ms(a);
to znowu będzie krótki kodzik, gorzej jak gdzieś znowu dalej w kodzie zmienna a będzie mogła ulec zmianie w trakcie obliczeń to już zostanie znowu rozwinięty kod o biblioteki zmiennoprzecinkowe.
Wiedząc o tym wszystkim chyba należy przyznać, że stwórcy mieli łeb na karku a nie tam jakieś głupoty popełniali czy byki strzelali - prawda ?
mam nadzieję, że to wyjaśnia ten problem - zagadkę ?