Escolar Documentos
Profissional Documentos
Cultura Documentos
ta ksika jest wanie dla Ciebie. Nie musisz wczeniej mie wiedzy z zakresu elektroniki, poniewa
wszystkie potrzebne pojcia zostay tu wyjanione od podstaw. Niepotrzebna Ci take znajomo programowania w jakimkolwiek jzyku te informacje, podane w moliwie najbardziej przystpny sposb,
te znajdziesz w podrczniku. Wobec tego wszystko, czego potrzebujesz, to ch nauki. I jeszcze jedno:
moe zastanawiasz si, co pocz z takim mikrokontrolerem? Ot moesz zastosowa go do konstruowania efektw wietlnych z diod, sterowania modelami samolotw, a nawet sterowania robotami.
Serwomechanizmy
Wywietlacze alfanumeryczne
Kompilatory
Obsuga przerwa
Cena: 77,00 z
Pawe Borkowski
Pawe Borkowski
5424
AVRAR7.indd 1
29-04-10 12:50:27
AVR i ARM7.
Programowanie
mikrokontrolerw
dla kadego
Autor: Pawe Borkowski
ISBN: 978-83-246-2628-1
Format: 158235, stron: 528
Spis treci
Wstp ...............................................................................................................................7
Poszukiwacze zaginionych portw, czyli jak zacz przygod z mikrokontrolerami ................9
Spis treci
Spis treci
Lekcja 15
Obsuga
wywietlacza graficznego
z telefonu Siemens S65.
Cz 1.
Temat lekcji to nie pomyka: rzeczywicie nauczymy si wywietla dane na kolorowym wywietlaczu LCD,
uywanym w telefonach firmy Siemens serii S65. Podobno informacja o tym fakcie lotem byskawicy obiega
cay wiat, take ten wodny, plotka zatacza coraz szersze krgi, take na wodzie. Opowiada mi znajomy ichtiolog A zreszt zobaczmy, jakie zdjcia w ichtiolog przynis mi z jeziora (patrz rysunek 15.1).
limak ma racj, mwic, e do podczenia wywietlacza S65 do mikrokontrolera najlepiej nadaje si interfejs
SPI. Jednak dobrze te jest zna alternatywny sposb obsugi wywietlacza LCD, dlatego w pierwszej kolejnoci wysyanie danych do wywietlacza zaimplementujemy programowo. Do podczenia wywietlacza uyjemy linii od P0.16 do P0.21.
Przypomnijmy sobie, jak wyglda modu wywietlacza graficznego S65 (patrz rysunek 15.2).
Waciwie gdy piszemy wywietlacz graficzny S65, posugujemy si skrtem penej nazwy wywietlacz graficzny uywany w telefonach Siemens S65. Aby nie potkn si o wasne nogi, bdziemy uywa nazw jeszcze
krtszych: wywietlacz S65, wywietlacz LCD, kolorowy wywietlacz lub po prostu wywietlacz. Poniewa nie bdziemy zajmowa si innymi wywietlaczami graficznymi, groba pomyki nie istnieje.
Jedyn dostpn pomoc dotyczc programowania wywietlacza S65 jest synny tutorial Christiana Kranza1.
Moemy si z niego dowiedzie, e interesujcy nas wywietlacz by wykorzystywany w telefonach firmy
Siemens serii S65, M65, CX65 oraz SK65. Modu ARE0055 zawiera wywietlacz S65 ze sterownikiem serii
LS020xxx firmy Sharp. Matryca wywietlacza ma rozdzielczo 176132 pikseli, przy moliwoci wywietlania 16-bitowych kolorw (65 536 kolorw).
Oryginalnie wywietlacz ma 10 wyprowadze z wejciami na dwa poziomy napi. Dziki zastosowanym
w module ARE0055 ukadom elektronicznym liczb t udao si zredukowa do omiu linii zawierajcych
wyprowadzenie zasilania +3.3 V. Ich rozkad na wtyczce moduu przedstawiono na rysunku 15.3.
412
Rysunek 15.3.
Rozkad wyprowadze
na wtyczce moduu ARE0055
(widok wtyczki z przodu).
Oznaczenie NP wskazuje
na wyprowadzenie
niepodczone
413
Skoro jest wtyczka, to niebezpodstawne bdzie pytanie o miejsce, gdzie mona j wetkn. Przewidziano do
tego celu jedno wspaniae miejsce na pytce edukacyjnej AE0061. Na rysunku 15.4 widzimy cz pytki
edukacyjnej, na ktrej uwidocznione zostay gniazda suce do podczenia moduu ARE0055.
Rysunek 15.4.
Zdjcie fragmentu pytki
edukacyjnej ARE0061
z uwidocznionymi
gniazdami sucymi
do podczenia
wywietlacza S65
Na zdjciu widzimy dwa gniazda oznaczone P18 i P19. Piny znajdujce si na tych samych miejscach dwch
gniazd s ze sob poczone. Na przykad pin znajdujcy si w lewym grnym rogu gniazda P19 jest poczony
z pinem znajdujcym si w lewym grnym rogu gniazda P18. Gniazdo P18 suy do podczenia wtyczki moduu
ARE0055, tej wtyczki, ktrej rozkad wyprowadze widzielimy na rysunku 15.3. Natomiast do pinw
gniazda P19 bdziemy kablami podcza wyprowadzenia mikrokontrolera.
Do zilustrowania pocze ukadu nie bdziemy uywa zdjcia, lecz schematu, ktry wida na rysunku 15.5.
Rysunek 15.5.
Schemat obszaru pytki
edukacyjnej sucego
podczeniu moduu
wywietlacza
graficznego S65
Na schemacie odpowiednimi nazwami oznaczono piny, ktre po podczeniu do gniazda P18 moduu ARE0055
bd odpowiaday liniom o tych samych nazwach wywietlacza LCD.
Zgodnie z zapowiedzi w pierwszym zadaniu interfejs komunikacji midzy mikrokontrolerem a wywietlaczem S65 zostanie obsuony programowo. Wykorzystamy przy tym konfiguracj poczenia mikrokontrolera i wywietlacza opisan w tabeli 15.1.
414
P0.16
RST
P0.17
RS
P0.18
CLK
P0.19
CS
P0.20
DAT
P0.21
BL
Naley zaznaczy, e przy programowej implementacji interfejsu komunikacji sposb poczenia mikrokontrolera z moduem wywietlacza moe by dowolny. Schemat przedstawionej konfiguracji pocze wida na
rysunku 15.6. Bdzie to nasz oficjalny schemat, ktry wykorzystamy do rozwizania pierwszego zadania
w ramach tej lekcji.
Rysunek 15.6.
Schemat ukadu
do pierwszego zadania
obsugi wywietlacza
graficznego bez
interfejsu SPI
Zarwno w pierwszym, jak i w drugim zadaniu chodzi wycznie o poprawne zainicjowanie wywietlacza
S65. Efektem tego powinien by kolorowy szum na ekranie wywietlacza (patrz rysunek 15.7).
Rysunek 15.7.
Postmodernistyczny
szum na wywietlaczu
sygna poprawnie
zainicjowanego
wywietlacza
graficznego
415
Do rozwizania drugiego zadania uyjemy interfejsu SPI, dziki czemu nasz sposb komunikacji z moduem
wywietlacza graficznego stanie si w peni profesjonalny. Schemat ukadu, ktry wykorzystamy przy
rozwizywaniu drugiego zadania, przedstawiono na rysunku 15.8.
Rysunek 15.8.
Schemat ukadu
do drugiego zadania
obsugi wywietlacza
graficznego poprzez
interfejs SPI
W trzecim zadaniu pokusimy si o zaprogramowanie rysunku, ktry swoim blaskiem opromieni nas na
lata, a krytykom sztuki odbierze ich krytyczny or. Narysujemy bowiem bohatersk twarz pana Ziutka
(patrz rysunek 15.9).
Rysunek 15.9.
Trzecie zadanie, czyli
twarz pana Ziutka
Zauwamy, e zby pana Ziutka, zgodnie zreszt ze stanem faktycznym, bd mieniy si w 16 podstawowych
kolorach: od bkitu (5 odcieni), poprzez ziele (6 odcieni), a do czerwieni (5 odcieni).
Znamy zadania, wic do dziea!
15.1. Jzyk C
Zagadnienia:
Wysyanie danych do sterownika wywietlacza S65.
Inicjalizacja wywietlacza S65.
Interfejs SPI.
Nowy odcinek opowieci dydaktycznej Sekretny wiat misia Ekrysia, czyli czmy P0.7 z 3V3.
16-bitowe kodowanie kolorw.
Rysowanie prostoktnych obszarw.
416
Zaznajamianie si z obsug wywietlacza S65 zaczniemy od omwienia roli linii czcych wywietlacz
z mikrokontrolerem. Do wysyania danych do sterownika wywietlacza suy linia DAT. Stan wysoki na
linii oznacza wysyanie wartoci 1, stan niski to nic innego, jak wysanie wartoci 0. Oczywicie musimy
poinformowa sterownik wywietlacza, e ustawienie linii DAT jest znaczce. Robi si to poprzez narastajce zbocze CLK (patrz rysunek 15.10).
Rysunek 15.10.
Schemat obsugi linii CS,
CLK i DAT przy wysyaniu
do sterownika wywietlacza
S65 bajtu danych
Dziki doskonaemu rysunkowi 15.10 ucilimy wiadomoci dotyczce wysyania danych do sterownika
wywietlacza S65:
1. Dane wysyamy w paczkach po 8 bitw.
2. Wysyanie bajtu danych jest sygnalizowane stanem niskim linii CS..
3. Dane wysyane s lini DAT w kolejnoci od najstarszego do najmodszego bitu.
4. Wysanie znaczcego bitu danych zostaje potwierdzone narastajcym zboczem linii CLK.
A tyle wywnioskowalimy z jednego maego rysunku? O tak. Rysunek 15.10 naley do naprawd wspaniaych ilustracji. Bystry obserwator atwo zauway w nim take liczby, ktre dadz najwysz wygran
w najbliszym losowaniu Lotto. A tymczasem sprbujmy poznane wiadomoci o wysyaniu danych przeku
we fragment kodu.
W pierwszej kolejnoci zdefiniujemy poczenie linii mikrokontrolera i wywietlacza. Zgodnie z rysunkiem 15.6 powinno ono wyglda tak:
#define
#define
#define
#define
#define
#define
S65_RST
S65_RS
S65_CLK
S65_CS
S65_DAT
S65_BL
1<<16
1<<17
1<<18
1<<19
1<<20
1<<21
Przypominam, e w pierwszym zadaniu nie uywamy interfejsu SPI. Zamy, e definiujemy funkcj o nastpujcej deklaracji:
void Wyslij_dane_S65(int8 dane);
Jej zadaniem bdzie wysanie bajtu danych, danego parametrem dane, do sterownika wywietlacza. W opisie
argumentu podalimy now nazw typu utworzon instrukcj typedef.
typedef unsigned char int8;
Z rysunku 15.10 wiemy, e wysyanie danych musi by poprzedzone wyzerowaniem linii CS. Zakoczenie
wysyania danych zasygnalizujemy wysokim stanem CS. Tak oto rysuje nam si podstawowy szkielet
funkcji Wyslij_dane_S65:
void Wyslij_dane_S65(int8 dane)
{
//sygnalizuj wysyanie danych (poziom niski CS)
IOCLR = S65_CS;
/////////////////////////////////////////////////
//tu bdzie kod wysyania danych
/////////////////////////////////////////////////
417
Wiemy, e wysyanie danych musi odbywa si od bitu najstarszego do najmodszego. Najprostszym, a jednoczenie najszybszym sposobem realizacji tego zamiaru bdzie kolejne testowanie bitw argumentu dane.
Na przykad tak wylemy bit sidmy i szsty:
//bit 7
if(dane & 0x80) IOSET = S65_DAT; else IOCLR = S65_DAT;
IOCLR = S65_CLK;
IOSET = S65_CLK;
//bit 6
if(dane & 0x40) IOSET = S65_DAT; else IOCLR = S65_DAT;
IOCLR = S65_CLK;
IOSET = S65_CLK;
Widzimy, e po kadym ustawieniu linii DAT nastpuje wywoanie narastajcego zbocza na linii CLK.
W ten sposb wylemy wszystkie 8 bitw argumentu dane.
Trzy tajemnicze linie czekaj na sowo prawdy o nich: to RS, RST i BL. Za pomoc pierwszej linii sygnalizujemy wysyanie danych (RS = 0) i rozkazw (RS = 1). Druga z przedstawionych linii posuy nam
wycznie do wystartowania sterownika wywietlacza. Natomiast ustawienie linii BL wcza podwietlenie
matrycy wywietlacza S65. Jej dziaanie jest niezalene od zainicjowania sterownika wywietlacza.
Skoro wiemy ju, jak wysya dane do wywietlacza S65, zatrzymajmy si nad jego uruchomieniem. Inicjalizacja sterownika wywietlacza S65 skada si z 10 punktw i wymaga wysania kilku sekwencji uruchomieniowych. Dwie z tych sekwencji radz umieci w osobnym pliku.
Listing dane15.h
typedef unsigned char int8;
typedef unsigned short int16;
//sekwencje inicjujce S65
int8 kod2[20] = {0xEF, 0x00, 0xEE, 0x04, 0x1B, 0x04, 0xFE, 0xFE, 0xFE, 0xFE,
0xEF, 0x90, 0x4A, 0x04, 0x7F, 0x3F, 0xEE, 0x04, 0x43, 0x06};
int8 kod3[40] = {0xEF, 0x90, 0x09, 0x83, 0x08, 0x00, 0x0B, 0xAF, 0x0A, 0x00,
0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0xEF, 0x00, 0xEE, 0x0C,
0xEF, 0x90, 0x00, 0x80, 0xEF, 0xB0, 0x49, 0x02, 0xEF, 0x00,
0x7F, 0x01, 0xE1, 0x81, 0xE2, 0x02, 0xE2, 0x76, 0xE1, 0x83};
418
IOSET = S65_RS;
IOCLR = S65_RST;
IOSET = S65_RST;
3. Oczekiwanie 1 ms:
Czekaj_ms(1);
5. Oczekiwanie 60 ms:
Czekaj_ms(60);
7. Oczekiwanie 7 ms:
Czekaj_ms(7);
9. Oczekiwanie 50 ms:
Czekaj_ms(50);
Tak oto sterownik wywietlacza S65 zosta zainicjowany. Cho nie naley to do inicjalizacji sterownika, polecam w funkcji startowej wczy podwietlenie wywietlacza.
IOSET = S65_BL;
Pierwsze zadanie moemy uzna za zrealizowane. Oto gotowy kod programu gwnego.
Listing lekcja15_1.c
#include <LPC210x.H>
#include "dane15.h"
#define S65_RST 1<<16
#define S65_RS 1<<17
S65_CLK
S65_CS
S65_DAT
S65_BL
1<<18
1<<19
1<<20
1<<21
void Czekaj_ms(int c)
{
c *= 12000;
while(c > 0) c--;
}
void Wyslij_dane_S65(int8 dane)
{
//sygnalizuj wysyanie danych (poziom niski CS)
IOCLR = S65_CS;
//bit 7
if(dane & 0x80) IOSET = S65_DAT; else IOCLR = S65_DAT;
IOCLR = S65_CLK;
IOSET = S65_CLK;
//bit 6
if(dane & 0x40) IOSET = S65_DAT; else IOCLR = S65_DAT;
IOCLR = S65_CLK;
IOSET = S65_CLK;
//bit 5
if(dane & 0x20) IOSET = S65_DAT; else IOCLR = S65_DAT;
IOCLR = S65_CLK;
IOSET = S65_CLK;
//bit 4
if(dane & 0x10) IOSET = S65_DAT; else IOCLR = S65_DAT;
IOCLR = S65_CLK;
IOSET = S65_CLK;
//bit 3
if(dane & 0x08) IOSET = S65_DAT; else IOCLR = S65_DAT;
IOCLR = S65_CLK;
IOSET = S65_CLK;
//bit 2
if(dane & 0x04) IOSET = S65_DAT; else IOCLR = S65_DAT;
IOCLR = S65_CLK;
IOSET = S65_CLK;
//bit 1
if(dane & 0x02) IOSET = S65_DAT; else IOCLR = S65_DAT;
IOCLR = S65_CLK;
IOSET = S65_CLK;
//bit 0
if(dane & 0x01) IOSET = S65_DAT; else IOCLR = S65_DAT;
IOCLR = S65_CLK;
IOSET = S65_CLK;
void Start_S65()
{
int i;
//ustaw kierunek wyjciowy linii obsugujcych S65
IODIR |= (S65_CS|S65_RS|S65_RST|S65_BL|S65_DAT|S65_CLK);
419
420
//sekwencja startujca
IOSET = S65_CS;
IOSET = S65_CLK;
IOSET = S65_DAT;
IOSET = S65_RS;
IOCLR = S65_RST;
IOSET = S65_RST;
//zaczekaj 1 ms
Czekaj_ms(1);
//sekwencja 1
Wyslij_dane_S65(0xFD);
Wyslij_dane_S65(0xFD);
Wyslij_dane_S65(0xFD);
Wyslij_dane_S65(0xFD);
//zaczekaj 60 ms
Czekaj_ms(60);
//sekwencja 2
for(i=0; i<20; i++) Wyslij_dane_S65(kod2[i]);
//zaczekaj 7 ms
Czekaj_ms(7);
//sekwencja 3
for(i=0; i<40; i++) Wyslij_dane_S65(kod3[i]);
//zaczekaj 50 ms
Czekaj_ms(50);
//sekwencja 4
Wyslij_dane_S65(0x80);
Wyslij_dane_S65(0x01);
Wyslij_dane_S65(0xEF);
Wyslij_dane_S65(0x90);
Wyslij_dane_S65(0);
Wyslij_dane_S65(0);
//wcz podwietlenie
IOSET = S65_BL;
}
int main()
{
//uruchomienie wywietlacza S65
Start_S65();
//ptla nieskoczona
for(;;);
Realizacja pierwszego zadania pozwolia nam lepiej pozna tajniki sterowania wywietlaczem S65. Zapewne przyda si take w sytuacjach, w ktrych bd zawodziy inne prby skomunikowania si ze sterownikiem LS020xxx.
Teraz zrealizujemy to samo zadanie za pomoc interfejsu SPI. I tu na wstpie musz pojawi si pewne
uwagi natury egzystencjalnej. Ot dokumentacja ukadu LPC2106 podaje, e rol linii SSEL jest ustawianie
urzdzenia w tryb master lub slave. Wiadomym te jest, e w trybie master, w wyniku bdu, linia SSEL
musi by zewntrznie podcignita pod napicie 3V3. Pamitajmy o tym, gdy niepodczenie linii
SSEL (wyprowadzenie P0.7) pod rdo napicia jest najczciej popenianym bdem, ktry sprawia, e
interfejs SPI nie dziaa. Pamitajmy rwnie, by lini podczy pod napicie 3V3, a nie 5 V. W drugim
przypadku mikrokontroler potrafi bardzo mocno si rozgrza, do stanu produkowania smrodu wcznie.
421
Nigdy nie sprawdzaem, co dalej z gorcym mikrokontrolerem moe si sta, i do takich prb nie zachcam. Pamitajmy: aby skorzysta z interfejsu SPI, wyprowadzenie P0.7 podczamy pod napicie 3V3, czyli
do listwy P26 na pytce edukacyjnej.
W celu utrwalenia powyszych wskazwek radz obejrze obrazki ilustrujce kilka chwil z ycia Misia
Ekrysia3 (patrz rysunek 15.11).
1<<10
1<<6
1<<4
1<<8
1<<9
1<<11
Geneza powstania imienia Ekry owiana jest mg tajemnicy. Za jego twrc uchodzi legendarny badacz natury
zwierzt Vasco da Vasco. Miaby jakoby w wielki podrnik, spotkawszy przodka Ekrysia, wypowiedzie dwa znamienne
sowa, co prawda naprdce, moe dlatego nieco niedbale, ktre w pewnej parafrazie przetrway do dzi. Sowa te podobno
brzmiay: Nie gry!.
422
2. Wybra prdko pracy interfejsu SPI. Robi si to poprzez przypisanie dzielnika wielkoci
PCLK/SPCCR do rejestru S0SPCCR. Dokumentacja podaje, e minimaln wielkoci moe by 8.
Z tego wynika, e SPI moe pracowa z maksymaln prdkoci 60 000 000/8 = 7 500 000 Hz:
S0SPCCR = 8;
3. Ustawi tryb pracy SPI. Suy do tego rejestr SPCR. Najwaniejsze bity tego rejestru to:
CPOL bit 4. Suy ustawieniu polaryzacji potwierdzania danych lini SCK. Warto 0
oznacza potwierdzanie zboczem narastajcym, warto 1 oznacza potwierdzanie zboczem
opadajcym. Pamitamy sposb wysyania danych do sterownika wywietlacza S65 i domylamy
si, e dla naszych zastosowa bit CPOL powinien by wyzerowany.
MSTR bit 5. Suy konfiguracji pracy SPI jako master (bit = 1) lub slave (bit = 0). W naszym
programie bit MSTR musi by ustawiony (tryb master).
LSBF kierunek wysyania bitw danych. Jeli LSBF = 1, dane s wysyane w trybie LSB
(bit 0 pierwszy), jeli LSBF = 0 dane s wysyane w trybie MSB (bit 7 pierwszy). Zgodnie
z podanym opisem wysyania danych do sterownika wywietlacza S65 dane maj by wysyane
w trybie MSB, czyli bit LSBF powinien by wyzerowany.
Ostatecznie otrzymujemy takie przypisanie:
S0SPCR = 0x20;
Pamitamy, e wysyanie danych do wywietlacza powinno odbywa si przy wyzerowanej linii CS. Mamy
na razie szkielet funkcji Wyslij_dane.
void Wyslij_dane(int8 dane)
{
//sygnalizuj wysyanie danych (poziom niski CS)
IOCLR = S65_CS;
/////////////////////////////////////////
//tu bd instrukcje transmisji danych
/////////////////////////////////////////
//sygnalizuj koniec wysyania danych (poziom wysoki CS)
IOSET = S65_CS;
}
Wysanie danych poprzez interfejs SPI wie si z uyciem jedynie dwu instrukcji. Pierwsza z nich to zaadowanie do rejestru S0SPDR bajtu do wysania.
S0SPDR = dane;
W drugiej instrukcji oczekujemy na potwierdzenie wysania danych. Zakoczenie wysyania danych jest
sygnalizowane ustawieniem bitu SPIF rejestru SPSR. Bit SPIF jest sidmym bitem rejestru SPSR, dlatego
druga instrukcja wysyania danych ma nastpujc posta:
while((S0SPSR&0x80) == 0);
Listing lekcja15_2.c
#include <LPC210x.h>
#include "dane15.h"
#define S65_CS
#define S65_DAT
#define S65_CLK
#define S65_RS
#define S65_RST
#define S65_BL
//P0.7 do 3V3!
1<<10
1<<6
1<<4
1<<8
1<<9
1<<11
void Czekaj_ms(int c)
{
c *= 12000;
while(c > 0) c--;
}
void Start_SPI()
{
PINSEL0 = 0x00005500;
S0SPCCR = 8;
S0SPCR = 0x20;//(transmisja 8-bitowa MSB, tryb Master)
}
void Wyslij_dane(int8 dane)
{
//sygnalizuj wysyanie danych (poziom niski CS)
IOCLR = S65_CS;
//zaaduj dane
S0SPDR = dane;
//zaczekaj na potwierdzenie wysania danych
while((S0SPSR&0x80) == 0);
//sygnalizuj koniec wysyania danych (poziom wysoki CS)
IOSET = S65_CS;
}
void Start_S65()
{
int i;
//ustaw kierunek wyjciowy linii obsugujcych S65
IODIR |= (S65_CS|S65_RS|S65_RST|S65_BL);
//sekwencja startujca
IOSET = S65_CS;
IOSET = S65_CLK;
IOSET = S65_DAT;
IOSET = S65_RS;
IOCLR = S65_RST;
IOSET = S65_RST;
//zaczekaj 1 ms
Czekaj_ms(1);
//sekwencja 1
Wyslij_dane(0xFD);
Wyslij_dane(0xFD);
Wyslij_dane(0xFD);
Wyslij_dane(0xFD);
423
424
//zaczekaj 60 ms
Czekaj_ms(60);
//sekwencja 2
for(i=0; i<20; i++) Wyslij_dane(kod2[i]);
//zaczekaj 7 ms
Czekaj_ms(7);
//sekwencja 3
for(i=0; i<40; i++) Wyslij_dane(kod3[i]);
//zaczekaj 50 ms
Czekaj_ms(50);
//sekwencja 4
Wyslij_dane(0x80);
Wyslij_dane(0x01);
Wyslij_dane(0xEF);
Wyslij_dane(0x90);
Wyslij_dane(0);
//wcz podwietlenie
IOSET = S65_BL;
}
int main()
{
//start moduu SPI
Start_SPI();
//wczenie wywietlacza
Start_S65();
//nieskoczona ptla
for(;;);
Dwa poprzednie zadania mona nazwa rozruchowymi. Czekaj nas programy coraz wiksze, z coraz
liczniejsz grup funkcji. Zasadne wic wydaje si podzielenie programu na kilka plikw. Naszym celem jest
zbudowanie biblioteki obsugi wywietlacza S65. Kolejne etapy na drodze do tego wiatego celu oznacza
bdziemy numerami. Natomiast produkt kocowy, czyli pliki nagwkowe wspaniaej biblioteki funkcji
obsugi wywietlacza S65, nazwiemy po prostu dane.h oraz S65.h.
Jeden z plikw nagwkowych moemy poda ju teraz, z nazw sugerujc ostateczne rozwizanie. To plik
zawierajcy funkcj opniajc.
Listing czekaj.h
void Czekaj_ms(int c)
{
c *= 12000;
while(c > 0) c--;
}
Plik nagwkowy zawierajcy sekwencje startowe sterownika wywietlacza S65 uzupenimy o sekwencj
uruchamiajc rozkaz wypenienia ta kolorem.
Listing dane15_3.h
typedef unsigned char int8;
typedef unsigned short int16;
//sekwencje inicjujce S65
int8 kod2[20] = {0xEF, 0x00, 0xEE, 0x04, 0x1B, 0x04, 0xFE, 0xFE, 0xFE, 0xFE,
0xEF, 0x90, 0x4A, 0x04, 0x7F, 0x3F, 0xEE, 0x04, 0x43, 0x06};
425
int8 kod3[40] = {0xEF, 0x90, 0x09, 0x83, 0x08, 0x00, 0x0B, 0xAF, 0x0A, 0x00,
0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0xEF, 0x00, 0xEE, 0x0C,
0xEF, 0x90, 0x00, 0x80, 0xEF, 0xB0, 0x49, 0x02, 0xEF, 0x00,
0x7F, 0x01, 0xE1, 0x81, 0xE2, 0x02, 0xE2, 0x76, 0xE1, 0x83};
//sekwencja kodu wypenienia
int8 kod_wypelnienia[8] = {0xEF, 0x90, 0x05, 0x04, 0x06, 0x00, 0x07, 0x00};
Funkcje obsugi wywietlacza, take funkcj inicjujc interfejs SPI, umiecimy w pliku S65_15_3.h.
Numerowana nazwa sugeruje, e nie jest to gotowa biblioteka funkcji obsugi wywietlacza. W pliku,
prcz znanych funkcji, znajd si dwie nowe i na nich si teraz skoncentrujmy.
Pierwsza z nowych funkcji zapeni to matrycy wywietlacza jednolitym kolorem. Pierwsze zdanie i ju
nieprawda kolor wcale nie musi by jednolity. Ale o tym za chwil. Funkcja bdzie si nazywaa
Rysuj_tlo_S65 i bdzie pobieraa 3 argumenty skadowe koloru ta:
void Rysuj_tlo_S65(int16 R, int16 G, int16 B);
Na wywietlaczu S65 kolor jest kodowany za pomoc 16-bitowej wartoci, zawierajcej skadowe koloru
czerwonego, zielonego i niebieskiego. Pi najstarszych bitw zawiera skadow koloru czerwonego, bity od
pitego do dziesitego zawieraj skadow zielon, pi najmodszych bitw zawiera skadow koloru niebieskiego (patrz rysunek 15.12).
Rysunek 15.12.
Kodowanie koloru
w standardzie TFT
Przedstawiony sposb kodowania koloru nazywa si kodowaniem w standardzie TFT. Pamitamy, e wysyamy do wywietlacza dane bajtowej wielkoci4. Musimy wic na przekazanych do funkcji argumentach
skadowych koloru wykona dwie operacje umoliwiajce ich wysanie. Po pierwsze z trzech wartoci,
dwch picio- i jednej szeciobitowej, musimy utworzy jedn warto 16-bitow. Na przykad tak:
int16 i;
int8 kolor1, kolor0;
//ustaw kolor
i = (R<<11)|(G<<5)|(B);
Kolor jest przygotowany do wysania. Zanim zajmiemy si jego adowaniem do pamici wywietlacza,
musimy wysa sekwencj bajtw oznaczajc rozkaz wypenienia ta zadanym kolorem. Poniewa wysyamy rozkaz, linia RS musi by w wysokim stanie logicznym.
IOSET = S65_RS;
Sekwencja rozkazu jest umieszczona w pliku nagwkowym dane15_3.h. Dziki zaadowaniu jej do tablicy
moliwe staje si uycie ptli:
for(i=0; i<8; i++) Wyslij_dane(kod_wypelnienia[i]);
Rozkaz wydany, czas na wysanie koloru. Poniewa teraz bdziemy wysya dane sensu stricte, linia RS musi
by wyzerowana.
IOCLR = S65_RS;
Nic nie stoi na przeszkodzie, by do wywietlacza S65 wysya dane wielkoci 16-bitowej. Nie czynimy tego, gdy
mikrokontroler LPC2106 posiada wycznie 8-bitowy interfejs SPI. Mona natomiast sprbowa wysya paczki
wikszych rozmiarw na przykad za pomoc mikrokontrolera LPC2103.
426
Rozdzielczo matrycy 132176 pikseli daje w sumie konieczno zaadowania 23 232 pikseli okrelonym
kolorem. Nie ma sprawy. Zrbmy to.
for(i=0; i<23232; i++)
{
Wyslij_dane(kolor1);
Wyslij_dane(kolor0);
}
To wszystko. To jest namalowane. Posta ptli nasuwa nam od razu myl, e kolor ta nie musi by jednolity.
Rzeczywicie. Wystarczy zmieni zapis na taki:
for(i=0; i<23232; i++)
{
Wyslij_dane(kolor1++);
Wyslij_dane(kolor0);
}
a otrzymamy to pokryte adnie mienicymi si przejciami z koloru zielonego w czerwie. Mona take
adowa dane z tablicy i w ten sposb wywietla obrazy.
Druga z nowych funkcji jest bardzo podobna do pierwszej. Suy do zapenienia fragmentu obszaru matrycy
kolorem czy te kolorami. A poniewa jest to jedyna funkcja tego typu dostpna na wywietlaczu S65,
czyni j to podstawow funkcj rysujc wywietlacza S65.
Deklaracja funkcji jest do rozbudowana.
void Rysuj_obszar_S65(int8 X1, int8 Y1,
int8 X2, int8 Y2,
int16 R, int16 G, int16 B);
Trzy ostatnie parametry funkcji Rysuj_obszar_S65 to oczywicie skadowe koloru. W funkcji zakadamy, e
do obszaru nale take punkty z szerokoci Y2 i wysokoci X2. Dlatego wielko obszaru do zamalowania obliczamy za pomoc wzoru:
obszar = (X2-X1+1)*(Y2-Y1+1);
Teraz powinna nastpi sekwencja rozkazu zamalowania obszaru. Do tej sekwencji wplatamy przekazane przez parametry wsprzdne obszaru do odmalowania. Zwrmy uwag na wiersze 6., 8., 10. i 12.
Wyslij_dane(0xEF);
Wyslij_dane(0x90);
Wyslij_dane(0x05);
Wyslij_dane(0x00);
427
Wyslij_dane(0x08);
Wyslij_dane(Y1);
Wyslij_dane(0x09);
Wyslij_dane(Y2);
Wyslij_dane(0x0A);
Wyslij_dane(X1);
Wyslij_dane(0x0B);
Wyslij_dane(X2);
Poniewa wysyamy rozkaz, musimy pamita, by poinformowa o tej strasznej prawdzie sterownik wywietlacza, a to za pomoc ustawienia wysokiej wartoci linii RS.
Przyjrzyjmy si wysyanej sekwencji:
0xEF, 0x90, 0x05, 0x00, 0x08, Y1, 0x09, Y2, 0x0A, X1, 0x0B, X2
Jest to zbir liczb i parametrw. Co moe by w nim ciekawego? A jednak co moe by. Zwrmy uwag na
bajt czwarty. Ma on warto 0x00. Jest to bajt kierunku rysowania, nazwijmy go bajtem kierunkowym. Jego
moliwe wartoci i zwizany z tym kierunek rysowania obszarw prezentuje rysunek 15.14.
Rysunek 15.14.
Ilustracja wpywu
wartoci bajtu
kierunkowego
na kierunek
rysowania obszarw
Dziki zmianie kierunku rysowania obszarw moemy wybra wygodniejsz dla nas orientacj wywietlacza:
pionow, jak dotychczas, lub poziom.
Ostatnim zadaniem funkcji Rysuj_obszar_S65 powinno by wypenienie obszaru okrelonym kolorem. W ten
sposb mamy gotowy plik S65_15_3.h.
Listing S65_15_3.h
#define S65_CS 1<<10
#define S65_DAT 1<<6
#define S65_CLK 1<<4
#define S65_RS 1<<8
#define S65_RST 1<<9
#define S65_BL 1<<11
//Uwaga! Linia P0.7 do 3V3!
void Start_SPI()
{
PINSEL0 = 0x00005500;
S0SPCCR = 8;
S0SPCR = 0x20;//(transmisja 8-bitowa, tryb Master)
}
void Wyslij_dane(int8 dane)
{
//sygnalizuj wysyanie danych (poziom niski CS)
IOCLR = S65_CS;
//zaaduj dane
S0SPDR = dane;
428
//ustaw kolor
i = (R<<11)|(G<<5)|(B);
kolor0 = i;
kolor1 = i>>8;
//sygnalizuj rozkaz (RS = 1)
IOSET = S65_RS;
//zaaduj kod wypeniania obszaru
for(i=0; i<8; i++) Wyslij_dane(kod_wypelnienia[i]);
//sygnalizuj dane (RS = 0)
IOCLR = S65_RS;
//wypenij kolorem
for(i=0; i<23232; i++)
{
Wyslij_dane(kolor1);
Wyslij_dane(kolor0);
}
429
430
Pozostao nam skorzysta z zasobw pliku S65_15_3.h i zapeni matryc wywietlacza podanymi figurami. Zrobimy to w funkcji main gwnego pliku projektu, noszcego nazw lekcja15_3.c. Musimy pamita,
by najpierw doda zdefiniowane wczeniej pliki nagwkowe do zasobw projektu. Wystarczy, e zasoby
dodamy do pliku gwnego za pomoc dyrektywy include w ten sposb automatycznie zostan dodane do
zasobw projektu.
#include
#include
#include
#include
<LPC210x.H>
"czekaj.h"
"dane15_3.h"
"S65_15_3.h"
By moe bystry obserwator zauway, e funkcj inicjujc interfejs SPI wywoujemy w funkcji Start_S65.
To oznacza, e nie musimy jej umieszcza w funkcji main, wystarczy przecie wywoanie funkcji Start_S65.
Po wystartowaniu wywietlacza S65 na matrycy widzimy rnokolorowy szum. Aby si go pozby, wypenimy to jednolitym kolorem, na przykad zielonym.
Rysuj_tlo_S65(0, 0x3F, 0);
Pamitamy, e parametry funkcji odpowiadaj skadowym koloru czerwonego, zielonego i niebieskiego. Kolor
zielony jest kodowany za pomoc szeciu bitw. Ustawienie wszystkich bitw tworzy liczb 0x3F. Nastpnie
rysujemy dwa niebieskie kwadraty.
Rysuj_obszar_S65(20, 20, 40, 40, 0, 0, 0x1F);
Rysuj_obszar_S65(20, 91, 40, 111, 0, 0, 0x1F);
Niestety przy programowaniu sterownika wywietlacza S65 nie moemy wyda rozkazu w stylu narysuj
trjkt. T i wiele podobnych figur musimy skonstruowa samodzielnie z prostoktnych obszarw. Jeli
w funkcji Rysuj_obszar_S65 zajdzie przypadek, w ktrym X1 = X2, otrzymamy poziom lini. Lini pionow
narysujemy, gdy Y1 = Y2. Trjkt narysujemy z coraz duszych poziomych linii.
for(k=0; k<40; k++)
Rysuj_obszar_S65(50+k, 66-k, 50+k, 66+k, 0x1F, 0, 0);
Mwimy o kwadratach, trjktach, a przecie szkicujemy twarz pana Ziutka. Powinnimy wic mwi o oczach,
nosie i zbach, ktre musimy jeszcze narysowa. Samo naszkicowanie obszarw bdzie atwe. Natomiast podstawowe kolory osigniemy w efekcie przesunicia wartoci pocztkowej 0x1F w kadym przebiegu ptli
o krok w lewo. Popatrzmy na sze pierwszych krokw operacji przesuwania w lewo wartoci 16-bitowej:
0b0000000000011111
0b0000000000111110
0b0000000001111100
0b0000000011111000
0b0000000111110000
0b0000001111100000
=
=
=
=
=
=
0x001F
0x003E
0x007C
0x00F8
0x01F0
0x03E0
Widzimy, e z kodu koloru niebieskiego otrzymalimy kod koloru zielonego. Wreszcie cay program jest gotowy.
Listing lekcja15_3.c
#include
#include
#include
#include
<LPC210x.H>
"czekaj.h"
"dane15_3.h"
"S65_15_3.h"
int main()
{
unsigned int kolor = 0x1F, k;
//uruchomienie wywietlacza S65
Start_S65();
//to w kolorze zielonym
Rysuj_tlo_S65(0, 0x3F, 0);
431
//ptla nieskoczona
for(;;);
15.2. Asembler
Zagadnienia:
Kopoty doskonaego programisty asemblerowego.
Sposb przekazywania parametrw do podprogramw.
Podprogram rysowania obszarw.
Szanowny Czytelniku (waciwie chciaem powiedzie: drogi ekspercie w programowaniu ukadw ARM7
w asemblerze), poznae ju wikszo tajemnic programowania niskopoziomowego ukadw ARM7, co
pozwala Ci pisa dowolnie skomplikowany program. To, jak rwnie fakt, e bdziemy zajmowali si
programami coraz duszymi, sprawia, e nie bd ju w paragrafach asemblerowych zamieszcza
kompletnych listingw budowanych programw. Zamiast tego bdziemy omawia wybrane ciekawsze fragmenty konstruowanego kodu5. Po prostu nie chc, aby niniejszy podrcznik swoj objtoci zacz dorwnywa dzieom Lenina.
Paragraf zaczniemy od kilku uwag oglnych. Ot modych programistw asemblera czsto nurtuj nastpujce pytania:
1. W jaki sposb argumenty powinny by przekazywane do podprogramw? Czy naley uy rejestrw,
czy odkada dane na stos, czy moe umieszcza je pod specjalnym adresem pamici RAM?
2. W jakiego typu kod niskopoziomowy zamieniaj kompilatory nasz kod wysokiego poziomu?
(To waciwie druga posta pierwszego pytania).
3. W jaki sposb wartoci s zwracane z podprogramw?
Naley wiedzie, e nie zawsze sposb radzenia sobie z parametrami przez kompilatory jest optymalny. Wic
odpowied na pytanie drugie wcale nie musi by tosama z odpowiedzi na pytanie pierwsze. Pewne
praktyki s jednak wsplne, przecie kompilatory te zaprojektowali programici.
Najlepsz i najczciej stosowan praktyk, o ile program na to pozwala, jest uycie rejestrw. Wiadomo, e
w efekcie pracy z rejestrami powstaje najszybszy kod. Zarwno argumenty podprogramw (funkcji), jak
i wartoci zwracane przez funkcje powinny by umieszczane w rejestrach. Dopiero w przypadku gdy danych
5
Oczywicie pene wersje programw znajdzie Czytelnik na doczonym do ksiki noniku CD.
432
jest bardzo duo, mona skorzysta ze stosu lub z innego fragmentu pamici RAM. Dissasemblowanie
programw napisanych w jzykach wysokiego poziomu pozwala zauway pewne mechanizmy wsplnie
wystpujce we wszystkich kompilatorach. Na przykad warto zwracana z funkcji jest najczciej umieszczana w najmodszym rejestrze oglnego uytku. W asemblerze PC jest to rejestr AX (EAX), w asemblerze
AVR jest to rejestr R16, wreszcie w asemblerze ARM7 jest to rejestr R0.
Jako si rzeko kod tworzony przez kompilatory nie zawsze jest optymalny. Przeledmy nastpujcy przykad przy zaoeniu, e w jednym z naszych programw wystpi taki kod:
int fun(int a, int b)
{
return a+b;
}
int main()
{
int x = 2, y = 3;
x = fun(x, y);
}
for(;;);
Przymknijmy oko na to, e zaprezentowany kod jest zupenie bezsensowny. Interesuje nas, w jaki sposb
kompilator zakoduje przekazanie parametrw x i y do funkcji fun, a take w jaki sposb obliczona warto zostanie zwrcona do zmiennej x. Program zosta skompilowany kompilatorem uVision3. Po jego zdissasemblowaniu zobaczymy takie dziwy:
0x00000210 E1A02000 MOV
; 5:
return a+b;
0x00000214 E0820001 ADD
; 6: }
; 7:
; 8: int main()
0x00000218 E12FFF1E BX
; 9: {
0x0000021C E92D4010 STMDB
; 10:
int x = 2, y = 3;
; 11:
0x00000220 E3A03002 MOV
0x00000224 E3A04003 MOV
; 12:
x = fun(x, y);
; 13:
0x00000228 E1A01004 MOV
0x0000022C E1A00003 MOV
0x00000230 EBFFFFF6 BL
; 14:
for(;;);
0x00000234 E1A00000 NOP
0x00000238 EAFFFFFE B
R2,R0
R0,R2,R1
R14
R13!,{R4,R14}
R3,#0x00000002
R4,#0x00000003
R1,R4
R0,R3
fun(0x00000210)
0x00000238
R3,#0x00000002
R4,#0x00000003
Zgodnie ze standardem jzyka C do funkcji fun powinny zosta przekazane kopie zmiennych. Tak si rzeczywicie stao. Warto rejestru R4 zostaa skopiowana do rejestru R1, warto rejestru R3 zostaa skopiowana
do rejestru R0.
0x00000228 E1A01004 MOV
0x0000022C E1A00003 MOV
R1,R4
R0,R3
Teraz zachodzi wywoanie funkcji fun. Po skopiowaniu wartoci z R0 do R2 nastpuje zwrcenie obliczonej
sumy do rejestru R0.
0x00000210 E1A02000 MOV
; 5:
return a+b;
0x00000214 E0820001 ADD
R2,R0
R0,R2,R1
433
A w jaki sposb przedstawiony fragment kodu wysokiego poziomu zapisalibymy my, doskonali programici? Po pierwsze wida, e kopiowanie wartoci rejestrw nie jest potrzebne, gdy w funkcji fun nie
wystpuj dziaania modyfikujce wartoci zmiennych, a dokadniej mwic rejestrw. Po drugie w ogle
nie uylibymy funkcji fun, gdy dziaanie caego przedstawionego programu sprowadza si do wykonania
jednej instrukcji sumowania. Tak kod niskopoziomowy napisalibymy my doskonali programici:
;int x = 2, y = 3;
MOV R3,#0x00000002
MOV R4,#0x00000003
;x = fun(x, y);
ADD R3,R4,R3
Wrmy do pierwszego zadania, cho nie rozstajemy si jeszcze ze wiatem programistycznych rozterek. Na
pocztek zdefiniujemy poczenie wywietlacza S65 z ukadem LPC2106, tak jak prezentuje to rysunek 15.6.
S65_RST
S65_RS
S65_CLK
S65_CS
S65_DAT
S65_BL
EQU
EQU
EQU
EQU
EQU
EQU
(1<<16)
(1<<17)
(1<<18)
(1<<19)
(1<<20)
(1<<21)
Z podanego opisu moemy wyczyta, e rejestr R4 jest uywany do przekazywania argumentu do podprogramu
oczekujcego oraz do podprogramu wysyajcego dane do wywietlacza. Zajmijmy si drugim z wymienionych podprogramw. Niech si nazywa Wyslij_dane. Wiadomo, e transfer danych powinien by zasygnalizowany niskim stanem linii CS.
Wyslij_dane
;sygnalizuj wysyanie danych (poziom niski CS)
LDR R0, =S65_CS
STR R0, [R2]
A teraz przejdmy do operacji testowania bitw rejestru R4. Dlaczego R4? Jak ju wspomnielimy, za
porednictwem tego rejestru s bowiem przenoszone dane do podprogramu Wyslij_dane. Popatrzmy na
sposb testowania bitw 7 i 6:
;testuj 7 bit
TST R4, #0x80
;jeli bit ustawiony IOSET = S65_DAT
STRNE R0, [R1]
;jeli bit wyzerowany IOCLR = S65_DAT
STREQ R0, [R2]
;IOCLR = S65_CLK
STR R3, [R2]
;IOSET = S65_CLK
STR R3, [R1]
;testuj bit 6
TST R4, #0x40
;jeli bit ustawiony IOSET = S65_DAT
STRNE R0, [R1]
;jeli bit wyzerowany IOCLR = S65_DAT
434
STREQ R0, [R2]
;IOCLR = S65_CLK
STR R3, [R2]
;IOSET = S65_CLK
STR R3, [R1]
Dane do wysania s przenoszone za porednictwem rejestru R4. Oczywicie wysanie danych musi by poprzedzone wyzerowaniem linii CS. Nastpnie bajt z rejestru R4 jest adowany do rejestru S0SPDR o adresie
0xE0020008. Skopiowanie bajtu realizuje instrukcja STRB. W ptli oczekujcej na potwierdzenie wysania
danych testujemy bit SPIF, wykonujc ptl, dopki jest on wyzerowany.
Przystpujemy do realizacji trzeciego zadania. Zdefiniujemy podprogramy zapeniajce obszary kolorem.
Bd to:
Rysuj_tlo podprogram zapeniajcy jednolitym kolorem to.
Rysuj_obszar podprogram zamalowujcy jednolitym kolorem okrelony obszar.
Od razu nasuwa si pytanie o sposb przenoszenia parametrw do podprogramu. Proponuj uy rejestru R4
do przenoszenia parametru koloru, rejestru R5 do przenoszenia wsprzdnych zamalowywanego obszaru.
Kod koloru bdzie umieszczany w modszych 16 bitach rejestru R4. Rezygnujemy tym samym z uatwienia,
ktrego uywalimy w jzyku C, pozwalajcego umieszcza skadowe koloru w osobnych parametrach
R, G i B. Upraszczamy sposb przenoszenia parametrw do podprogramu, gdy zaley nam na otrzymaniu jak
najszybszego kodu. Popatrzmy na asemblerow posta procedury Rysuj_tlo:
Rysuj_tlo
;zapamitaj na stosie adres powrotu z procedury
STR R14,[R13,#-0x0004]!
435
Zauwamy, e zachowujemy na stosie nie tylko adres powrotu z podprogramu, ale te warto znajdujc si
w R4 (kolor). Zapamitanie wartoci rejestru R4 jest konieczne z tego wzgldu, e uywamy tego rejestru do
przenoszenia parametrw do innych podprogramw (na przykad w R4 podajemy liczb milisekund dla procedury Czekaj_ms). Bajty koloru s dekodowane za pomoc instrukcji ROR.
ROR R4, #8
BL Wyslij_dane
ROR R4, #24
BL Wyslij_dane
Pierwsze uycie instrukcji ROR pozwala otrzyma starszy bajt 16-bitowego koloru. Nastpne uycie instrukcji ROR z obrotem 24 bitw powoduje otrzymanie wartoci rejestru R4 w pierwotnej postaci (wykonalimy peny obrt bitw rejestru).
Czy zaprezentowany podprogram mgby wyglda inaczej? Oczywicie! Przedstawione rozwizania nie
stanowi jakiego ostatecznego i jedynie poprawnego algorytmu budowania kodu asemblerowego. Zapewniam
Ci, szanowny Czytelniku, e wkrtce wypracujesz wasny styl pisania programw w asemblerze. I bardzo
dobrze, gdy czsto tak jest, e t sam rzecz mona wykona na kilka sposobw i kady jest rwnie dobry.
Prawdziwym wyzwaniem jest dla nas definicja podprogramu zamalowujcego okrelony obszar. Poniewa
wsprzdne obszaru nie bd przekraczay wielkoci 1 bajtu, proponuj przenosi je w rejestrze R5, wedug
nastpujcego schematu:
0x|X2|X1|Y2|Y1
436
Jak wida, w dwch najmodszych bajtach zostay umieszczone wsprzdne Y zamalowywanego obszaru,
w dwch starszych bajtach umiecilimy wsprzdne X. Jak to dziaa? Zamy, e chcemy zapeni kolorem
obszar o wsprzdnych X1 = 20, Y1 = 91, X2 = 40, Y2 = 111. Zanotujmy podane wartoci w postaci
szesnastkowej:
X1 = 0x14,
Y1 = 0x5B,
X2 = 0x28,
Y2 = 0x6F.
Przekazanie parametrw odbdzie si zatem za pomoc przypisania:
LDR R5, =0x28146F5B
I znw nasuwa si pytanie o to, czy nie moglimy parametrw obszaru przekazywa inaczej, na przykad za
pomoc czterech rejestrw lub czterech bajtw pamici RAM. Oczywicie moglimy. Kiedy stosuje si pewne
rozwizanie programistyczne, zawsze naley zastanowi si nad korzyciami i ewentualnymi stratami.
Niewtpliw korzyci zaproponowanego rozwizania jest oszczdno w zastosowaniu rejestrw. A jakie
straty czy raczej to waciwsze sowo trudnoci wynikaj z kodowania wsprzdnych za pomoc
jednego rejestru? Trudnoci w programowaniu, to po pierwsze. Po drugie trudnoci w dekodowaniu wsprzdnych. Przecie bdziemy chcieli na bazie podanych wsprzdnych obliczy pole obszaru do zamalowania.
W tym celu konieczne bdzie odczytanie wartoci z R4 poprzez zastosowanie przesunicia bitowego. Mimo
wszystko uwaam, e korzyci ze stosowania tylko jednego rejestru przewyszaj wynikajce z tego trudnoci.
Zanalizujmy kod obliczajcy pole obszaru do zamalowania. Zakadamy przy tym, e X2
Odpowiedni wzr znamy ju z programu napisanego w jzyku C.
X1 oraz Y2
Y1.
obszar = (X2-X1+1)*(Y2-Y1+1);
Zaczniemy od obliczenia czonu (X2-X1+1). W tym celu do rejestru R0 zaadujemy warto X2.
MOV R0, R5, LSR #24
Przed zaadowaniem danych bity rejestru R4 zostay przesunite o 24 miejsca w prawo. Skutkiem zastosowania operacji LSR jest wyzerowanie najstarszych bitw. Dziki temu w rejestrze R0 znajdzie si liczba, w ktrej
ustawionych moe by tylko 8 najmodszych bitw. Do rejestru R6 zaadujemy warto X1.
MOV R6, R5, LSR #16
AND R6, R6, #0xFF
Tym razem, aby otrzyma warto bajtow, konieczne byo zastosowanie iloczynu bitowego. Obliczamy
rnic X2X1, nastpnie dodajemy do niej warto 1.
;R6 = R0R6+1
SUB R6, R0, R6
ADD R6, R6, #1
Wreszcie obliczamy pole powierzchni obszaru do zamalowania. Wynik umiecimy w rejestrze R6.
;R6 = R0*R6 = (Y2Y1+1)*(X2X1+1)
MUL R6, R0, R6
437
438
Kiedy rysuje si obszary o bardziej skomplikowanym ksztacie, naley odpowiednio adowa wartoci wsprzdnych do rejestru R4. Na przykad w taki sposb narysujemy trjkt:
;narysuj czerwony trjkt
;warto pocztkowa R7 (k)
LDR R7, =0
petla_trojkat
;for(k=0; k<40; k++)
; Rysuj_obszar_S65(50+k, 66-k, 50+k, 66+k, 0x1F, 0, 0);
;kolor
LDR R4, =0xF800
;wsprzdne obszaru
;X2
LDR R5, =50
;dodaj warto k
ADD R0, R5, R7
;kopiuj wynik do X2
MOV R5, R0
;przesu o 8 miejsc w lewo
LSL R5, #8
;X1
ORR R5, R5, R0
;przesu o 8 miejsc w lewo
LSL R5, #8
;Y2 = 66+k
ORR R5, R5, #66
ADD R5, R5, R7
;przesu o 8 miejsc w lewo
LSL R5, #8
;Y1 = 66k
ORR R5, R5, #66
SUB R5, R5, R7
BL Rysuj_obszar
;inkrementuj zmienn ptli
ADD R7, R7, #1
15.3. wiczenia
1. Narysuj na wywietlaczu S65 cztery zagniedajce si prostokty (patrz rysunek 15.15).
Rysunek 15.15.
Rysunek majcy si
pojawi na wywietlaczu
S65 w wyniku wykonania
wiczenia 1.
2. Zaprogramuj wywietlacz S65 tak, aby na matrycy wida byo poruszajcy si w pionie kwadrat
(patrz rysunek 15.16).
Rysunek 15.16.
W wyniku wykonania
wiczenia 2.
na wywietlaczu powinien
pojawi si kwadrat
poruszajcy si w pionie
(z gry na d i z dou
do gry)
439
Serwomechanizmy
Wywietlacze alfanumeryczne
Kompilatory
Obsuga przerwa
Cena: 77,00 z
Pawe Borkowski
Pawe Borkowski
5424
AVRAR7.indd 1
29-04-10 12:50:27