HomeMade

Pełna wersja: Synteza na AT89C51 i AD9835
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Czołem! Piszę właśnie program do syntezy DDS na AT89C51 i syntezerze AD9835 i mam problem jak napisać jakiś elegancki kod w C wykonujący równanie REG=(FREQ*2^32)/FOSC korzystający tylko ze zmiennych całkowitych 32 bitowych bez znaku (unsigned int). Czy ktoś z was może robił już coś takiego i byłby mi w stanie pomóc? Oczywiście jak tylko skończę pisać kod znajdzie się on tutaj w całości wraz ze schematami Big Grin
Jakiś czas temu było to już rozważane - zobacz http://sp-hm.pl/thread-1161-page-13.html
AT89C51 ma tylko 128 bajtów RAMu, samo dzielenie zabierze 16 już bajtów.
Brak EEPROMu, nie będzie gdzie zapisać kalibracji zegara.
Dzięki!, EEPROM można dodać zewnętrzny tylko z RAMem będzie problem :/ Jeśli mimo prób rzeczywiście nie da rady na '51 to spróbuję na PICu.
EDIT #2: Obliczenia są złe, wyjaśnienie w poście poniżej.

Jeśli bardzo chcesz trzymać się czterech bajtów, a kilka herców nie zrobi Ci różnicy to możesz skorzystać z takiej (brzydkiej, ale działającej) metody dla słabych mikrokontrolerów (przyjmuję f. osc = 125MHz):

Zmiana o 1Hz = (1/125000000)*2³² ~= 34.359738368 bity - magiczna stała

Zakładając że chcemy VFO nastroić na 14230.5 kHz, liczymy:

Kod:
reg = 14230500 * 34 + (14230500 * 35)/100 + (14230500 * 97)/10000 + (14230500 * 33)/1000000
reg == 488956179
(488956179/2³²) * 125000000 == 14230497.73 [Hz]
Tracimy więc ok. 2,3 Hz przy 14 MHz; dla 29,620 MHz analogicznie:

Kod:
>>> f=29620000
>>> reg = f * 34 + (f * 35)/100 + (f * 97)/10000 + (f * 33)/1000000
>>> 29620000-(reg/2**32.0)*125000000
Tracimy ~4.64 [Hz], co jest wartością zdecydowanie mniejszą niż dryft częstotliwościowy syntez AD i łatwo kompensowalną (dodając ~1.55Hz na każde 10MHz trafiamy zawsze z dokładnością +/- 1Hz.

Dla założonych parametrów i częstotliwości z zakresu KF nie wyskoczymy poza 32 bity, gdyż 30000000 * 99 / 2^32 < 1.

Piękne to nie jest, ale jak inaczej nie można.. Smile

EDIT: Widzę, że dla AD9835 zegar wynosi zazwyczaj 50MHz. Błąd będzie więc mniejszy niż zaprezentowany.
Na swój sposób ładne Tongue Dzięki wielkie! Jak tylko znajdę trochę więcej czasu to się za to zabiorę.
Spojrzałem jeszcze raz na swój post i widzę że pomyliłem się w numerkach - metoda jest dobra. Ostatnie mnożenie powinno być razy 38 a nie razy 33. Błąd na 30MHz wyniesie wtedy ~0.32 Hz. 4 mnożenia, 3 dzielenia, 3 sumy.
Też zauważyłem ale i tak przeliczyłem to dla generatora 50MHz.
Przetestowałem kod na Arduino Nano i AD9850 - działa bezproblemowo, na 30MHz ma niecałe 0.1Hz odchyłki. Szybsze niż dzielenie double'i/floatów - jeśli komuś na szybkości zależy. Należy pamiętać o typie zmiennych - 32-bitowe unsigned.
Kod:
uint32_t reg = frequency * 34 + (frequency * 35)/100 + (frequency * 97)/10000 + (frequency * 38)/1000000;
Przekierowanie