(26-02-2012 23:34)SP4EJT napisał(a): Co do tego że kompilator powinien czerwone kropy wywalać to się zgadzam - ale on nie wywala, kompiluje i program działa ! ... dziwne zachowanie z jego strony
No to mamy triumf praktyki nad teorią: "program działa tylko nie wiemy dlaczego"
Kod:
unsigned long int FTW, fs; // deklaracja zmiennej FTW i zmiennej fs
fs=400000000; // fs to częstotliwość taktowania DDSa
...
...
FTW=4294967296*frequency/fs;
Dlaczego powyższy kod działa poprawnie ?
* liczba 4294967296 to nic innego jak 2 do potęgi 32. Słusznie zauważono wcześniej, że nie mieści się ona na 4 bajtach. Na szczęście nie został jawnie określony format tej liczby jako (UL). Kompilator widząc w kodzie źródłowym liczbę większą od long int (32bity) nadał jej format long long int (64bity) co uratowało ten kod od wysypania !
* mimo, że zmienne frequency i fs są 32 bitowe to wynik wyrażenia po prawej stronie jest 64 bitowy ponieważ przyjmuje on format największego argumentu występującego w wyrażeniu (stała long long int, 64bity) .
* format zmiennej FTW jest zgodny z naszymi potrzebami, czyli 32bity. Podczas przypisania wyniku wyrażenia zmiennej FTW następuje niejawna konwersja formatu wyniku z 64 bitów do 32bitów. Nie tracimy żadnej informacji ponieważ wynik zawsze mieści się na 4 bajtach i jest to tylko zmiana formatu danych.
Bardziej czytelny byłby zapis zawierający jawne
rzutowanie wyniku wyrażenia na format zmiennej po lewej stronie oraz jawne określenie formatu stałej:
FTW=(unsigned long int) (4294967296ULL*frequency/fs)
Inne uwagi:
- ze względu na zajętość pamięci oraz czas wykonania należy unikać długich formatów zmiennych;
- szybszą metodą niż mnożenie przez 4294967296 jest przesunięcie zmiennej o 32 bity w lewo !!!
- wysyłanie nastawy FTW do DDS-a lepiej przerobić na wysyłanie pojedynczych bajtów, maskowanie bitu na zmiennej 32 bitowej pochłania bardzo dużo czasu;
- jeszcze efektywniejsze jest wykorzystanie sprzętowego SPI procesora do komunikacji z DDS-em.