instrukcja - Politechnika Warszawska

Transkrypt

instrukcja - Politechnika Warszawska
Politechnika Warszawska
Wydział Elektryczny
Laboratorium Programowania urządzeń mikroprocesorowych
automatyki elektroenergetycznej
Skrypt do ćwiczenia M.35
Implementacja algorytmów zabezpieczeniowych na procesorze DSP –
cz.1 (procesor stałoprzecinkowy ADSP 2181).
1
Implementacja algorytmów zabezpieczeniowych na
procesorze DSP - cz. 1 /procesor stałoprzecinkowy/
Opracowali:
Krzysztof Aniołek
Andrzej Bałazy
Ryszard Kowalik
1. Cel i zakres ćwiczenia
Celem ćwiczenia jest poznanie budowy i działania przykładowego procesora sygnałowego DSP,
stałoprzecinkowego oraz sposobu tworzenia i uruchamiania programów, realizujących podstawowe
algorytmy zabezpieczeniowe na sterowniku mikroprocesorowym, zbudowanym w oparciu o taki
procesor.
2. Wprowadzenie
Urządzenia Automatyki Zabezpieczeniowej od kilkunastu lat są konstruowane w oparciu o technikę
cyfrową. Ten sposób budowy powoduje, ze urządzenia charakteryzują się cennymi właściwościami,
takimi jak:
- komunikowanie się z innymi urządzeniami cyfrowymi
- pamięć o dużej pojemności
- możliwość realizacji złożonych algorytmów w zakresie przetwarzania sygnałów
- możliwość łatwego samo-testowania pozwalająca zbadać własną sprawność układu (co jest
szczególnie ważne dla zabezpieczeń)
- integracja w struktury, które przyczyniają się do znacznego ograniczenia okablowania wtórnego
w stacjach elektroenergetycznych
- redukcja kosztów sprzętu mikroprocesorowego
- duża szybkość działania
Wśród wielu procesorów stosowanych obecnie w technice zabezpieczeniowej szczególną rolę zajęły
procesory sygnałowe DSP (Digital Signal Procesor). Charakteryzują się one ogromną szybkością
działania, przez co często są stosowane w najnowszych zabezpieczeniach czołowych firm.
3. Budowa stanowiska laboratoryjnego
3.1. Opis elementów, z których składa się stanowisko laboratoryjne
Do budowy stanowiska laboratoryjnego wykorzystano zestaw szkoleniowy oparty o procesor ADSP
2181 umieszczony na płytce EZ-KIT Lite. Zawiera on, oprócz procesora, układ przetwornika A/C i C/A
(kodeka) wraz z układami liniowymi umożliwiającymi wprowadzenie i wyprowadzenie sygnałów
analogowych oraz układy konwerterów TTL/RS232 pozwalające na wymianę informacji przez łącze
szeregowe z komputerem klasy PC.
Do zestawu szkoleniowego ADSP1281 dołączono wymuszalnik, którego zadaniem jest wytworzenie
sygnałów analogowych i dwustanowych symulujących obiekt poddawany obserwacji. W tym celu do
wejść analogowych modułu DSP podłączono dwukanałowy symulator przebiegów analogowych,
wyposażony w generator przebiegu sinusoidalnego o częstotliwości 50Hz z możliwością regulacji
amplitudy oraz fazy, a do wejść i wyjść dwustanowych wymuszalnik sygnałów dwustanowych
umożliwiający zarówno zadawanie stanu sygnałom dwustanowym za pomoca przełączników jak i
obserwację stanu wyjść dwustanowych zestawu ADSP za pomocą diod LED. Źródłem sygnałów
analogowych w stanowisku laboratoryjnym może być również
generator z możliwością regulowania kształtu i częstotliwości przebiegu analogowego. Wyposażenie
stanowiska stanowią również: czterokanałowy oscyloskop pozwalający na obserwacje przebiegów
sygnałów analogowych i dwustanowych, zasilacz modułu DPS oraz komputer klasy PC z systemem
2
Windows i oprogramowaniem potrzebnym do pisania, uruchamiania i przesyłania kodu programu z
komputera do modułu DSP.
Budowa stanowiska laboratoryjnego przedstawiona została na rysunku 1 a jego schemat blokowy na
rysunku 2.
Moduł z procesorem ADSP2181 zasilany jest napięciem 9V DC dostarczonym z zewnętrznego
zasilacza, do modułu ADSP podłączony jest za pomocą interfejsu RS232 komputer PC. Wymiana
informacji pomiędzy modułem ADSP a wymuszalnikiem odbywa się za pomocą taśmy 50-pinowej.
Wymuszalnik przystosowany jest do połączenia z zewnętrznym generatorem oraz oscyloskopem.
Wymuszalnik (układ sterujący) składa się z: symulatora dwustanowych sygnałów wejściowych
procesora DSP, układu wizualizującego stany wyjść dwustanowych procesora DSP oraz generatora
przebiegu 50Hz wraz z przesuwnikiem fazowym. Sygnały wchodzące na wejścia dwustanowe procesora
(FL5..FL8) są generowane poprzez cztery przełączniki podające napięcie +5V. Nad przełącznikami, na
przedniej stronie układu wymuszającego znajdują się cztery diody LED, na których odwzorowane są
sygnały wyjść dwustanowych (FL1..FL4) procesora.
COM
RS232
PC
Taśma
9V
P3
J3
J4
DSP
moduł z
procesorem DSP
oscyloskop
czterokanałowy
generator
off
on
off
on
off
on
off
on
układ sterujący
(wej./wyj. dwustanowe, reg. gen. 50Hz, przes. fazowy)
Rysunek 1. Budowa stanowiska laboratoryjnego
3
L1
A
G1
C
Ampl.; f
0-100kHz
Generator
fi
A
Wej. kanał 1
A
Wej. kanał 2
C
Kodek
Ampl.
Układ
ster.
G2
A
C
50Hz
C
Ampl.
Łącze
szeregowe
FL1
FL2
FL3
FL4
R
Rdzeń
DSP 21xx
GND
FL5
FL6
FL7
FL8
Wej. kanał 3
Port SPORT0
Procesor DSP
/ADSP 2181/
Pamięć
RAM 48kB
/Program/
Pamięć
RAM 32 kB
/Dane/
Wej. kanał 4
Oscyloskop 4 kanałowy
Port SPORT1
5V
Układ sterujący
220Vac
Stab.
9V/5V
Pamięć
EPROM
Moduł z procesorem DSP
9V
Konwertery
TTL/RS232
Łącze RS232
/do komputera PC/
PC
Zasilacz
Rysunek 2. Schemat blokowy stanowiska laboratoryjnego
Analogowe sygnały wejściowe procesora powstają w generatorze przebiegu sinusoidalnego.
Regulację kąta i amplitud przebiegów umożliwiają trzy potencjometry obrotowe umieszczone na
pokrywie obudowy.
Wbudowany generator, nie jest jednak jedynym źródłem sygnałów analogowych. Istnieje także
możliwość uzyskania przebiegu analogowego z generatora zewnętrznego. Generator zewnętrzny
używany jest w trakcie badań procesora DSP do badania filtrów cyfrowych ze względu na możliwość
wytwarzania sygnałów o dużym przedziale częstotliwości. Wybór źródła sygnału (wewnętrzny generator
50Hz lub generator zewnętrzny) odbywa się poprzez przełącznik (L1) znajdujący się z tyłu obudowy.
Ostatnim z pięciu elementów stanowiska jest oscyloskop czterokanałowy. Służy on do obserwacji
sygnałów analogowych wchodzących oraz wychodzących z wejść oraz wyjść analogowych modułu DSP.
3.2. Opis budowy modułu EZ-KIT Lite
Podstawową częścią stanowiska laboratoryjnego jest moduł EZ-KIT Lite. Jego integralną częścią jest
procesor ADSP-2181, pełniący najważniejsze funkcje w układzie. Oprócz procesora DSP na płytce
modułu umieszczone są: przetwornik A/C i C/A nazywany kodekiem, pamięć EPROM oraz kilka złącz i
układów peryferyjnych takich jak wzmacniacze analogowe oraz konwerter TTl/RS232.
Poniżej przedstawione są charakterystyczne cechy części składowych modułu.
Parametry modułu:
Procesor
Przetwornik A/C i C/A
Wejścia analogowe
Wyjścia analogowe
Zasilanie
- ADSP-2181 KS-133 - częstotliwość pracy 33MHz przy
zew. generarze kwarcowym: 16.667 MHz
- kodek stereo AD1847
- 2 x 2Vac lub 2 x 20mVac
- 2 x 1Vac
- od 8 do 10Vdc / 300mA
Konstrukcja mechaniczna modułu pokazana jest na rysunku 3, na którym każdemu z elementów
przyporządkowano oznaczenia niezbędne do ich identyfikacji.
ADSP-2181 33 MIPS DSP
AD1847 Stereo
Złącze RS-232
Gniazdo EPROM
Przyciski
Diody sygnalizacyjne
Gniazdo zasilania
Złącza dodatkowe
- U3
- U7
- J3
- U2
- S1, S2
- D1, D2
- J4
- P2,P3
4
Zwory konfiguracyjne
Gniazda analogowe
- JP1, JP2
- J1, J2
P3
D2
Pin 1
J4
J3
U3
J2
ADSP-2181
Digital
Signal
Processor
P1
J1
U7
AD1847
Stereo
Codec
U2
JP2
Gniazdo EPROM
S1
MIC
S2
Pin 1
D1
Pin 1
P2
ADSP-2181
EZ-KIT LITE
JP1
RESET
INTERRUPT
FL1
Rysunek 3. Budowa modułu EZ-KIT Lite
Pamięć EPROM (27C010 - 256Kbajtów) jest podłączona do procesora poprzez port Byte DMA, który
może adresować do 32M bitów (4Mbajty) pamięci. Jej konfiguracja odbywa się za pomocą pinów JP1.
Ustawienie wszystkich parametrów pamięci następuje z chwilą zresetowania układu.
Do konwersji A/C i C/A wykorzystuje się 16-to bitowy kodek o nazwie Stereo Audio I/O AD1847
SoundPort Codec (U7), który jest połączony z procesorem DSP za pomocą portu szeregowego SPORT0.
Jako wejście sygnału analogowego wykorzystywane jest gniazdo typu jack (J1) 3.5mm. Jako wyjście
sygnału analogowego używane jest gniazdo typu jack o oznaczeniu J2. W stanowisku laboratoryjnym
sygnały analogowe są wprowadzane i wyprowadzane z modułu przez złącze P3. Do konfiguracji wejść
analogowych służy grupa sześciu pinów (JP2).
Do komunikacji z komputerem PC służy łącze o standardzie RS232 wyprowadzone na złącze żeńskie
(J3).
Do zasilania modułu wykorzystuje się zewnętrzny zasilacz o napięciu stałym 9V podłączonym przez
złącze (J4) wtyczką cylindryczną jack 5.5mm, w której centralny pin ma biegunowość ujemną (-),
natomiast jej część zewnętrzna dodatnią (+).
(P1) jest grupą szesnastu pinów, które można użyć do podłączenia procesora z in-circuit emulatorem
EZ-ICE (Pin 7 usunięto). Złącza (P2) i (P3) są pięćdziesięcio-pinowymi gniazdami umożliwiającymi
dostęp do sygnałów procesora. Można je wykorzystać do wyprowadzania sygnałów na zewnątrz układu,
sprawdzania działania lub rozbudowy modułu.
Przycisk o nazwie (S1) podaje sygnał Reset dla procesora DSP. Drugi z przycisków o nazwie (S2)
przekazuje do procesora DSP sygnał przerwania IRQE.
Moduł wyposażony jest standardowo w 2 diody świecące pokazujące stan jego pracy:
- (D1) - dioda o kolorze czerwonym pokazuje stan wyjścia o nazwie FL1 (flaga FL1). Istnieje
możliwość programowego kontrolowania jej stanu
- (D2) - dioda o kolorze zielonym informuje o obecności zasilania modułu.
W skład zestawu szkoleniowego, oprócz modułu EZ_KIT Lite, wchodzi także pakiet programów o
nazwie "ADSP-2181 Family development software", zawierający komplet narzędzi programowych
umożliwiający uruchomienie systemu mikroprocesorowego opartego o procesor ADSP2181. W skład
pakietu wchodzą następujące programy:
- "Builder System" - umożliwiający zdefiniowanie struktury budowanego systemu
- "Asembler" - pozwalający na skompilowanie programu napisanego w mnemonikach procesora
ADSP2181, do postaci kodu wynikowego
- "Linker" - łączący pliki wynikowe w plik wykonawczy, który można uruchomić w module EZKIT
- "Symulator" - umożliwiający wykonanie symulacji działania napisanego programu
5
- "PROM Spliter" generujący kod wykonawczy, który może być zapisane do pamięci EPROM.
3.3. Opis procesora ADSP-2181
3.3.1. Wstęp
ADSP-2181 jest mikrokomputerem jednoukładowym ukierunkowanym na przetwarzanie sygnałów
cyfrowych, czyli procesorem DSP od angielskiego skrótu "Digital Signal Procesor". Wyprodukowany
został w technologii CMOS 0.5µm i wykorzystując zegar 33MHz wykonuje każdą instrukcję w
pojedynczym cyklu procesora, tj. w czasie 30ns. Jest produkowany jest w obudowach TQFP i PQFP 128pinowych. (W module EZ-Kit Lite zastosowano procesor z obudowę PQFP.)
Struktura blokowa procesora została pokazana na rysunku 4:
Łączy ona bazową architekturę rodziny ADSP-21xx, na którą składają się:
- trzy jednostki obliczeniowe
- dwa generatory adresu danych
- generator adresu programu (program sequencer)
z dodatkowymi układami peryferyjnymi:
- dwoma portami szeregowymi
- 16-to bitowym wewnętrznym portem DMA
- bajtowym portem DMA
- programowalnym timerem
- portami wejścia-wyjścia
- kontrolerem przerwań oraz
- układem sterowania poborem mocy (Power Down)
- wewnętrzną pamięcią programu i pamięcią danych
Wymienione elementy spełniają w procesorze ADSP2181 następujące funkcje:
- trzy jednostki obliczeniowe - jednostki te przetwarzają bezpośrednio 16-to bitowe dane:
- ALU - odpowiada za wykonywanie standardowych operacji arytmetycznych i logicznych
- MAC multiplier/accumulator - wykonuje w jednym cyklu procesora operacje: mnożenia,
mnożenia/dodawania, mnożenia/odejmowania. Wynik obliczeń tych operacji może być
nawet 40-to bitowy
- SHIFTER - wykonuje logiczne oraz arytmetyczne przesunięcie, normalizację, denormalizację oraz wyprowadza wykładnik potęgi. Shifter może być użyty do sprawnego
implementowania obliczeń zmiennoprzecinkowych
- dwa generatory adresu danych - elementy te o nazwach DAG1 i DAG2, dostarczają adresy dla
równoczesnego pobrania argumentu z pamięci danych oraz z pamięci programu. Każdy układ
utrzymuje oraz aktualizuje cztery wskaźniki adresu
- generator adresu programu (program sequencer) - układ przy pomocy generatorów adresu danych
zapewnia sprawne dostarczenie argumentów operacji do jednostek obliczeniowych. Poza tym
inicjuje skoki warunkowe, wywołania podprogramów, oraz powroty z podprogramów w
pojedynczym cyklu rozkazowym. Dzięki niemu procesor ADSP-2181 wykonuje np. kod pętli
warunkowej bez żadnych sprecyzowanych instrukcji skoku
- dwa porty szeregowe - o nazwach SPORT0 i SPORT1 służą do komunikacji z innymi
urządzeniami. Umożliwiają uruchomienie mechanizmu buforowania transmisji szeregowej.
- 16-to bitowy wewnętrzny port DMA - o nazwie IDMA służy do połączenia procesora DSP z
zewnętrznym systemem mikroprocesorowym. Skład się on z 16 sygnałów danych/adresów oraz 5
sygnałów sterujących
- bajtowy port DMA (BDMA) - jest dwukierunkowym portem umożliwiającym adresowanie
pamięci zewnętrznej RAM oraz ROM do wielkości 4MB. Pozwala to na przechowywanie bardzo
dużych bloków danych
- programowalny timer - jest układem licznikowym umożliwiającym odliczanie czasu oraz
generację przerwań
- porty wejścia wyjścia - składa się na nie osiem programowalnych pinów wejścia/wyjścia, trzy
piny wyjściowe oraz dwa dodatkowe sygnały dostępne przy alternatywnej konfiguracja SPORT1
- kontroler przerwań - jest układem umożliwiającym sprawowanie nadzoru oraz podjęcie
właściwej reakcji na 11 różnych przerwań
6
- układ sterowania poborem mocy (Power Down) - służy do obniżenia poboru mocy procesora w
przypadku np. aplikacji o zasilaniu bateryjnym
- wewnętrzna pamięć programu i danych. - ten 80 kbajtowy obszar pamięci wewnętrznej (on-chip)
skonfigurowanej jako 48kB pamięci RAM programu oraz 32kB pamięci RAM danych umożliwia
sprawne wykonywanie programu oraz obliczeń.
DATA ADDRESS
GENERATORS
Generatory Adresu
Danych
DAG1
DAG2
PROGRAM
SEQUENCER
POWERDOWN
CONTROL
PROGRAMOWALNE
WE/WY
WEWNĘTRZNA PAMIĘĆ
FLAGI
PAMOIĘĆ
PROGRAMU
PAMOIĘĆ
DANYCH
BYTE DMA
CONTROLLER
ZEWNĘTRZNA
SZYNA
ADRESÓW
SZYNA ADRESÓW PAMIĘCI PROGRAMU
SZYNA ADRESÓW PAMIĘCI DANYCH
ZEWNĘTRZNA
SZYNA
DANYCH
SZYNA DANYCH PAMIĘCI PROGRAMU
SZYNA DANYCH PAMIĘCI DANYCH
JEDNOSTKI ARYTMETYCZNE
ALU
MAC
SHIFTER
PORTY SZEREGOWE
SPORT0
SPORT1
TIMER
WEWNĘTRZNY
PORT
DMA
SZYNA
DMA
Rdzeń budowy rodziny ADSP-2100
Rysunek 4. Budowa wewnętrzna procesora ADSP-2181
Elastyczna struktura oraz obszerny zestaw instrukcji pozwala procesorowi na wykonanie wielu
operacji równolegle. W jednym cyklu procesor może w związku z tym np.:
- generować nowe adresy programu
- pobierać nowe instrukcje
- wykonać jedno lub dwa przesłania danych
- modyfikować jeden lub dwa wskaźniki adresów danych
- wykonać operację obliczeniową.
Wykonanie powyższych operacji nie koliduje z pracą innymi czynnościami procesora, który może
równocześnie:
- otrzymywać oraz transmitować dane poprzez dwa porty szeregowe
- otrzymywać i/lub transmitować dane poprzez wewnętrzny port DMA
- otrzymywać i/lub transmitować dane poprzez port bajtowy DMA
- zmniejszać wartość timera.
Rysunek 5 pokazuje budowę procesora ADSP-2181 w sposób bardziej szczegółowy, pozwalający na
opisanie mechanizmów wymiany danych między jego elementami.
Jak widać wewnętrzna szyna wyniku (R) łączy jednostki obliczeniowe w taki sposób, że wyjście
dowolnej jednostki może być wejściem innej dowolnej jednostki w kolejnym cyklu.
Dwa generatory adresów danych DAG1 i DAG2 dostarczają adresy niezbędne do równoczesnego
pobrania argumentu z pamięci danych oraz z pamięci programu. Każdy układ DAG utrzymuje oraz
aktualizuje cztery wskaźniki adresu. Pojedynczy generator adresu danych (DAG) posiada trzy rejestry:
- (M) Modify
- (I) Index
- (L) Length.
Każdy z nich zawiera po cztery rejestry 14-to bitowe, które mogą być bezpośrednio czytane bądź
zapisywane na szynę DMD. Rejestr I (I0-I3 w generatorze DAG1, I4-I7 w generatorze DAG2) zawiera
aktualne adresy pamięci. Rejestr L (L0-L3 w generatorze DAG1, L4-L7 w generatorze DAG2) zawiera
długości buforów. Rejestr M (M0-M3 w generatorze DAG1, M4-M7 w generatorze DAG2) zawiera
wartość modyfikacji adresu. Generatory adresu umożliwiają dwa typy adresowania: adresowanie liniowe
7
i kołowe. Wartość rejestru L korespondująca z rejestrem I (np. L0 może korespondować z I0) decyduje,
który schemat adresowania zostanie użyty. Przy adresowaniu liniowym należy wyłączyć logikę modułu
poprzez ustawienie rejestru korespondującego L na wartość „0”. Przy adresowaniu buforu kołowego
rejestr L jest ustawiony na długość bufora różną od zera.
POWER
DOWN
CONTROL
LOGIC
INSTRUCTION
REGISTER
DAG1
Data
Address
Generator
#1
PROGRAM
SRAM
16K x 24
DAG1
Data
Address
Generator
#1
DATA
SRAM
16K x 24
BYTE
DMA
CONTROLLER
PROGRAM
SEQENCER
2
PROGRAMMABLE
I/O
8
3
FLAGS
14
MUX
14
SZYNA PMA
14
ZEWNĘTRZNA
SZYNA
ADRESU
SZYNA DMA
24
24
SZYNA PMD
BUS
EXCHANGE
16
MUX
ZEWNĘTRZNA
SZYNA
DANYCH
SZYNA DMD
COMPANDING
CIRCUITRY
INPUT REGS
INPUT REGS
INPUT REGS
ALU
MAC
SHIFTER
OUTPUT REGS
OUTPUT REGS
OUTPUT REGS
TRANSMIT REG
TRANSMIT REG
RECEIVE REG
RECEIVE REG
SERIAL
PORT0
SERIAL
PORT1
TIMER
16
INTERNAL
DMA
PORT
4
16
5
5
INTERRUPTS
SZYNA R
Rysunek 5. Budowa wewnętrzna procesora ADSP-2181
Sprawny transfer danych uzyskuje się, dzięki użyciu pięciu wewnętrznych szyn:
- szyny PMA Program Memory Address
- szyny PMD Program Memory Data
- szyny DMA Data Memory Address
- szyny DMD Data Memory Data
- szyny R Result.
Dwie szyny adresów PMA i DMA tworzą pojedynczą, multipleksowaną, zewnętrzna szynę adresową.
Dwie szyny danych PMD i DMD w podobny sposób tworzą pojedyncza, multipleksowaną, zewnętrzna
szynę danych.
Pamięć programu może przechowywać zarówno instrukcje jak i dane, pozwalając procesorowi ADSP2181 na pobranie dwu argumentów w pojedynczym cyklu: jeden z pamięci programu oraz jeden z
pamięci danych. ADSP-2181 może pobierać z pamięci programu w tym samym cyklu argument oraz
następną instrukcję. Pamięć programu stanowi przestrzeń o szerokości 24-bitów (trzech bajtów). ADSP2181 ma możliwość adresowania 16K słów wewnętrznej pamięci programu RAM, co pozwala na
dysponowanie pamięcią o wielkości 48Kbajty (3bajty x 16 x 1024bajty=48Kbajty).
Pamięć danych jest przestrzenią o szeroką 16 bitów, użytą do magazynowania danych oraz rejestrów
kontrolnych. ADSP-2181 ma możliwość adresowania 16k słów wewnętrznej pamięci danych lecz dla
użytkownika dostępnych jest 16352 słów, ponieważ ponieważ resztę pamięci zajmują 32 zmapowane
rejestry.
ADSP-2181 posiada 16-to bitowy port (IDMA) łączący szynę PMD z szyną DMD. Jest on
wykorzystywany do podłączania układów zewnętrznych. Port IDMA składa się z 16 pinów
danych/adresów oraz 5 pinów kontrolnych. Port IDMA umożliwia bezpośredni dostęp do pamięci
programu oraz danych RAM.
Sygnały pochodzące z nieużywanego portu IDMA są dostępne na złączu P3 modułu EZ-KIT.
Dwukierunkowy Port BDMA może bezpośrednio adresować do 4MB zewnętrznej pamięci RAM oraz
ROM wykorzystywanej do podręcznego przechowywania programu lub danych.
8
ADSP-2181 zawiera dwa szeregowe porty (SPORT0 i SPORT1). Szeregowy port SPORT0 służy do
przesyłania danych i komunikacji z kodekiem. Port SPORT1 służy opcjonalnie do wymiany danych z
głównym komputerem, lub może być skonfigurowany jako wejście i wyjście dwustanowe.
ADSP-2181 może odpowiadać na 11 źródeł przerwań, sześć zewnętrznych (jedna wyzwalana
zboczem, dwie poziomem oraz trzy z możliwością konfigurowania) oraz pięć wewnętrznych
generowanych poprzez:
- timer
- porty szeregowe (SPORTs)
- port Byte DMA oraz
- układy sterowania poborem mocy
- sygnał RESET
ADSP-2181 zapewnia 13 uniwersalnych bitów wejścia/wyjścia - flag. Osiem z nich można
zaprogramować dowolnie jako wejścia lub wyjścia. Trzy flagi są na stałe skonfigurowane jako wyjścia.
Dwie ostatnie flagi, z których jedna jest wejściem a druga wyjściem, są przypisane do portu SPORT1
W procesorze istnieje również programowalny timer generujący przerwania. Jest on zbudowany w
oparciu o 16-to bitowy rejestr zliczający (TCOUNT), którego wartość jest zmniejszana po każdych n
cyklach procesora, gdzie n jest wartością przechowywaną w 8 bitowym rejestrze (TSCALE). Kiedy
wartość rejestru licznika osiąga zero, generowana jest przerwanie, a do rejestru zliczającego wpisywana
jest powtórnie wartość z 16-to bitowego rejestru okresu (TPERIOD).
3.3.2. Rejestry
Na rysunku 6 pokazano wszystkie rejestry specjalne procesora ADSP-2181. Rejestry te mogą mieć
znaczenie bitowe lub mogą przechowywać wartości - liczby. Przykładowo: rejestr AX0 zawiera jeden z
operandów jednostki arytmetyczno-logicznej ALU, rejestr I4 przechowuje wartość adresu DAG2.
Rejestry bitowe składają się z bitów kontrolnych, pól, lub flag stanu. Na przykład:
- rejestr ASTAT zawiera flagi stanu operacji arytmetycznych
- bity w rejestrze DWAIT określają opóźnienie cyklu odczytu lub zapisu danych, dla różnych
zakresów adresów mapy pamięci
- rejestry PMOVLAY i DMOVLAY określają wielkość przestrzeni adresowej dla pamięci danych
oraz programu. (Rejestry te mogą być użyte w instrukcjach przesyłania danych.)
Niektóre rejestry są dostępne w obszarze pamięci danych. Są to:
- System Control Register
- DWAIT
- timer
- port IDMA
- port IDMA
- SPORT
9
PROGRAM
SRAM
16K x 24
PROGRAM SEQENCER
DAG2
I0
I1
I2
I3
M0
M1
M2
M3
SSTAT
SSTAT
IFC
CNTR
OWRCNTR
COUNT
STACK
4 x 14
IMASK
MSTAT
ASTAT
STATUS
STACK
12 x 25
DAG2
L0
L1
L2
L3
I4
I5
I6
I7
M4
M5
M6
M7
L4
L5
L6
L7
LOOP
STACK
4 x 18
PC
STACK
16 x 14
BYTE DMA
PORT
IDMA
PORT
BTYPE
BIAD
BEAD
BMPAGE
BDIR
BWCOUNT
PMOVLAY
DMOVLAY
0x3FFF
0x3FFE
DATA
SRAM
16K x 24
SYSTEM CONTROL
DM WAIT CONTROL
IDMAA
14
SZYNA PMA
14
SZYNA DMA
24
SZYNA PMD
PX
16
SZYNA DMD
AX0
AX1
AY0
AY1
MX0
ALU
AR
MX1
MY0
MY1
SI
MAC
AF
MR0
MR1
MR2
SE
SB
SHIFTER
MF
SR0
RX0
TX0
RX1
TX1
0x3FFA-0x3FF3
0x3FF2-0x3FEF
CONTROL REGISTERS
CONTROL REGISTERS
SR1
SPORT 0
SPORT 1
TIMER
FLAGS
0x3FFD
0x3FFC
0x3FFB
TPERIOD
TCOUNT
TSCALE
POWERDOWN
CONTROL
LOGIC
PROGRAMMABLE
I/O
Rysunek 6. Rejestry procesora ADSP-2181
Rejestry te położone są pod adresami pokazanymi w poniższej tabeli.
Nazwa rejestru
Sys_Crtl_Reg
Dm_Wait_Reg
Tperiod_Reg
Tcount_Reg
Tscale_Reg
Sport0_Rx_Words1
Sport0_Rx_Words0
Sport0_Tx_Words1
Sport0_Tx_Words0
Prog_Flag_Data
BDMA_Word_Count
BDMA_Control
Adres
0x3fff
0x3ffe
0x3ffd
0x3ffc
0x3ffb
0x3ffa
0x3ff9
0x3ff8
0x3ff7
0x3fe5
0x3fe4
0x3fe3
Nazwa rejestru
Sport0_Ctrl_Reg
Sport0_Sclkdiv
Sport0_Rfsdiv
Sport0_Autobuf_Ctrl
Sport1_Ctrl_Reg
Sport1_Sclkdiv
Sport1_Rfsdiv
Sport1_Autobuf_Ctrl
Prog_Flag_Comp_Sel_Ctrl
BDMA_External_Address
BDMA_Internal_Address
IDMA_Control
Adres
0x3ff6
0x3ff5
0x3ff4
0x3ff3
0x3ff2
0x3ff1
0x3ff0
0x3fef
0x3fe6
0x3fe2
0x3fe1
0x3fe0
Pokazane wartości rejestrów są wartościami obowiązującymi po zresetowaniu procesora.
3.3.4. Opis wybranych instrukcji procesora ADSP-2181
Instrukcje języka asemblera procesora ADSP-2181 mają formę prostych wyrażeń matematycznych.
Charakteryzują się następującymi cechami użytkowymi:
- algebraiczną składnią, która eliminuję potrzebę zapamiętywania mnemoników asemblera.
Przykładowo typowa instrukcja dodawania arytmetycznego: przypomina proste równanie
AR=AX0+AY0
- kodowaniem instrukcji w postaci pojedynczego, 24 bitowego słowa, wykonywanego w
pojedynczym cyklu procesora
- kompatybilnością z kodem wynikowym innych członków rodziny ADSP 21xx
- obecnością wielu instrukcji warunkowych, wykonywanych w tym samym cyklu maszynowym co
reszta instrukcji. (Warunek może być sprawdzony dla instrukcji: skoku, wywołania procedury,
powrotu z procedury lub instrukcji arytmetycznych.)
10
- jednoczesnym wykonywaniem instrukcji arytmetycznych, wykorzystujących do dwóch odczytów
oraz jednego zapisu w przestrzeni pamięci procesora, podczas pojedynczego cyklu
maszynowego.
Instrukcje arytmetyczne ALU
- dodawanie/dodawanie z przeniesieniem
[IF cond ]
AR
AF
=
xop
+
yop
C
yop+C
constant
;
yop
C
yop+C-1
constant
;
- odejmowanie/odejmowanie z pożyczką
[IF cond ]
AR
AF
=
xop
-
gdzie
xop: AX0, AX1, AR, MR0, MR1, MR2, SR0, SR1
yop: AY0, AY1, AF
constant: 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32767, -2,
-3, -5, -9, -17, -33, -65, -129, -257, -513, -1025, -2049, -4097, -8193, -1638, -32768
cond:
- EQ - równe zero
- NE - nie równe zero
- LT - mniejsze od zera
- GE - większe, równe zero
- LE - mniejsze, równe zero
- GT - większe od zera
- operacje logiczne AND, OR, XOR
[IF cond ]
AR
AF
=
yop
AND
OR
XOR
xop
;
- czyszczenie/porównanie
[IF cond ]
AR
AF
= PASS
Xop
Yop
constant
;
gdzie
xop: AX0, AX1, AR, MR0, MR1, MR2, SR0, SR1
yop: AY0, AY1, AF
constant: 0, 1, 2, 3, 4, 5, 7, 8, 9, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127,128, 129, 255, 256,
257, 511, 512, 513, 1023, 1024, 1025, 2047, 2048, 2049, 4095, 4096, 4097, 8191,
8192, 8093, 16383, 16384, 16385, 32766, 32767, -1, -2, -3, -4 -5, -6, -8, -9, -10, -16,
-17, -18, -32, -33, -34, -64, -65, -66, -128, -129, -130, -256, -257, -258, -512, -513, 514, -1024, -1025, -1026, -2048, -2049, -2050, -4096, -4097, -4098, -8192, -8193, 8194, -16384, -16385, -16386, -32767, -32768.
- Increment (zwiększanie o 1)
[IF cond ]
AR
AF
=
yop+1
- Decrement (zmniejszanie o1)
[IF cond ]
AR
AF
=
yop-1
gdzie: yop: AY0, AY1, AF
Instrukcje arytmetyczne MAC
- mnożenie
[IF cond ]
MR
MF
= xop
* yop
xop
(SS)
(SU)
11
;
(US)
(UU)
(RND)
- mnożenie/dodawanie
[IF cond ]
MR
MF
= MR
+ xop
* yop
xop
(SS)
(SU)
(US)
(UU)
(RND)
;
= MR
-
* yop
xop
(SS)
(SU)
(US)
(UU)
(RND)
;
- mnożenie/odejmowanie
[IF cond ]
MR
MF
xop
Instrukcje przesunięcia
- przesunięcie arytmetyczne
[IF cond ]
SR
= [SR OR]
ASHIFT
xop
(HI)
(LO)
;
= [SR OR]
LSHIFT
xop
(HI)
(LO)
;
- przesunięcie logiczne
[IF cond ]
SR
gdzie:
(HI) - przesunięcie do rejestru SR1
(LO) - przesunięcie do rejestru SR0
Instrukcje przesyłania danych
- przesył z rejestru do rejestru
reg = reg;
- przesył danej do rejestru
reg = <data>;
- przesył danej do rejestru danych
dreg= <data>;
- przesył z pamięci danych do rejestru (adres bezpośredni)
reg = DM(<data>);
- przesył z pamięci danych do rejestru danych(adres niebezpośredni)
dreg
= DM
(
I0
I1
I2
I3
,
,
,
,
M0
M1
M2
M3
I4
I5
I6
I7
,
,
,
,
M4
M5
M6
M7
);
- przesył z pamięci programu do rejestru danych(adres pośredni)
dreg = PM
(
I4
I5
I6
I7
,
M4
M5
M6
M7
);
- przesył z rejestru do pamięci danych (adresowanie bezpośrednie)
DM(<addr>) = reg;
- przesył z rejestru danych do pamięci danych (adresowanie pośrednie)
DM
(
I0
I1
I2
I3
,
,
,
,
M0
M1
M2
M3
);
= dreg ;
12
I4
I5
I6
I7
,
,
,
M4
M5
M6
M7
- przesył z rejestru danych do pamięci programu (adresowanie pośrednie)
DM
(
I4
I5
I6
I7
,
,
,
,
M4
M5
M6
M7
);
= dreg ;
Instrukcje sterujące wykonywaniem programu
- instrukcja skoku
[IF cond ] JUMP= <addr>;
- powrót z podprogramu standardowego
[IF cond ] RTS;
- powrót z podprogramu obsługi przerwań
[IF cond ] RTI;
- wprowadzenie procesora w stan zmniejszonego poboru mocy - zmniejszenie szybkości procesora
IDLE[(n)];
Instrukcje sterujące bitami procesora
- przełączenie wyjścia dwustanowego
[IF cond ]
TOGGLE
RESET
SET
= FLAG_OUT
FL0
FL1
FL2
;
- ustawienie bitów rejestrów MSTAT
ENA SEC_REG
DIS BIT_REV
4. Opis oprogramowania użytego w stanowisku laboratoryjnym
4.1. Wstęp
Elementem niezbędnym do prawidłowego funkcjonowania stanowiska, bez którego sprzęt staje się
bezużyteczny, jest oprogramowanie.
Umożliwia ono wykonywanie ćwiczenia, testowanie i prezentacja możliwości procesora, a przede
wszystkim realizację funkcji zabezpieczeniowych. Całość oprogramowania składa się z trzech
programów: Asembler, Host program oraz MathCad, w których funkcjonują stworzone specjalnie dla
laboratorium aplikacje użytkowe.
Mają one za zadanie:
- symulację pracy procesora
- komunikację z procesorem
- generację współczynników filtru
- przetwarzanie współczynników filtru do formatu wymaganego przez asembler procesora
- stworzenie środowiska do funkcjonowania programów napisanych dla stanowiska.
W celu poprawnego działania programów kompilatora i symulatora niezbędne jest utworzenie w
systemie zmiennej o nazwie ADI_DSP oraz odpowiedniej ścieżki dostępu. Oba polecenie w postaci:
SET ADI_DSP=C:\ADI_DSP
Path c:\ADI_DSP\21XX\BIN
zostały wpisane do pliku AUTOEXEC.BAT.
4.2. Asemblacja i linkowanie
Po napisaniu programu w postaci źródłowej, czyli w języku asembler procesora ADSP 2181 należy
ten program zamienić na postać binarną, możliwą do wykonania przez układ procesora. W tym celu
należy poddać program asemblacji oraz linkowaniu.
13
Program źródłowy powinien mieć rozszerzenie: .DSP. Asembler zamienia kod źródłowy programu na
postać binarną, w części skompilowaną. Asembler uruchamiany jest komendą
asm21 mój_prog -2181
gdzie: mój_prog jest nazwą pliku.
Tworzy on plik kodu wynikowego z rozszerzeniem .OBJ. Program Asemblera ma wiele opcji, które
można wykorzystać. Pełna lista opcji jest wyświetlana w przypadku podania komendy asm21. Użyteczną
opcją jest wykonanie kompilacji z listingiem , co umożliwia parametr „L” np.:
asm21 mój_prog -2181 -L
Pliki przetworzone przez asembler, można następnie zlinkować, poleceniem
ld21 mój_prog -a adsp2181 -e mój_prog
Program linkera pozwala na wprowadzenie do kodu powstałego w czasie asemblacji konkretnych
adresów zamiennych oraz procedur. Działanie to tworzy plik wykonawczy, możliwy do wykonania przez
procesor DSP 2181. Zbiór ten nosi nazwę pliku źródłowego z rozszerzeniem .EXE. Podobnie jak w
przypadku asemblera lista dostępnych opcji linkera jest wyświetlana w przypadku podania komendy
ld21.
Przyspieszenie i ułatwienie powyższych dwu operacji, jest możliwe poprzez stworzenie pliku
wsadowego o rozszerzeniu BAT, łączącego wszystkie niezbędne polecenia. Poniżej pokazano zawartość
przykładowego liku o nazwie DEMO.BAT.
asm21 demo -2181
ld21 demo -a ezkit_lt -e demo -x -g
sim2181 -a ezkit_lt -e demo
4.3. Symulator
Symulator to program demonstrujący pracę i możliwości procesora DSP. Poprzez prezentację
poszczególnych procedur asemblera, zmian zawartości rejestrów i komórek pamięci, pozwala na szybkie
zrozumienie zasady działania funkcji i budowy tego procesora.
Symulator pozwala na testowanie napisanego programu bez użycia sprzętu. Ten etap pracy pozwala
na sprawdzenie prawidłowego działania programu przy wyeliminowaniu ewentualnych błędów
sprzętowych.
Obsługa symulatora odbywa się tylko i wyłącznie za pomocą myszki.
Rysunek 7. Widok okna symulatora
Łatwa obsługa rozwijalnego menu skraca czas wyszukiwania potrzebnych komend i danych. Pozwala
obserwować zmiany zawartości rejestrów w poszczególnych taktach DSP. Daje możliwość
14
skonfigurowania edytowanych na ekranie elementów, sprawdzenia danego kroku oraz wpisania
określonej wartości do rejestru.
Dzięki wizualizacji procesów zachodzących w procesorze, które towarzyszą pracy danego programu,
użytkownik może śledzić krok po kroku działania DSP i sprawdzić poprawność napisanej aplikacji.
Poniżej przedstawiono sposób zastosowania symulatora.
Symulator jest uruchamiany komendą :
sim2181.exe
W celu uruchomienia w symulatorze konkretnego programu należy wpisać komendę, która ułatwi
rozpoczęcie pracy:
sim2181 -a adsp2181 -e nazwa_programu
Aby sprawdzić działanie programu w symulatorze, program ten musi być wcześniej poddany
linkowaniu.
Menu Register i Memory umożliwiają pokazanie zawartości rejestrów i pamięci, których zawartość
zmienia się w trakcie wykonywania poleceń. Kolejne linie programu wykonywane są po naciśnięciu
klawisza „F-10”.
W menu Execution opcja step”n”Times umożliwia wykonanie programu w dowolnej ilości „n”
kroków. Wyjście z symulatora za pomocą opcji „Exit” powoduje zachowanie ostatniego ustawienia ikon.
Natomiast wyjście poprzez wybór opcji Quit powoduje anulowanie ostatnio wykonanych zmian.
4.4. Uruchomienie programu wynikowego w środowisku Windows
EZ-KIT Lite Monitor jest programem pracującym w środowisku Windows, który służy do
komunikacji z modułem procesora ADSP-2181. Program ten przesyła poprzez łącze RS-232 kod
skompilowanego programu, który ma zostać uruchomiony. W celu załadowania programu
(skompilowanego do postaci wynikowego zbioru o rozszerzeniu EXE) należy wybrać opcję "Loading"
oraz podopcję "Download User program and Go" lub nacisnąć "^L". Przed uruchomieniem transferu
danych należy wykonać reser modułu.
4.5. Program Mathcad
Program Mathcad jest używany do obliczania współczynników filtrów cyfrowych wykorzystywanych
w jednym z przykładowych programów. Generuje on współczynniki filtrów dolno i górno przepustowych
lub pasmowozaporowych, dowolnego rzędu, o skończonej lub nieskończonej odpowiedzi impulsowej. W
celu utworzenia zbioru z współczynnikami odpowiedniego filtru należy uruchomić program MATHCAD
oraz wczytać właściwy plik dokonujący obliczeń. W przypadku filtru:
- dolnoprzepustowego o skończonej odpowiedzi impulsowej:
zbiór wykonujący obliczenia współczynników filtru:
FIL_DFIR.MCD
zbiór z współczynnikami filtru:
WSP_D.DAT
- górnoprzepustowego o skończonej odpowiedzi impulsowej:
zbiór wykonujący obliczenia współczynników filtru:
FIL_GFIR.MCD
zbiór z współczynnikami filtru:
WSP_G.DAT
- pasmowozaporowego o skończonej odpowiedzi impulsowej:
zbiór wykonujący obliczenia współczynników filtru:
FIL_PFIR.MCD
zbiór z współczynnikami filtru:
WSP_P.DAT
- dolnoprzepustowego o nieskończonej odpowiedzi impulsowej:
zbiór wykonujący obliczenia współczynników filtru:
FIL_DFII2.MCD
zbiory z współczynnikami filtru:
WSP_DIA.DAT
WSP_DIB.DAT
- górnoprzepustowego o nieskończonej odpowiedzi impulsowej:
zbiór wykonujący obliczenia współczynników filtru:
FIL_GFII2.MCD
zbióry z współczynnikami filtru:
WSP_GIA.DAT
WSP_GIB.DAT
- pasmowozaporowego o nieskończonej odpowiedzi impulsowej:
zbiór wykonujący obliczenia współczynników filtru:
FIL_PFII2.MCD
15
zbióry z współczynnikami filtru:
WSP_ZIA.DAT
WSP_ZIB.DAT
W przypadku filtrów o skończonej odpowiedzi impulsowej, wybór rzędu filtru następuje przez
podanie parametru N, a częstotliwość graniczna jest określana przez współczynnik Fg. Dla filtrów o
skończonej odpowiedzi impulsowej właściwe wartości współczynników należy obliczyć iteracyjnie
zmieniając częstotliwość dopasowywaną filtru o symbolu Fg w taki sposób, aby wyliczany moduł
wzmocnienia dla właściwej częstotliwości granicznej o symbolu Fg1 przyjął wartość docelowego
wzmocnienia ok. 0.7071.
Na rysunku 8 przedstawiono wygląd początku przykładowego pliku wyliczającego współczynniki
filtru, otwartego w programie Mathcad z widocznymi charakterystycznymi parametrami: rzędem filtru
oraz częstotliwością graniczną. Na rysunku 9 pokazano dalszy fragment tego samego pliku z widoczną
wyliczoną wartością wzmocnienia dla częstotliwości granicznej oraz charakterystyką amplitudową filtru.
Rysunek 8. Widok okna programu Mathcad
Współczynniki filtrów w celu dostosowania do poziomu i formatu użytecznego dla asemblera
procesora przed zapisem do zbioru mnoży się, przez 2^15, co powoduje, że zawierają się one w
granicach od -32768 do 32768.
16
wyliczana
wartość wzmocnienia
dla docelowej częstotliwości
Rysunek 9. Widok fragmentu pliku weryfikującego współczynniki filtru w programie Mathcad
Ponieważ asembler procesora DSP 2181 jest w stanie odczytać z pliku współczynniki w systemie
szesnastkowym, niezbędne jest ich przetworzenie do tej postaci, co wykonuje program o nazwie
KFIL_DSP.EXE.
Wygląd głównego okna tego programu przedstawiono na rysunku 10. W celu dokonania zamiany
sposobu zapisu danych należy wskazać zbiór źródłowy a następnie wybrać rodzaj przeliczenia (MCAD>DSP czyli z systemu dziesiętnego na szesnastkowy lub DSP->MCAD czyli z systemu szesnastkowego
na dziesiętny).
Rysunek 10. Widok okna programu dokonującego konwersji
5. Programy przykładowe
Na użytek laboratoryjny, w asemblerze procesora 2181 napisano kilka przykładowych programów
realizujących podstawowe funkcje zabezpieczeniowe. Znajdują się one w katalogu
c:\adi_dsp\21xx\ezkitl\2181\dsp\ na komputerze stanowiska laboratoryjnego.
5.1. Program szkoleniowy
Poniżej przedstawiono prosty program, umożliwiający szybkie poznanie zasady działania procesora i
podstawowych jego funkcji. Nosi on nazwę:
demo_2d.dsp
Program szkoleniowy uruchamiamy w pierwszej kolejności na symulatorze, który umożliwia
poznanie poszczególnych procedur asemblera i zapoznanie się z wewnętrzną budową procesora. Program
ten nie wykorzystuje pełnych możliwości układu EZKIT LITE, dlatego nie posiada wielu złożonych
17
komend inicjalizujących kodek oraz porty szeregowe, niezbędnych w pracy z rzeczywistym układem.
Prostota i przejrzystość programu powoduje, że doskonale nadaje się on do nauki jako program
szkoleniowy
Pierwsza linia programu zawiera jego nazwę, a kolejne dwa wiersze stanowią deklarację
wykorzystywanych zmiennych. Są to zmienna kołowa zajmująca 10 komórek w pamięci danych oraz
jednowymiarowa zmienna ogólnego stosowania. W następnych wierszach zdefiniowane są wektory
przerwań, które są umieszczane w pamięci programu o adresach od 0x0000H do 0x002FH. Jest ich 11,
tyle ile procesor jest w stanie obsłużyć.
W pierwszej komórce, od której rozpoczyna się wykonywanie programu, znajduje się rozkaz skoku do
etykiety start znajdującej się za wszystkimi wektorami przerwań.
Niewykorzystane w programie przerwania wypełnione są instrukcjami RTI gwarantującymi w
przypadku wystąpienia takiego przerwania powrót do programu.
Adres przerwania IRQE, który generowany jest przyciskiem J3 na module, zawiera rozkaz
umieszczenia stałej 000F w pamięci danych.
Po deklaracji przerwań znajdują się instrukcje programu, pokazujące działanie funkcji
arytmetycznych oraz instrukcji przesyłania danych.
Za pomocą instrukcji TOGGLE FL1 trzy wzajemnie zagnieżdżone pętle zmieniają stan na wyjściu
dwustanowym, powodując miganie podłączonej do niego diody LED.
Po sprawdzeniu i analizie działania programu w symulatorze można przystąpić do pracy w
rzeczywistym układzie.
.module/ram/abs=0 demo;
.var/dm/circ buffer[10];
.var/dm
flag;
jump start;
nop; nop; nop;
rti; rti; rti; rti;
rti; rti; rti; rti;
rti; rti; rti; rti;
rti; rti; rti; rti;
rti; rti; rti; rti;
ax0 = 0x000f;
dm(flag) = ax0;
rti;
rti;
rti; rti; rti; rti;
rti; rti; rti; rti;
rti; rti; rti; rti;
rti; rti; rti; rti;
rti; rti; rti; rti;
start: imask = 0x0010;
ax0 = 0;
dm(flag) = ax0;
ax0 = 3;
ay1 = 5;
ar = ax0 + ay1;
af = ax0 - ay1;
nazwa programu
deklaracja zmiennej dziesięcio-wymiarowej
deklaracja zmiennej ogólnego zastosowania
skok ponad wektorem przerwań
no-operation -rozkaz pusty „nic nie rób”
wypełnienie nieużywanych lokacji przerwań
przerwanie IRQE
ustawienie flag na wartość różną od zera
ładuj do rejestru przerwań wartość 0010 uaktywniając IRQE
umieść w rejestrze ax0 wartość 0
zawartość rejestru ax0 do pamięci danych
ładuj 3 do rejestru ax0
ładuj 5 do rejestru ay1
dodaj rejestry, sumę umieść w rejestrze wyniku ar
odejmij, wynik umieść w feednack rejestrze
zobacz w flagach ALU w symulatorze
ena m_mode;
ustawienie mnożnika dla arytmetyki całkowitej
mx0 = 2;
ładuj 2 do rejestru mx0
mx1 = 3;
ładuj 3 do rejestru mx1
my0 = 2;
ładuj 2 do rejestru my0
mr = mx0 * my0 (uu);
pomnożyć liczby jako nieoznaczone liczby
mr = mr + mx1 * my0 (uu);
wykonywać mnożenie i sumowanie
Następna sekcja używa pętli przy kołowym (cyklicznym) buforze danych.
Można obserwować zmianę częstotliwości świecenia diody w zależności
od zmian wartości licznika pętli.
18
i0 = ^buffer;
l0 = %buffer;
m0 = 1;
m1 = 3;
again: cntr = 3;
do loop_1 until ce;
dm(i0, m0) = ar;
cntr = 2;
do loop_2 until ce;
cntr = 10;
do loop_3 until ce;
ar = ar + ay1;
loop_3:
dm(i0, m0) = ar;
loop_2: dm(i0, m1) = mr1;
loop_1: mr1 = ar;
toggle fl1;
ax0 = dm(flag);
none = pass ax0;
if ne rts;
jump again;
ładuj adres wskaźnika z początku adresu z buforu
ładuj długość rejestru z długości bufora
ładuj adres modyfikacji rejestru do inkrementacji
ładuj drugi modyfikator = 3
ładuj licznik pętli (counter-licznik)
ustaw pętlę zliczanie upływa gdy ce
zapisywać zawartość rejestru do bufora
ładuj licznik pętli, stos licznika(cntr) pozwala zagnieżdżać
powtarzaj pętlę loop_2, 2 jednostki czasu
ładuj licznik pętli na 10
powtarzaj loop_3, 10 jednostek czasu
dodaj zawartości ‘ay1’ do ‘ar’
przesuń zawartości z ‘ar’ do ‘mr1’
przełączaj fl1
weź wartość flag z pamięci
generuj ALU arytmetyczną flagę
jeżeli nie 0, powrót do monitora
skocz z powrotem do start z zagnieżdżonej pętli
.endmod;
5.2. Przykładowy program
W celu zwiększenia przejrzystości wydruków programu, pominięto pewne powtarzające się fragmenty
programu.
Poniższy program przykładowy jest podstawą do tworzenia dalszych aplikacji pokazujących funkcje
zabezpieczeniowe. Spełnia on zadanie edukacyjne, przez wprowadzenie do tworzenia zaawansowanych
modułów.
Korzysta on w pełni z możliwości procesora i kodeka. Przy korzystaniu z sygnałów analogowych
niezbędne było ustawienie łącza SPORT0 oraz kodeka, co spowodowało zwiększenie liczby instrukcji i
przez to mniejszą czytelność programu.
W początkowej części programu znajdują się deklaracje wykorzystywanych stałych, są to określenia
adresów pamięci zajmowanych przez 32 zmapowane rejestry.
Zajmują one obszar w pamięci danych od adresu 0x3FE0H do 0x3FFFH. Żmudne wpisywanie linii
deklaracji można zastąpić globalnym poleceniem
include <..\system.k>;
które uwzględnia stałe znajdujące się w pliku o nazwie system.k.
W części dotyczącej deklaracji zmiennych, zdefiniowane są trzy bufory kołowe oraz jedna zmienna
jednowymiarowa. Dwa zmienne bufory kołowe rx_buf i tx_buf służą do komunikacji i wymiany danych
między procesorem a kodekiem poprzez łącze SPORT0.
Bufor kołowy o wymiarach tablicy 13-to elementowej wykorzystany jest do sterowania kodeka.
Zawarte w nim dane decydują o częstotliwości próbkowania sygnału analogowego, wzmocnieniach
kanałów i o rodzajach wykorzystywanych wejść analogowych.
Kolejny fragment określa początkowe wartości zmiennych, przypisywane podczas uruchamiania
programu.
Główną częścią sterującą pracą programu jest część określająca kody wektorów przerwań. Dla
sygnału nadrzędnego reset przyporządkowane są cztery pierwsze miejsca komórek pamięci programu
0x0000H, 0x0001H, 0x0002H, 0x0003H, które są czytane w pierwszej kolejności działania programu. W
tym programie jest to komenda skoku ponad wektorem przerwań „jump START;” odwołująca się do
procedury znajdującej się w dalszej części programu.
Kolejne miejsca komórek pamięci programu 0x0004H-0x000FH zarezerwowane są dla nie
używanych przerwań IRQ2, IRQL1, IRQL0, wypełnionych instrukcją „rti;”.
Kolejne dwa przerwania SPORT0_tx i SPORT0_rx odpowiedzialne są za wysyłanie i odbieranie
danych między kodekiem a procesorem przez port SPORT0. Wywołują one skoki do procedur
19
next_cmd i
input_samples
wykonujące transfer danych.
Przerwanie IRQE z zarezerwowanym miejscem w pamięci od 0x0018H do 0x001BH wywoływane
jest przyciskiem w układzie EZ-KIT Lite i powoduje skok do procedury Irqe.
Kolejne nieużywane przerwania wypełnione są instrukcją „rti;”.
Po zdefiniowaniu wektora przerwań rozpoczyna się część programu, w której definiowane są
procedury wykorzystane w przerwaniach.
Procedura start, do której odwołuje się nadrzędny sygnał reset wykonywana jest jako pierwsza.
Można ją podzielić na trzy części:
- inicjacja działania portu SPORT0
- konfiguracja pamięci zewnętrznej
- ustawienie działania kodeka.
Procedura ta zakończona jest instrukcją „IDLE;” wprowadzającą procesor w stan oczekiwania do
czasu pojawienia się przerwania.
Z punktu widzenia użytkowego najważniejszą w programie jest procedura Input_samples wywołana
przerwaniem pojawiającym się po zapisaniu i odczytaniu kompletu danych z kodeka. W procedurze tej
próbki z danymi sygnału wejściowego znajdują się w komórkach pamięci (rx_buf+2) oraz (rx_buf+1).
Dane, które mają trafić na wyjścia analogowe kodeka powinny zostać zapisane do komórek pamięci
(tx_buf+1) oraz (tx_buf+2). W tej procedurze są również umieszczane algorytmy realizujące funkcje
zabezpieczeniowe, niepokazane w przykładowym programie. Procedura ta kończy się instrukcją rti
powrotu z przerwania.
Procedura next_cmd przesyła dane do wyjścia analogowego kodeka.
Opisany i przedstawiony poniżej program stanowi podstawę do tworzenia pozostałych aplikacji
realizujących funkcje zabezpieczeniowe.
Po skompilowaniu wykonuje przepisanie wartości zmierzonych 2 kanałów analogowych na wyjścia
analogowe i nie realizuje żadnej funkcji zabezpieczeniowej. Analogowe wejścia i wyjścia można
obserwować ma oscyloskopie zmieniając potencjometrami na obudowie układu sterującego amplitudę
przebiegu i kąt fazowy.
{******************************************************************************}
.module/RAM/ABS=0 loopback;
{deklaracja
}
{******************************************************************************
*
* Assemble time constants
*
******************************************************************************}
{Deklaracja stałych}
.const IDMA=
0x3fe0; {deklaracja stałej IDMA której obszar 16-to bitowy zarezerwowany
jest w komórce pamięci DM o adresie 0x3fe0}
.const BDMA_BIAD=
0x3fe1;
.const BDMA_BEAD=
0x3fe2;
.const BDMA_BDMA_Ctrl=
0x3fe3;
.const BDMA_BWCOUNT=
0x3fe4;
.const PFDATA=
0x3fe5;
.const PFTYPE=
0x3fe6;
.const SPORT1_Autobuf=
0x3fef;
.const SPORT1_RFSDIV=
0x3ff0;
.const SPORT1_SCLKDIV=
0x3ff1;
.const SPORT1_Control_Reg= 0x3ff2;
.const SPORT0_Autobuf=
0x3ff3;
.const SPORT0_RFSDIV=
0x3ff4;
.const SPORT0_SCLKDIV=
0x3ff5;
.const SPORT0_Control_Reg= 0x3ff6;
.const SPORT0_TX_Channels0= 0x3ff7;
.const SPORT0_TX_Channels1= 0x3ff8;
.const SPORT0_RX_Channels0= 0x3ff9;
20
.const
.const
.const
.const
.const
.const
SPORT0_RX_Channels1= 0x3ffa;
TSCALE=
0x3ffb;
TCOUNT=
0x3ffc;
TPERIOD=
0x3ffd;
DM_Wait_Reg=
0x3ffe;
System_Control_Reg= 0x3fff;
{deklaracje zmiennych i buforów kołowych }
.var/dm/ram/circ
rx_buf[3];
/* Status + L data + R data */ {deklaracja zmiennej, wektora,
tzw. buforu kołowego o rozmiarze 3}
.var/dm/ram/circ
tx_buf[3];
/* Cmd + L data + R data */
.var/dm/ram/circ
init_cmds[13];
.var/dm
stat_flag;
{deklaracja zmiennej “zwykłej”}
{inicjalizacja zdeklarowanych zmiennych i buforów kołowych }
.init tx_buf: 0xc000, 0x0000, 0x0000; /* Initially set MCE
*/
{ustalenie początkowej wartości
zmiennej tx_buf na wartości 0c0000H
0c0000H
0c0000H }
.init init_cmds:
{ ustalenie początkowej wartości zmiennej ustawiającej
codec patrz }
0xc002, {0000.0010
Left input control reg
b7-6: 0=left line 1 ----------------------------------------- 0
1=left aux 1
2=left line 2
3=left line 1 post-mixed loopback
b5-4: res
b3-0: left input gain x 1.5 dB
2*1.5=3dB
}
0xc102, {0000.0010
Right input control reg
b7-6: 0=right line 1 ----------------------------------------- 0
1=right aux 1
2=right line 2
3=right line 1 post-mixed loopback
b5-4: res
b3-0: right input gain x 1.5dB
2*1.5=3dB
}
0xc288, {1000.1000
left aux 1 control reg
b7 : 1=left aux 1 mute
b6-5: res
b4-0: gain/atten x 1.5, 08= 0dB, 00= 12dB
}
0xc388, {.1000.1000
right aux 1 control reg
b7 : 1=right aux 1 mute
b6-5: res
b4-0: gain/atten x 1.5, 08= 0dB, 00= 12dB
}
0xc488, {1000.1000
left aux 2 control reg
b7 : 1=left aux 2 mute
b6-5: res
b4-0: gain/atten x 1.5, 08= 0dB, 00= 12dB
}
0xc588, {1000.1000
right aux 2 control reg
b7 : 1=right aux 2 mute
21
b6-5: res
b4-0: gain/atten x 1.5, 08= 0dB, 00= 12dB
}
0xc680, {1000.0000
left DAC control reg
b7 : 1=left DAC mute
b6 : res
b5-0: attenuation x 1.5dB
}
0xc780, {1000.0000
right DAC control reg
b7 : 1=right DAC mute
b6 : res
b5-0: attenuation x 1.5dB
}
0xc85c, {0101.1100
data format register
b7 : res
b5-6: 0=8-bit unsigned linear PCM
1=8-bit u-law companded
2=16-bit signed linear PCM-------------------1
3=8-bit A-law companded
b4 : 0=mono, 1=stereo-----------------------------1
b0-3: 0= 8.
1= 5.5125
2= 16.
3= 11.025
4= 27.42857
5= 18.9
6= 32.
7= 22.05
8= .
9= 37.8
a= .
b= 44.1
c= 48.------------------------------------kHz
d= 33.075
e= 9.6
f= 6.615
(b0) : 0=XTAL1 24.576MHz; 1=XTAL2 16.9344MHz
}
0xc909,
{0000.1001
interface configuration reg
b7-4: res
b3 : 1=autocalibrate-------------------------1
b2-1: res
b0 : 1=playback enabled--------------------1
}
0xca00, {0000.0000
pin control reg
b7 : logic state of pin XCTL1
b6 : logic state of pin XCTL0
b5 : master - 1=tri-state CLKOUT
slave - x=tri-state CLKOUT
b4-0: res
}
0xcc40, {0100.0000
miscellaneous information reg
b7 : 1=16 slots per frame, 0=32 slots per frame
22
b6 : 1=2-wire system, 0=1-wire system--------------2-wire system
b5-0: res
}
0xcd00; { 0000.0000
digital mix control reg
b7-2: attenuation x 1.5dB
b1 : res
b0 : 1=digital mix enabled-----------------------------0-disabled
}
{******************************************************************************
*
* Interrupt vector table
tablica wektora przerwań
*
******************************************************************************}
jump start; rti; rti; rti; {00: reset }
rti;
rti; rti; rti; {04: IRQ2 }
rti;
rti; rti; rti; {08: IRQL1 }
rti;
rti; rti; rti; {0c: IRQL0 }
ar = dm(stat_flag);
{10: SPORT0 tx }
ar = pass ar;
if eq rti;
jump next_cmd;
jump input_samples;
{14: SPORT1 rx }
rti; rti; rti;
jump irqe; rti; rti; rti; {18: IRQE }
rti;
rti; rti; rti; {1c: BDMA }
rti;
rti; rti; rti; {20: SPORT1 tx or IRQ1 }
rti;
rti; rti; rti; {24: SPORT1 rx or IRQ0 }
rti;
rti; rti; rti; {28: timer }
rti;
rti; rti; rti; {2c: power down }
{******************************************************************************
*
* ADSP 2181 intialization
Inicjalizacja ADSP-2181
*
******************************************************************************}
start:
i0 = ^rx_buf;
{adres zmiennej rx_buf do rejestru i0}
l0 = %rx_buf;
{długość, wartość zmiennej rx_buf do rejestru l0}
i1 = ^tx_buf;
l1 = %tx_buf;
i3 = ^init_cmds;
l3 = %init_cmds;
m1 = 1;
{================== S E R I A L P O R T #0 S T U F F ==================}
{===============konfiguracja portu szeregowego #0========================}
ax0 = b#0000001010000111; dm (SPORT0_Autobuf) = ax0;
{ |||!|-/!/|-/|/|+- receive autobuffering 0=off, 1=on
|||!| ! | | +-- transmit autobuffering 0=off, 1=on
|||!| ! | +---- | receive m?
|||!| ! |
| m1
|||!| ! +------- ! receive i?
|||!| !
! i0
|||!| !
!
|||!| +========= | transmit m?
|||!|
| m1
|||!+------------ ! transmit i?
|||!
! i1
|||!
!
|||+============= | BIASRND MAC biased rounding control bit
||+-------------- 0
23
|+--------------- | CLKODIS CLKOUT disable control bit
+---------------- 0
}
ax0 = 0; dm (SPORT0_RFSDIV) = ax0;
{ RFSDIV = SCLK Hz/RFS Hz - 1 }
ax0 = 0; dm (SPORT0_SCLKDIV) = ax0;
{ SCLK = CLKOUT / (2 (SCLKDIV + 1) }
ax0 = b#1000011000001111; dm (SPORT0_Control_Reg) = ax0;
{ multichannel
||+--/|!||+/+---/ | number of bit per word - 1
||| |!|||
| = 15
||| |!|||
|
||| |!|||
|
||| |!||+====== ! 0=right just, 0-fill; 1=right just, signed
||| |!||
! 2=compand u-law; 3=compand A-law
||| |!|+------- receive framing logic 0=pos, 1=neg
||| |!+-------- transmit data valid logic 0=pos, 1=neg
||| |+========= RFS 0=ext, 1=int
||| +---------- multichannel length 0=24, 1=32 words
||+-------------- | frame sync to occur this number of clock
||
| cycle before first bit
||
|
||
|
|+--------------- ISCLK 0=ext, 1=int
+---------------- multichannel 0=disable, 1=enable
}
{ non-multichannel
|||!|||!|||!+---/ | number of bit per word - 1
|||!|||!|||!
| = 15
|||!|||!|||!
|
|||!|||!|||!
|
|||!|||!|||+===== ! 0=right just, 0-fill; 1=right just, signed
|||!|||!||+------ ! 2=compand u-law; 3=compand A-law
|||!|||!|+------- receive framing logic 0=pos, 1=neg
|||!|||!+-------- transmit framing logic 0=pos, 1=neg
|||!|||+========= RFS 0=ext, 1=int
|||!||+---------- TFS 0=ext, 1=int
|||!|+----------- TFS width 0=FS before data, 1=FS in sync
|||!+------------ TFS 0=no, 1=required
|||+============= RFS width 0=FS before data, 1=FS in sync
||+-------------- RFS 0=no, 1=required
|+--------------- ISCLK 0=ext, 1=int
+---------------- multichannel 0=disable, 1=enable
}
ax0 = b#0000000000000111; dm (SPORT0_TX_Channels0) = ax0;
{ ^15
00^ transmit word enables: channel # == bit # }
ax0 = b#0000000000000111; dm (SPORT0_TX_Channels1) = ax0;
{ ^31
16^ transmit word enables: channel # == bit # }
ax0 = b#0000000000000111; dm (SPORT0_RX_Channels0) = ax0;
{ ^15
00^ receive word enables: channel # == bit # }
ax0 = b#0000000000000111; dm (SPORT0_RX_Channels1) = ax0;
{ ^31
16^ receive word enables: channel # == bit # }
{============== S Y S T E M A N D M E M O R Y S T U F F ==============}
ax0 = b#0000111111111111; dm (DM_Wait_Reg) = ax0;
{ |+-/+-/+-/+-/+-/- ! IOWAIT0
|| | ! |
!
|| | ! |
!
|| | ! +------ | IOWAIT1
|| | !
|
|| | !
|
24
|| | +--------- ! IOWAIT2
|| |
!
|| |
!
|| +------------ | IOWAIT3
||
|
||
|
|+=============== ! DWAIT
|
!
|
!
+---------------- 0
}
ax0 = b#0001000000000000; dm (System_Control_Reg) = ax0;
{ +-/!||+-----/+-/- | program memory wait states
| !|||
|0
| !|||
|
| !||+---------- 0
| !||
0
| !||
0
| !||
0
| !||
0
| !||
0
| !||
0
| !|+----------- SPORT1 1=serial port, 0=FI, FO, IRQ0, IRQ1,..
| !+------------ SPORT1 1=enabled, 0=disabled
| +============= SPORT0 1=enabled, 0=disabled
+---------------- 0
0
0
}
ifc = b#00000011111111;
{ clear pending interrupt }
nop;
icntl = b#00000;
{ ||||+- | IRQ0: 0=level, 1=edge
|||+-- | IRQ1: 0=level, 1=edge
||+--- | IRQ2: 0=level, 1=edge
|+---- 0
|----- | IRQ nesting: 0=disabled, 1=enabled
}
mstat = b#1000000;
{ ||||||+- | Data register bank select
|||||+-- | FFT bit reverse mode (DAG1)
||||+--- | ALU overflow latch mode, 1=sticky
|||+---- | AR saturation mode, 1=saturate, 0=wrap
||+----- | MAC result, 0=fractional, 1=integer
|+------ | timer enable
+------- | GO MODE
}
{******************************************************************************
*
* ADSP 1847 Codec intialization
Inicjalizacja Codeca ADSP-1847
*
******************************************************************************}
{ clear flag }
wyzerowanie flagi
ax0 = 1;
dm(stat_flag) = ax0;
{ enable transmit interrupt }
umożliwiać transmitować przerwanie
imask = b#0001000000;
{ |||||||||+ | timer
||||||||+- | SPORT1 rec or IRQ0
|||||||+-- | SPORT1 trx or IRQ1
25
||||||+--- | BDMA
|||||+---- | IRQE
||||+----- | SPORT0 rec
|||+------ | SPORT0 trx
||+------- | IRQL0
|+-------- | IRQL1
+--------- | IRQ2
}
ax0 = dm (i1, m1);
{ start interrupt }
rozpoczęcie(początek) przerwania
tx0 = ax0;
check_init:
ax0 = dm (stat_flag);
{ wait for entire init } oczekiwanie na kompletny ......
af = pass ax0;
{ buffer to be sent to }
bufor do transmisji do
if ne jump check_init;
{ the codec
}
kodera
ay0 = 2;
check_aci1:
ax0 = dm (rx_buf);
{ once initialized, wait for codec }
wcześniejsze inicjalizowanie,
oczekiwanie na koder
ar = ax0 and ay0;
{ to come out of autocalibration } do wysłania automatycznej kalibracji
if eq jump check_aci1;
{ wait for bit set }
oczekiwania na ustawienie bitu
check_aci2:
ax0 = dm (rx_buf);
{ wait for bit clear }
oczekiwanie na wyzerowany bit
ar = ax0 and ay0;
if ne jump check_aci2;
idle;
ay0 = 0xbf3f;
{ unmute left DAC }
..........................
ax0 = dm (init_cmds + 6);
ar = ax0 AND ay0;
dm (tx_buf) = ar;
idle;
ax0 = dm (init_cmds + 7); { unmute right DAC }
ar = ax0 AND ay0;
dm (tx_buf) = ar;
idle;
ifc = b#00000011111111; { clear any pending interrupt }
wyzerowanie jakiś przerwań
oczekujących na obsługę
nop;
imask = b#0000110000;
{ enable rx0 interrupt }
włączenie przerwania rx0
{ |||||||||+ | timer
||||||||+- | SPORT1 rec or IRQ0
|||||||+-- | SPORT1 trx or IRQ1
||||||+--- | BDMA
|||||+---- | IRQE
||||+----- | SPORT0 rec
|||+------ | SPORT0 trx
||+------- | IRQL0
|+-------- | IRQL1
+--------- | IRQ2
}
{------------------------------------------------------------------------------ wait for interrupt and loop forever
czekaj na przerwanie i pętle
------------------------------------------------------------------------------}
talkthru:
idle;
jump talkthru;
{******************************************************************************
*
* Interrupt service routines
przerwanie programu użytkowego
*
26
******************************************************************************}
{------------------------------------------------------------------------------ receive interrupt used for loopback
odbiór przerwania użytego do pętli zwrotnej
------------------------------------------------------------------------------}
input_samples:
ena sec_reg;
{ use shadow register bank }
użycie cienia banku rejestru
mr0 = dm (rx_buf + 1);
{ loopback inputs to outputs } wejście pętli zwrotnej do wyjścia
mr1 = dm (rx_buf + 2);
sr = ashift mr0 by -1 (hi);
af = pass sr1;
sr = ashift mr1 by -1 (hi);
{sygnały wejściowe znajdują się odpowiednio w rejestrach “af” “sr1”}
{IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII}
ar = sr1;
dm (tx_buf + 1) = ar;
ar = af;
dm (tx_buf + 2) = ar;
ar = ar + 0x10;
rti;
{------------------------------------------------------------------------------ transmit interrupt used for Codec initialization
przerwanie transmisji użytej do
inicjalizacji codec
------------------------------------------------------------------------------}
next_cmd:
ena sec_reg;
ax0 = dm (i3, m1);
{ fetch next control word and }
przynieś następne słowo
kontrolne i
dm (tx_buf) = ax0;
{ place in transmit slot 0 }
umieść w gnieźdie transmisji
ax0 = i3;
ay0 = ^init_cmds;
ar = ax0 - ay0;
if gt rti;
{ rti if more control words still waiting }
rti jeżeli więcej słów nieruchomo
czekających
ax0 = 0xaf00;
{ else set done flag and }
w przeciwnym wypadku ustaw flage i
dm (tx_buf) = ax0;
{ remove MCE if done initialization }
przenieś MCE jeżeli wykonana
inicjalizacja
ax0 = 0;
dm (stat_flag) = ax0;
{ reset status flag }
zeruj status flag
rti;
irqe: toggle fl1;
rti;
.endmod;
5.3. Programy demonstracyjne
5.3.1. Program demonstrujący działanie wyjść dwustanowych
Działanie wyjść dwustanowych przedstawiono za pomocą prostego programu
\TEST_WY\T2\d02.exe
Jego uruchomienie powoduje sekwencyjne zapalanie się diod w układzie sterującym. Istnieje
programowa możliwość zmiany częstotliwości i sekwencji zapalania się diod. Realizacja tej opcji
następuje przez zmianę licznika pętli.
.module/ram/abs=0 demo;/* define the program module */
.var/dm/circ buffer[10]; /* declare a circular buffer of length 10 */
27
.var/dm
flag;
.var/dm
flag1;
jump start;
nop; nop; nop;
rti; rti; rti; rti;
rti; rti; rti; rti;
rti; rti; rti; rti;
rti; rti; rti; rti;
rti; rti; rti; rti;
ax0 = 0x000f;
dm(flag) = ax0;
rti;
rti;
rti; rti; rti; rti;
rti; rti; rti; rti;
rti; rti; rti; rti;
rti; rti; rti; rti;
rti; rti; rti; rti;
/* general purpose flag */
/* general purpose flag */
/* jump over interrupt vectors */
/* code vectors here upon IRQ2 interrupt */
/* code vectors here upon IRQL1 interrupt */
/* code vectors here upon IRQL0 interrupt */
/* code vectors here upon SPORT0 TX interrupt */
/* code vectors here upon SPORT0 RX interrupt */
/* code vectors here upon IRQE interrupt */
/* set flag to non-zero value */
/* code vectors here upon BDMA interrupt */
/* code vectors here upon SPORT1 TX (IRQ1) interrupt */
/* code vectors here upon SPORT1 RX (IRQ0) interrupt */
/* code vectors here upon TIMER interrupt */
/* code vectors here upon POWER DOWN interrupt */
start:
ax0 = dm(0x3fe6);
ay0 = 0x000f;
ar = ax0 OR ay0;
dm(0x3fe6) = ar;
ax1 = 0x0000;
imask = 0x0010;
ax0 = 0;
dm(flag) = ax0;
dm(flag1) = ax0;
ax0 = 3;
ay1 = 5;
ar = ax0 + ay1;
af = ax0 - ay1;
/* enable IRQE, interrupt button on EZ-LAB */
/* clear flag */
/* clear flag1 */
/* load a 3 into an ALU X input register */
/* load a 5 into an ALU Y input register */
/* add inputs, store sum in result register */
/* subtract, store result in feednack reg */
/* look at ALU flags in simlator*/
ena m_mode;
/* set up multiplier for integer arithmetic */
mx0 = 2;
/* load a 2 into a MAC X input register */
mx1 = 3;
/* load a 3 into another MAC X input register */
my0 = 2;
/* load a 2 into a MAC Y input register */
mr = mx0 * my0 (uu); /* multiply numbers as unsigned numbers */
mr = mr + mx1 * my0 (uu);
/* perform multiply and accumulate */
i0 = ^buffer;
l0 = %buffer;
m0 = 1;
m1 = 3;
/* load address pointer with start address of buffer */
/* load length register with length og buffer */
/* load address modify register with 1 to increment */
/* load second modifier with a 3 */
again: cntr = 300;
/* load loop counter */
do loop_1 until ce;
/* set up loop to end when count expires */
dm(i0, m0) = ar;
/* store contents of register ar in buffer */
cntr = 20;
/* load loop counter, cntr stack allows nesting */
do loop_2 until ce;
/* repeat to loop_2, 2 times */
cntr = 1000;
/* load loop counter with 10, change to 0x1000 to run on EZ-LAB */
do loop_3 until ce;
/* repeat from her to loop_3, 10 times */
ar = ar + ay1;
/* add contents of ay1 to ar */
loop_3: dm(i0, m0) = ar;
loop_2: dm(i0, m1) = mr1;
loop_1:
mr1 = ar;
/* move contents of ar into mr1 */
toggle fl1;
/* toggle flag */
ax0 = dm(flag1);
28
ay0 = 0x0001;
ar = ax0 + ay0;
ay0 = 0x0003;
ar = ar AND ay0;
dm(flag1) = ar;
se = ar;
ax0 = dm(0x3fe5);
ay1 = 0xfff0;
ar = ax0 AND ay1;
si = 0x0001;
sr = ASHIFT si (LO);
ay0 = sr0;
ar = ar OR ay0;
dm(0x3fe5)=ar;
ax0 = dm(flag);
none = pass ax0;
if ne rts;
jump again;
.endmod;
/* wartość przesunięcia */
/* maska bitowa */
/* get flag value from memory */
/* generate ALU arithmetic flag */
/* if not 0, return to monitor */
/* go back to start of nesed loops */
5.3.2. Program demonstrujący działanie wejść dwustanowych
Działanie wejść dwustanowych pokazuje program
\TEST_WE\T2\d02.exe
Załączenie przełącznika na obudowie układu sterującego, powoduje zapalenie się odpowiadającej mu
diody. Stosując odpowiednią logikę można stworzyć różne kombinacje testowania wejść i wyjść
dwustanowych.
.module/ram/abs=0 demo; /* define the program module */
.var/dm/circ buffer[10]; /* declare a circular buffer of length 10 */
.var/dm
flag;
/* general purpose flag */
.var/dm
flag1;
/* general purpose flag */
jump start;
/* jump over interrupt vectors */
nop; nop; nop;
rti; rti; rti; rti;
/* code vectors here upon IRQ2 interrupt */
rti; rti; rti; rti;
/* code vectors here upon IRQL1 interrupt */
rti; rti; rti; rti;
/* code vectors here upon IRQL0 interrupt */
rti; rti; rti; rti;
/* code vectors here upon SPORT0 TX interrupt */
rti; rti; rti; rti;
/* code vectors here upon SPORT0 RX interrupt */
/* code vectors here upon IRQE interrupt */
ax0 = 0x000f;
/* set flag to non-zero value */
dm(flag) = ax0;
rti;
rti;
rti; rti; rti; rti;
/* code vectors here upon BDMA interrupt */
rti; rti; rti; rti;
/* code vectors here upon SPORT1 TX (IRQ1) interrupt */
rti; rti; rti; rti;
/* code vectors here upon SPORT1 RX (IRQ0) interrupt */
rti; rti; rti; rti;
/* code vectors here upon TIMER interrupt */
rti; rti; rti; rti;
/* code vectors here upon POWER DOWN interrupt */
start:
ax0 = dm(0x3fe6);
ay0 = 0x000f;
ar = ax0 OR ay0;
dm(0x3fe6) = ar;
ax1 = 0x0000;
imask = 0x0010;
/* enable IRQE, interrupt button on EZ-LAB */
ax0 = 0;
dm(flag) = ax0;
/* clear flag */
dm(flag1) = ax0;
/* clear flag1 */
ax0 = 3;
/* load a 3 into an ALU X input register */
29
ay1 = 5;
ar = ax0 + ay1;
af = ax0 - ay1;
/* load a 5 into an ALU Y input register */
/* add inputs, store sum in result register */
/* subtract, store result in feednack reg */
/* look at ALU flags in simlator*/
ena m_mode;
/* set up multiplier for integer arithmetic */
mx0 = 2;
/* load a 2 into a MAC X input register */
mx1 = 3;
/* load a 3 into another MAC X input register */
my0 = 2;
/* load a 2 into a MAC Y input register */
mr = mx0 * my0 (uu); /* multiply numbers as unsigned numbers */
mr = mr + mx1 * my0 (uu);
/* perform multiply and accumulate */
i0 = ^buffer;
/* load address pointer with start address of buffer */
l0 = %buffer;
/* load length register with length og buffer */
m0 = 1;
/* load address modify register with 1 to increment */
m1 = 3;
/* load second modifier with a 3 */
again: cntr = 300;
/* load loop counter */
do loop_1 until ce;
/* set up loop to end when count expires */
dm(i0, m0) = ar;
/* store contents of register ar in buffer */
cntr = 20;
/* load loop counter, cntr stack allows nesting */
do loop_2 until ce;
/* repeat to loop_2, 2 times */
cntr = 1000;
/* load loop counter with 10, change to 0x1000 to run on EZ-LAB */
do loop_3 until ce;
/* repeat from her to loop_3, 10 times */
ar = ar + ay1;
/* add contents of ay1 to ar */
loop_3: dm(i0, m0) = ar;
loop_2: dm(i0, m1) = mr1;
loop_1: mr1 = ar;
/* move contents of ar into mr1 */
ax0 = dm(0x3fe5);
ay1 = 0xfff0;
ar = ax0 AND ay1;
ax0 = ar;
/* aktualna wartość 0x3fe5 ze zgaszonymi wyjściami */
ay1 = 0x00f0;
ar = ax0 AND ay1;
/* aktualny stan wejść */
af = TSTBIT 5 OF AR;
if NE JUMP bit5set;
JUMP bitclr;
bit5set:
TOGGLE fl1;
bitclr:
se = -4;
/* wartość przesunięcia */
sr = ASHIFT ar (LO);
ay0 = sr0;
/* bity wejść przesunięte o 4 w lewo */
ar = ax0 OR ay0;
dm(0x3fe5)=ar;
ax0 = dm(flag);
/* get flag value from memory */
none = pass ax0;
/* generate ALU arithmetic flag */
if ne rts;
/* if not 0, return to monitor */
jump again;
/* go back to start of nesed loops */
.endmod;
5.3.3. Program realizujący algorytm zabezpieczenia nadmiarowego
Właściwe funkcje zabezpieczeniowe, uzyskuje się wstawiając w przedstawionym programie
przykładowym na początku deklaracje zmiennych, a w procedurze Input_samples część realizującą daną
funkcję.
Funkcję nadmiarową realizuje program o nazwie:
\NAD_PR\nad_pr1.dsp
Oblicza on liczbę odebranych próbek, wyliczając na podstawie wartości chwilowych wartość
maksymalną. W przypadku, gdy liczba próbek jest większa niż 513, co wskazuje na to, że dokonano
porównania próbek i określenia wartości maksymalnej, z czasu większego niż połowa okresu, program
dokonuje porównania wartości maksymalnej z zadeklarowaną wartością I_nast. W przypadku gdy
wartość nastawiona jest większa od wartości maksymalnej, zostaje zgaszona flaga FL1, w odwrotnym
30
przypadku flaga FL1 zostaje zapalona. Po porównaniu następuje zerowanie liczby próbek oraz określonej
wartości maksymalnej. Na rysunku 11 pokazano algorytm działania procedury, a poniżej dwa fragmenty
programu zawierające deklaracje wykorzystywanych zmiennych oraz samą procedurę.
Rysunek 11. Zaimplementowany algorytm funkcji nadnapięciowej
{ Deklaracja zmiennych: }
.var/dm
I_max; {zmienna programowa}
31
.var/dm
.var/dm
.var/dm
.init I_max:
.init I_nast:
.init licz::
.init I_odp:
I_nast;
{zmienna zawierająca wartość nastawy}
licz;
{zmienna programowa -licznik}
I_odp;
{zmienna zawierająca wartość odpadu}
0;
0x3000;
0;
0x2f00;
{Fragment z procedurą realizującą algorytm zabezpieczeniowy }
AX0 = dm(I_max); { czytaj wartość }
ay0 = mr0;
{ bieżąca wartość }
ar = AX0 - ay0;
{porównaj }
if GT jump LICZNIK; { jeżeli bufor jest większy od stałej to ... }
dm(I_max) = ay0;
{ przypisanie }
LICZNIK:
ay0 = dm(licz);
{ czytaj stan licznika }
ar = ay0 + 1;
{ zwiększ o 1 }
ay0 = ar;
{ zapisz licznik }
dm(licz) = ay0;
{ f = 48kHz na pól okresu przypada 480 próbek = 1e0h }
ax1 = ay0;
ar = ax1 - 513;
{ spr.2 licznika który zależy od częstotliwości }
if LE jump koniec;
ar = dm(I_nast);
{ czytaj wartość nastawiona }
ay0 = dm(I_max);
{ czytaj wartość maksymalna }
ar = ar - ay0;
{ warunek nadprądowy }
if GT jump zgas;
ar = ar - ay0;
if LE jump zapal;
zapal:
SET FL1;
jump skok;
zgas:
ar = dm(I_odp);
ay0 = dm(I_max);
ar = ar - ay0;
{ warunek odpadu }
if GE RESET FL1;
skok:
ar = 0;
dm(licz) = ar;
{ zerowanie licznika }
dm(I_max)= ar;
{ zerowanie I_max }
KONIEC:
5.3.4. Program realizujący algorytm zabezpieczenia niedomiarowego
Zabezpieczenie niedomiarowe jest wykonane podobnie jak nadmiarowe.
Procedura oblicza liczbę odebranych próbek, wyliczając na podstawie wartości chwilowych wartość
maksymalną. W przypadku, gdy liczba próbek jest większa niż 513, co wskazuje na to, że dokonano
porównania próbek i określenia wartości maksymalnej, z czasu większego niż połowa okresu, program
dokonuje porównania wartości maksymalnej z zadeklarowaną wartością I_nast. W przypadku gdy
wartość nastawiona jest mniejsza od wartości maksymalnej, zostaje zgaszona flaga FL1, w odwrotnym
przypadku flaga FL1 zostaje zapalona. Po porównaniu następuje zerowanie liczby próbek oraz określonej
wartości maksymalnej.
Na rysunku 12 pokazano algorytm działania procedury, a poniżej dwa fragmenty programu
zawierające deklaracje wykorzystywanych zmiennych oraz samą procedurę.
\POD_NAP\pod_nap.dsp.
{ Deklaracja zmiennych: }
.var/dm
U_max; {zmienna programowa}
.var/dm
U_nast; {zmienna zawierająca wartość nastawy}
.var/dm
licz;
{zmienna programowa -licznik}
32
.var/dm
.init U_max:
.init U_nast:
.init licz:
.init U_odp:
U_odp;
0;
0x3000;
0;
0x3100;
{zmienna zawierająca wartość odpadu}
{wartość chwilowa maksymalna }
{wartość pobudzenia }
{wartość początkowa licznika }
{wartość odwzbudzenia }
{Fragment z procedurą realizującą algorytm zabezpieczeniowy }
{ zakłada się że próbka znajduje się w mr0 }
AX0 = dm(U_max); { czytaj wartość }
ay0 = mr0;
{ bieżąca wartość }
ar = AX0 - ay0;
{porównaj }
if GT jump LICZNIK; { jeżeli bufor jest większy od stałej to ... }
dm(U_max) = ay0;
{ przypisanie }
LICZNIK:
ay0 = dm(licz);
{ czytaj stan licznika }
ar = ay0 + 1;
{ zwiększ o 1 }
ay0 = ar;
{ zapisz licznik }
dm(licz) = ay0;
{ f = 48kHz na pół okresu przypada 480 próbek = 1e0h }
ax1 = ay0;
ar = ax1 - 513;
{ spr.2 licznika który zależy od częstotliwości }
if LE jump koniec;
ar = dm(U_odp);
{ czytaj wartość nastawiona }
ay0 = dm(U_max);
{ czytaj wartość maksymalna }
ar = ar - ay0;
{ warunek podnapieciowy }
if LT jump zgas;
ar =dm(U_nast)
ar = ar - ay0;
{ warunek podnapieciowy }
if GE jump zapal;
zapal:
SET FL1;
jump skok;
zgaś:
RESET FL1;
skok:
ar = 0;
dm(licz) = ar;
{ zerowanie licznika }
dm(U_max)= ar;
{ zerowanie U_max }
KONIEC:
33
Rysunek 12. Zaimplementowany algorytm funkcji podnapięciowej
34
5.4. Programy realizujące algorytmy filtracyjne
Program realizujący algorytm filtracji cyfrowej uzyskuje się wstawiając w przedstawionym programie
przykładowym na początku deklaracje zmiennych i nazwę odpowiedniego zbioru zawierającego
współczynniki filtru zapisane w formie liczb szesnastkowych oraz w procedurze Input_samples
właściwy program realizujący filtrację.
Cały program dokonujący filtracji SOI nosi nazwę:
\SOI_FIL.DSP
a dokonujący filtracji NOI:
\NOI_FIL.DSP
Przykładowe zbiory zawierające współczynniki filtru noszą rozszerzenia WSP.
W części definiującej stałe zdeklarowana jest wieloelementowa stała o nazwie taps, której wartość
ustawiana jest zależnie od rzędu stosowanego filtru.
Komendy:
var
coeffsTbl [2]
oraz
init coeffsTbl: ^fir1_coefs, ^fir1_coefs;
deklarują zmienną tablicę dwuelementową ze składnikami fir1_coefs, w których znajdują się
współczynniki filtru z przykładowego zbioru o nazwie wsp_d.wsp
init fir1_coefs: <wsp_d.wsp>;
W buforze kołowym „data” przechowywana jest tablica zpróbkowanych sygnałów wejściowych,
której wielkość określa rząd filtru.
Ze względu na dużą liczbę współczynników filtru częstotliwość próbkowania wynosi 8kHz.
Obliczanie próbek wyjściowych przebiega według wzoru:
Ytaps = X1•w1+ X2•w2+ X3•w3+ ....+ Xtaps•wtaps .
gdzie:
X1, X2, X3 ... Xtaps oznaczają kolejne próbki wejściowe umieszczone w pamięci danych
w1, w2, w3 ...wtaps oznaczają kolejne współczynniki filtru typu FIR
Linia:
fir: cntr=taps-1;
ustawia licznik pętli na wartość równą liczbie współczynników,
Wiersz
mr=0, mx0=dm(i0,m0), my0=pm(i4,m4);
definiuje argumenty operacji, a polecenia:
do fir1loop until ce;
fir1loop: mr=mr+mx0*my0(ss), mx0=dm(i0,m0), my0=pm(i4,m4);
obliczają wartości próbki wyjściowej.
Próbka wyjściowa jest przepisywana do bufora wyjściowego portu SPORT0, skąd zostaje przesłana
do kodeka, trafiając na oba jego kanały cyfrowoanalogowe.
Poniżej przedstawiono dwa fragmenty programu zawierające deklaracje wykorzystywanych
zmiennych oraz samą procedurę.
{ Deklaracja zmiennych: }
.const
taps=16; {rząd filtru - liczba współczynników filtru }
.var
coeffsTbl [2];
.init
coeffsTbl: ^fir1_coefs, ^fir1_coefs;
35
{
.var/circ
.var/pm/circ
.init
^^^^^^^^^^ dummy for talk through }
data[taps];
fir1_coefs[taps]; { deklaracja tablicy w pam. progr. z współczynnikami filtru}
fir1_coefs: <wsp_d.wsp>; { nazwa pliku z współczynnikami filtru }
{Część realizująca algorytm filtracji}
sr1 = dm (rx_buf + 1);
{ get new sample from SPORT0 (from codec) }
process_sample:
dm(i0,m0)=sr1;
{ store sample in data buffer (delay line) }
fir:
cntr=taps-1;
{rzad filtru - liczba wspolczynnikow - mnozen}
mr=0;
{probka wyjsciowa - po filtracji}
mx0=dm(i0,m0);
{piwrwsza probka wejściowa z pamięci danych - rejestr i0 wskazuje na }
{tablicę o nazwie data zawierającą kolejne próbki wejściowe}
my0=pm(i4,m4);
{współczynniki filtru z pamięci programu - rejestr i4 wskazuje na tablicę o}
{nazwie fir1_coefs zawierającą współczynniki filtru zapisane w zbiorze }
{wsp_d.wsp}
do fir1loop until ce;
fir1loop: mr=mr+mx0*my0(ss), mx0=dm(i0,m0), my0=pm(i4,m4);
mr=mr+mx0*my0(rnd);
if mv sat mr;
sr = ashift mr1 by 1 (lo);
{pomnożenie wartości próbki wyjściowej przez 2}
mr1 = sr0;
output:
dm (tx_buf + 1) = mr1;
{ wpisanie próbki wyjściowej do bufora wyjściowego SPORT0}
dm (tx_buf + 2) = mr1;
{ wpisanie próbki wyjściowej do bufora wyjściowego SPORT0}
rti;
6. Przebieg ćwiczenia
Celem ćwiczenia jest pokazanie działania i budowy kilku prostych programów realizujących
podstawowe algorytmy zabezpieczeniowe.
Ćwiczenie należy rozpocząć od zapoznania się z działaniem symulatora programowego sim2181.exe
na przykładzie programu demonstracyjnego o nazwie demo_2d.dsp. W programie należy zwrócić uwagę
na sposób wykonania przez procesor działań arytmetycznych oraz instrukcji pętli.
Następnie należy uruchomić na module EZ KIT program demonstrujący działanie wyjścia
dwustanowego \TEST_WY\T2\d02.exe. W tym celu należy wykorzystać program ładujący o nazwie
EZKITAPP.EXE. Po stwierdzeniu poprawnego działania programu, należy dokonać modyfikacji
programu źródłowego tak, aby uzyskać dwukrotne i czterokrotne wydłużenie czasu zapalania i gaśnięcia
diody podłączonej do flagi Fl1. Po każdej z modyfikacji należy skompilować zmodyfikowany plik
źródłowy i po uzyskaniu programu wynikowego o rozszerzeniu EXE, za pomocą programu
EZKITAPP.EXE uruchomić go na module EZ-KIT.
W podobny sposób należy zapoznać się z programami demonstrującymi:
- działanie wejścia dwustanowego (program \TEST_WE\T2\d02.exe)
- algorytm zabezpieczenia nadprądowego \NAD_PR\nad_pr1.dsp
- algorytm zabezpieczenia podnapięciowego \POD_NAP\pod_nap.dsp
W przypadku dwu ostatnich programów należy sprawdzić wpływ zmiany parametrów o nazwach
U_nast, U_odp na progi działania i odpadania sprawdzanych funkcji przekaźnikowych.
Następnie należy uruchomić program Mathcad i po wczytaniu odpowiedniego zbioru obliczającego
utworzyć zbiór z współczynnikami filtru typu FIR o parametrach podanych przez prowadzącego. Po
zamianie współczynników filtru na wartości szesnastkowe za pomocą programu KFIL_DSP.EXE oraz
skompilowaniu programu źródłowego o nazwie \TEST_FIL\FIL100.DSP należy za pomocą programu
EZKITAPP.EXE uruchomić uzyskany plik wynikowy na module EZ-KIT. Po uruchomieniu programu,
należy określić charakterystykę amplitudową i fazową uzyskanego filtru, zmieniając częstotliwość
sygnału podawanego z generatora na wejście analogowe modułu i obserwując sygnały wejściowe i
wyjściowe na oscyloskopie.
36

Podobne dokumenty