Odpowiedz 
 
Ocena wątku:
  • 3 Głosów - 3.33 Średnio
  • 1
  • 2
  • 3
  • 4
  • 5
Programowanie w języku C w środowisku AVR Studio4
SP4EJT Offline
Marcin
****

Liczba postów: 340
Dołączył: 06-05-2011
Post: #111
RE: Programowanie w języku C w środowisku AVR Studio4
Dobra, skoro SQ6OXK nie ma czasu to ja zacznę wałkować temat syntezy DDS....
Zainteresowani tym tematem koniecznie muszą ściągnąć sobie pdf o AD9951, w google pełno tego.
Dam wam niedługo przepis na płytkę wraz ze spisem części... ale możeci zrobić obojętnie jaką znalezioną w internecie z układem AD9951 - ważne tak na prawdę aby była mozliwość podłaczenia wszystkich wyprowadzeń DDSa o których mowa niżej do naszej płyty ewaluacyjnej - a każda płytka ma taką możliwość Smile
Będziemy wysyłać do układu AD9951 instrukcje wykorzystując wyprowadzenia, po stronie DDS:
1. RESET
2. CS
3. SCLK
4. SDIO
5. I/O UPDATE
Zaznaczyłem je na poniższym rysunku dwoma kolorami - zielone są mało istotne:
- RESET można pominąć bo po włączeniu układu jest jakby po resecie - podanie przez chwile stanu wysokiego powoduje zresetowanie układu, a potem przez cały czas pracy ma być stan niski
- CS ( chip select - po polskiemu "wybór cipu" Smile ) - jeśli jest w stanie wysokim to układ olewa wszystko co mu próbujemy przekazać. CS można na stałe podłaczyć do masy jeżeli nie chcemy sterować dwiema lub więcej DDSami.
İmage
I/O UPDATE to wyprowadzenie, które służy do tego aby wprowadzona przez nas zmiana częstotliwości przyniosła efekt. Jeżeli wyślemy rozkaz zmiany częstotliwości a nie wyślemy impulsu na to wyprowadzenie częstotliwość się nie zmieni.
SCLK to wyprowadzenie taktujące naszą szeregową szynę danych pomiędzy atmega i AD9951. W "rytm" zmian tego sygnału wysyłamy polecenia i dane do układu, poprzed wyprowadzenie SDIO, według przepisu podanego poniżej. Poniższy przykład obrazuje jak wysłać do AD9951 jeden bajt, który reprezentuje adres rejestru do którego chcemy zapisać dane, a po nim jeden bajt danych - czyli zawartość tego rejestru.
İmage
Teraz opisze jak za pomoca dwóch kabli ( SDIO i SCLK ) wysłać jeden bajt...
Przypuśćmy że SCLK naszego DDSa będzie podłączone do wyprowadzenia B0, a SDIO podłączone jest do B1.
Chcemy wysłać bajt który jest wartością zmiennej bobo typu unsigned char (czyli ośmiobitowa bez znaku) ... będziemy wysyłać bit po bicie zmiennej bobo, począwszy od najstarszego bitu, skończywszy na najmłodszym. Acha, DDS "łyka" bit danych/instrukcji przy zboczu narastającym sygnały SCLK - czyli w momencie gdy stan na SCLK przechodzi z niskiego na wysoki.

Kod:
for(i=0; i<8; i+=1)     // pętla wykonująca polecenia w nawiasie klamrowym 8 razy - czyli tyle ile bitów ma bajt
{
   if(bobo&0b10000000)    // jeżeli najstarszy bit zmiennej bobo jest równy 1 to ..
   { PORTB = PORTB|0b00000010; }   // SDIO (PB1) będzie miał stan wysoki
   else         // w przeciwnym wypadku
   { PORTB = PORTB&(~0b00000010); }   // SDIO bęzie miał stan niski
   PORTB = PORTB|0b00000001;   // SCLK (PB0) przechodzi w stan wysoki - teraz DDS "zapamiętuje" jaki stan jest na SDIO
   PORTB = PORTB&(~0b00000001);  /// SCLK przechodzi w stan niski
   bobo = bobo << 1;      // bity zmiennej bobo przesuwane są o jedno miejsce w lewo czyli w stronę najstarszego bitu
}
Nie pamiętam czy opisywałem przesunięcie bitowe a więc opowiem o tym :
przypuśćmy że nasza zmienna bobo ma wartość
0b10001001, gdy poddamy ją przesunięciu jednobitowemu w lewo (czyli bobo = bobo << 1; to będzie miała wartość
0b00010010, znowu przesuwamy w lewo o jedno miejsce, i po tej operacji ma wartość
0b00100100, znowu ..
0b01001000, znowu ...
0b10010000, znowu ...
0b00100000, znowu ...
0b01000000, i ostatni raz ...
0b10000000. Zwróciliście pewnie uwagę, że przy przesuwaniu wartość uzupełnia się zerami (po prawej stronie zapisu)
Przesunięcie o dwa miejsca zapisujemy bobo = bobo << 2; i działa tak:
0b10001001 - wartość przed przesunięciem
0b00100100 - wartość po przesunięciu. Przesunięcie o 3, 4, itd ... chyba już będzie zrozumiałe.
Przy przesunięciu w prawo np. bobo = bobo >> 1; działa to analogicznie w przypadku zmiennych "unsigned" czyli bez znaku.
Jeżeli mamy do czynienia z typem zmiennej signed (ze znakiem) to przy przesuwaniu w prawo jej wartość uzupełnia się jedynkami (z lewej strony). Przeanalizujcie ten kod zerkając co i raz na rysunek z ilustracja przebiegu sygnałów CS SCLK SDIO, który wkleiłem w tym poście, wyżej (CS na razie nie ważny)
Studiując pdf o AD9951 zobaczycie tabelą z adresami rejestrów... najczęściej będziemy używać rejestru "Frequency Tuning Word", który jak widać w tej tabeli, ma adres o wartości 0x04 czyli 0b00000100 lub poprostu 4.
Zatem żeby zmienić częstotliwość trzeba najpierw wysłać bajt o wartości 0x04 do DDSa, który mówi za chwile będę przesyłać wartość częstotliwości. Po tym nastąpić powinno wysłanie 4 bajtów (czyli 32 bitów) zawierających "słowo z wartością częstotliwości" jaką chcemy wygenerować. Zatem typ zmiennej określającej częstotliwość musi być 32 bitowy bez znaku (bo ujemnych częstotliwości raczej nie będziemy wysyłać) czyli unsigned long int... to będzie ta zmienna z programu wyświetlającego częstotliwość, który już mamy zrobiony, czyli frequency
Teraz zajmiemy się problemem przesłania tego "słowa określającego częstotliwość". Będzie to kod bardzo podobny do tego, którym wysyłaliśmy bajt bobo do DDSa, dodam jednak sygnał I/O UPDATE który będzie w naszych rozważaniach podłączony do PB2.
Poczytajcie w pdf-ie o AD9951 jeśli chcecie znać szczegóły - mi brakuje teraz czasu na wszystkie wyjaśnienia, wkleję wam tylko rysunek z którego coś można zakumać. İmage
Na razie kod bez sygnału I/O UPDATE
Kod:
for(i=0; i<32; i+=1)     // pętla wykonująca polecenia 32 razy - czyli tyle ile bitów ma "słowo częstotliwości"
{
   if(frequency&0b10000000000000000000000000000000)    // jeżeli najstarszy bit zmiennej frequency jest równy 1 to ..
   { PORTB = PORTB|0b00000010; }   // SDIO (PB1) będzie miał stan wysoki
   else         // w przeciwnym wypadku
   { PORTB = PORTB&(~0b00000010); }   // SDIO bęzie miał stan niski
   PORTB = PORTB|0b00000001;   // SCLK (PB0) przechodzi w stan wysoki - teraz DDS "zapamiętuje" jaki stan jest na SDIO
   PORTB = PORTB&(~0b00000001);  /// SCLK przechodzi w stan niski
   frequency = frequency << 1;      // bity zmiennej frequency przesuwane są o jedno miejsce w lewo
}
Teraz dodam sygnał I/O UPDATE...
Kod:
for(i=0; i<32; i+=1)     // pętla wykonująca polecenia 32 razy - czyli tyle ile bitów ma "słowo częstotliwości"
{
   if(frequency&0b10000000000000000000000000000000)    
   { PORTB = PORTB|0b00000010; }  
   else        
   { PORTB = PORTB&(~0b00000010); }  
   PORTB = PORTB|0b00000001;  
   PORTB = PORTB&(~0b00000001);  
   if(i=15)   { PORTB = PORTB&(~0b00000100); }    // I/O UPDATE w stan niski
   if(i=31)   { PORTB = PORTB|0b00000100; }   // I/O UPDATE w stan wysoki
   frequency = frequency << 1;    
}
Zapis tych 32 cyfr jest trochę kłopotliwy zatem w docelowym programie będzie zapis szesnastkowy czyli
if(frequency&0b10000000000000000000000000000000) zamienie na if(frequency&0x8000)
Czekam na pytania .... na następnej lekcji będzie inicjacja DDSa a po niej będzie program docelowy i już gotowy do tego by samemu zrobić syntezę DDS !!
(Ten post był ostatnio modyfikowany: 15-02-2012 16:15 przez SP4EJT.)
15-02-2012 16:13
Odwiedź stronę użytkownika Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
Odpowiedz 


Wiadomości w tym wątku
RE: Programowanie w języku C w środowisku AVR Studio4 - SP4EJT - 15-02-2012 16:13

Skocz do:


Użytkownicy przeglądający ten wątek: 4 gości