81_84.PDF

(105 KB) Pobierz
C dla mikrokontrolerów 8051, część 2
K U  R S
Drug¹ czÍúÊ kursu poúwiÍcimy omÛwieniu
część 2
przyk³adowego programu, ktÛry umoøliwia wyúwietlanie informacji
na standardowym alfanumerycznym wyúwietlaczu LCD, sterowanym
poprzez interfejs 4-bitowy.
Sterowanie wyœwietlaczem LCD w trybie 4-bitowym
Zaczynamy od bardzo uøyteczne-
go programu. Przyda siÍ on nam
w†przysz³oúci, dziÍki czemu czas po-
úwiÍcony na naukÍ nie bÍdzie zmar-
nowany. Analizuj¹c kod poszczegÛl-
nych fragmentÛw programu (kod
ürÛd³owy przedstawiono na list. 1 )
roz³oøymy go na kawa³eczki. To naj-
lepsza droga do poznania ca³ego pro-
gramu.
Na pocz¹tku znajduj¹ siÍ dekla-
racje. Wybieramy model pamiÍci
( #pragma SMALL ), do³¹czamy w³aú-
ciw¹ definicjÍ rejestrÛw mikroproce-
sora ( #include <reg51.h> ), nastÍpnie
okreúlamy, ktÛre bity steruj¹ wy-
úwietlaczem ( sbit ), jakie definicje
znakÛw zapiszemy do wyúwietlacza
itp. ZwrÛÊmy uwagÍ na trochÍ
odmienny, niø w†innych jÍzykach
programowania, opis bitu portu. Se-
paratorem pomiÍdzy nazw¹ portu,
a†numerem bitu nie jest znak krop-
ki, lecz umowny symbol potÍgi. S³o-
wo kluczowe sbit umieszcza nasz¹
definicjÍ w†rejestrze funkcji specjal-
nych SFR, w†obszarze adresowania
bitowego.
Przyjrzyjmy siÍ zawartoúci tablicy
z†definicjami znakÛw uøytkownika,
ktÛre bÍd¹ wprowadzane do pamiÍci
CG-ROM ( Character-Graphics ROM )
sterownika wyúwietlacza. Zauwaømy,
øe jej deklaracja zawiera wiele istot-
nych informacji dla naszego progra-
mu, praktycznie w†jednej linijce:
- okreúlony zostaje typ elementÛw
tablicy, w†tym przypadku char
(czyli element jednobajtowy),
- tablica zostaje umieszczona w†pa-
miÍci programu mikrokontrolera
(s³owo code ),
- tablica otrzymuje nazwÍ symbolicz-
n¹ ( CGRom ) i†okreúlona zostaje
liczba jej elementÛw ( 65 ),
- elementom tablicy nadawana jest
wartoúÊ sta³a.
Pierwsz¹ z†funkcji, ktÛr¹ napotka-
my analizuj¹c program, jest Delay .
Jest to zwyk³a pÍtla, ktÛra absorbu-
je mikrokontroler na wielokrotnoúÊ
oko³o 1†milisekundy. Tak stanie siÍ
tylko wtedy, gdy uøyjemy rezonato-
ra kwarcowego 7,3728MHz. Jeúli sto-
sujemy inny kwarc, procedura wy-
maga zmiany. Zmieni siÍ bowiem
czas potrzebny na wykonanie pÍtli.
S³owo void przed definicj¹ funkcji
oznacza, øe funkcja nie zwraca øad-
nych wartoúci jako rezultatu dzia³a-
nia. Tutaj wyjaúnienie: funkcja w†jÍ-
zyku C†moøe zwracaÊ tylko jedn¹
wartoúÊ. Nie moøe zwrÛciÊ ich kil-
ku tak, jak procedura jÍzyka Pascal
poprzez var . Jeúli zachodzi potrze-
ba, aby funkcja zwraca³a wiÍcej niø
jeden wynik dzia³ania, moøna to
zrobiÊ na przyk³ad przekazuj¹c, jako
argument funkcji wskaüniki do
zmiennych. WÛwczas obliczenia wy-
konywane s¹ bezpoúrednio na
zmiennych ürÛd³owych. Dzia³ania
wewn¹trz funkcji, o†ile nie s¹ wy-
konywane na wskaünikach, wykony-
wane s¹ na kopiach argumentÛw
przekazywanych w wywo³aniu
funkcji i†dotycz¹ wy³¹cznie zmien-
nych lokalnych zawartych pomiÍdzy
nawiasami klamrowymi {}, oznacza-
j¹cymi jej pocz¹tek i†koniec.
Parametr unsigned int k jest to
po prostu liczba milisekund do ìod-
czekaniaî. S³owo unsigned oznacza,
øe liczba k jest dwubajtow¹ liczb¹
bez znaku, czyli przyjmuje wartoúci
tylko dodatnie. Cia³o funkcji zawiera
rÛwnieø deklaracje zmiennych pomoc-
niczych: j oraz k . Pos³uø¹ one do
budowy pÍtli for . Interesuj¹cy jest
w†jÍzyku C jej zapis: for (j = 0; j†<
k; j++) , co oznacza:
- wstaw do zmiennej j liczbÍ 0 ( j†= 0; );
- dopÛki j jest mniejsze od k ( j <
k; ) zwiÍkszaj wartoúÊ j o† 1 ( j++ ),
wykonuj dzia³anie opisane za na-
wiasem (w tym przypadku jest to
nastÍpna pÍtla for ).
ZwrÛÊmy uwagÍ, øe o†ile w†RC-
51, przed deklaracj¹ typu int musi-
my uøyÊ s³owa unsigned , gdy ma to
byÊ liczba bez znaku, o†tyle s³owo
to jest zbÍdne w†przypadku typu
char . Domyúlnie kompilator zak³ada,
øe chodzi o†liczbÍ unsigned char .
Uwaga: jest to cecha kompilatora RC-
51 firmy Raisonance. Uøywaj¹c inne-
go moøna siÍ napotkaÊ odmienne
rozwi¹zania (np. firma Keil stosuje
typ uchar ). Oczywiúcie, moøna przed
typem char dopisaÊ s³owo unsigned .
WÛwczas jest to zgodne ze specyfi-
kacj¹ ANSI C i†prawdopodobnie bÍ-
dzie dzia³aÊ tak samo, bez wzglÍdu
na typ uøytego kompilatora.
Po Delay wystÍpuje funkcja Wri-
teByteToLcd . Tak jak Delay , jest to
funkcja typu void . Jej zadaniem jest
zapisanie jednobajtowej liczby X do
rejestru wyúwietlacza. Funkcja doko-
nuje podzia³u bajtu na po³Ûwki
i†zapisuje je w†bezpieczny sposÛb -
wykorzystuj¹c tylko bity b4..b7 i†nie
uszkadzaj¹c zawartoúci b0..b3 - do
portu PORT. Przeúledümy ten
proces.
DziÍki funkcji sumy bitowej OR
cztery najstarsze bity portu PORT,
w†tym przypadku zadeklarowanego ja-
ko P2, s¹ ustawiane na ì1î. Zapis
PORT |= 0xF0 moøna bowiem prze-
kszta³ciÊ na rÛwnowaøny mu
PORT=PORT | 0xF0 . W³aúciwy zapis
zmiennej do portu nastÍpuje dziÍki
funkcji AND, jednak po uprzednim
ustawieniu dolnej po³Ûwki zapisywa-
nego bajtu na wartoúÊ ì1î (X |
0x0F). Zapis:
PORT &= (X | 0x0F);
moøna roz³oøyÊ na nastÍpuj¹c¹ sek-
wencjÍ dzia³aÒ:
temp = X | 0x0F; //mlodsze 4 bity
//X przyjmują wartość “1”
PORT = PORT & temp;//mlodsze 4 bity
//portu PORT pozostają niezmienione
//górne przyjmują wartość X
Nawias w wyraøeniu PORT &= (X
| 0x0F) jest konieczny, poniewaø su-
ma bitowa OR musi byÊ wykonana
przed iloczynem zapisuj¹cym po³Ûw-
kÍ bajtu do portu mikrokontrolera.
Identycznie postÍpujemy z†doln¹ po-
³Ûwk¹ bajtu z†tym, øe wykonywane
jest przesuniÍcie w†lewo (o†4 pozy-
cje) bitÛw zmiennej X ( X†<<= 4 , to
znaczy X†= X†<< 4 ).
Funkcja podczas zapisywania da-
nych do LCD nie sprawdza stanu fla-
gi busy wyúwietlacza zak³adaj¹c, øe
po 1†milisekundzie wszystkie opera-
cje wykonywane przez kontroler wy-
úwietlacza zostan¹ zakoÒczone. Wy-
Elektronika Praktyczna 7/2002
81
32267170.001.png
K U  R S
wo³anie Delay(1) wprowadza koniecz-
ne opÛünienie.
Kolejnymi s¹ funkcje o†nieco
przyd³ugich nazwach WriteToLcdCtrl-
Register i† LcdWrite . Ich zadaniem
jest zapisywanie parametru X do pa-
miÍci sterownika LCD, co wymaga
wygenerowania odpowiedniej kombi-
nacji sygna³Ûw steruj¹cych. Obie fun-
kcje korzystaj¹ z†omÛwionej wczeúniej
funkcji WriteByteToLcd . Poniewaø
okreúliliúmy w†deklaracjach, øe zmien-
ne LcdReg , LcdRead i† LcdEnable
bitami portu wyjúciowego mikrokont-
rolera, podstawienie wartoúci ì1î lub
ì0î odpowiada rozkazom asemblera
SETB i† CLR . Prawid³owy (i szczegÛl-
nie uøyteczny, gdy mamy do czynie-
nia z†duø¹ liczb¹ zmiennych) jest
rÛwnieø zapis LcdReg = LcdRead =
0; . Kompilator podzieli go na poje-
dyncze operacje SETB i† CLR . Zapis
w†takiej postaci nie ma wiÍc wp³y-
wu na wielkoúÊ generowanego kodu
wynikowego, poprawia jednak czytel-
noúÊ programu.
Dalej w listingu wystÍpuj¹ linie
z†tymi samymi funkcjami. Nie oma-
wian¹ dotychczas spotkamy dopiero
w† GotoXY . Jej rol¹ jest obliczenie
i†ustawienie w³aúciwego dla pozycji
kursora x , y adresu zapisu bajtÛw do
wyúwietlacza. Wykorzystuje ona pole-
cenie switch do rozpatrzenia poszcze-
gÛlnych moøliwych wartoúci y i†wy-
boru odpowiedniej akcji:
switch (y)
{
List. 1
/************************************************
Obsluga wyswietlacza LCD w trybie 4 bity
RC-51 Raisonance
Przykladowy program w jezyku C dla EP
-------------------------
jacek.bogusz@ep.com.pl
*************************************************/
// wybór modelu pamieci
#pragma SMALL
// dolaczenie definicji rejestrów ‘51
#include <reg51.h>
// definicje znaków specjalnych dla wyswietlacza LCD
char code CGRom[65] = {
0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,
// “kratka”
0x00
0xC0,0xC0,0xFF,0xF1,0xF1,0xF1,0xFF,0xC0,
// pusty kwadrat 0x01
0xC0,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,
// kwadrat zacz. 0x02
0xE0,0xFF,0xFF,0xFF,0xE0,0xE0,0xE0,0xE0,
// linia
0x03
0xFF,0xFF,0xF9,0xF3,0xE7,0xF3,0xF9,0xFF,
// znak w lewo 0x04
0xFF,0xFF,0xF3,0xF9,0xFC,0xF9,0xF3,0xFF,
// znak w prawo 0x05
0xFF,0xFF,0xFB,0xF1,0xE4,0xEE,0xFF,0xFF,
// znak w góre 0x06
0xFF,0xFF,0xFF,0xEE,0xE4,0xF1,0xFB,0xFF,
// znak w dól
0x07
0x00};
// port,do którego podlaczono wyswietlacz LCD
#definePORT P2
// 4 najstarsze bity, to bity danych, 4 mlodsze moga byc w dowolny sposób skonfigurowane
// jako sterujace
// po zmianie definicji moga to byc równiez 2 rózne porty,jednak w programie przykladowym
// zakladam wykorzystanie tylko jednego z portów mikrokontrolera
// bity sterujace LCD
sbit LcdEnable = PORT^0;
sbit LcdRead = PORT^3;
sbit LcdReg = PORT^1;
// opóznienie okolo k*1 milisekundy (dla kwarcu 7,3728MHz)
void Delay (unsigned int k)
{
unsigned int i,j;
for (j = 0; j < k; j++)
for (i = 0; i <= 296; i++);
}
// zapis bajtu do lcd, osobna procedura dla zmniejszenia objetosci kodu wynikowego
void WriteByteToLcd(char X)
{
LcdEnable = 1;
PORT |= 0xF0; // ustawienie górnej polówki portu PORT na “1”
PORT &= (X | 0x0F); // “bezkolizyjny” zapis 1-szej polówki bajtu (przez funkcje logiczna)
LcdEnable = 0;
case 0:
x += 0x80;
break ;
case 1:
x += 0xC0;
break ;
case 2:
x += 0x94;
break ;
case 3:
x += 0xD4;
// zapis do wyswietlacza (opadajace zbocze sygnalu E)
LcdEnable = 1; // zapis 2-giej polówki bajtu
X <<= 4; // przesuniecie 4x w lewo
PORT |= 0xF0; // ustawienie górnej polówki portu PORT na “1”
PORT &= (X | 0x0F); // zapis 2-giej polówki bajtu i maskowanie 4 mlodszych bitów
LcdEnable = 0;
// opadajace zbocze E - zapis do LCD
Delay(1);
}
// zapis bajtu do rejestru kontrolnego LCD
void WriteToLcdCtrlRegister(char X)
{
LcdReg = LcdRead = 0; // ustawienie sygnalów sterujacych
WriteByteToLcd(X);
}
}
Z poleceniem switch úciúle s¹
zwi¹zane s³owa kluczowe case i† bre-
ak . Case ma znaczenie takie, jak ety-
kieta danego warunku, a† break przery-
wa rozpatrywanie warunkÛw. Jeúli nie
uøyjemy polecenia break , wÛwczas na-
st¹pi przejúcie do nastÍpnego warunku
i†jego rozpatrzenie. W†naszym przypad-
ku jest to tylko strata czasu. Jedynym
zadaniem funkcji GotoXY jest bowiem
zwiÍkszenie wartoúci x tak, aby wska-
zywa³a poø¹dany adres - nie ma po-
trzeby dalszego analizowania zmiennej
y . Jeúli nasz y bÍdzie mia³ wartoúÊ 0,
wÛwczas do wartoúci x zostanie doda-
na liczba 80H. Jeúli 1†- to C0H, jeúli
2 to 94H i†tak dalej.
Kilka s³Ûw komentarza. Przecho-
dzenie od jednego przypadku do dru-
// zapis bajtu do pamieci obrazu
void LcdWrite(char X)
{
LcdReg = 1;
// ustawienie sygnalów sterujacych
LcdRead = 0;
LcdEnable = 1;
WriteByteToLcd(X);
}
// czyszczenie ekranu LCD
void LcdClrScr(void)
{
WriteToLcdCtrlRegister(0x01);
}
// inicjalizacja wyswietlacza LCD w trybie 4 bity
void LcdInitialize(void)
{
char i;
Delay(15);
P0 = 0x0F;
// wyzerowanie linii LcdReg,LcdRead,LcdEnable
82
Elektronika Praktyczna 7/2002
32267170.002.png
K U  R S
for (i = 0; i<3; i++)
{
giego budzi trochÍ w¹tpliwoúci. Nie-
w¹tpliwie zalet¹ jest to, øe moøna
definiowaÊ wiele rÛønych warunkÛw
dla jednej akcji. Jednak taka kon-
strukcja programu, ktÛra umoøliwia
przechodzenie od warunku do warun-
ku, jest bardzo podatna na ìrozsypa-
nieî siÍ podczas jej modyfikacji.
Z†wyj¹tkiem wielu etykiet dla poje-
dynczej akcji, przechodzenie przez
przypadki, powinno byÊ stosowane
bardzo oszczÍdnie i†zawsze opatrzone
komentarzem. Do dobrego stylu pro-
gramowania naleøy wstawianie break
po ostatniej instrukcji ostatniego
przypadku, mimo øe nie jest to ko-
nieczne.
Funkcja WriteTextXY wykorzystu-
je wskaünik. Jest to wskaünik do ele-
mentu typu char . Jego definicjÍ mo-
øemy bardzo ³atwo odrÛøniÊ po sym-
bolu * . Zauwaømy, øe do funkcji ja-
ko parametr nie jest przekazywany
tekst do wyúwietlenia, a†jedynie
wskazanie (adres) do miejsca w†pa-
miÍci RAM (lub ROM), gdzie ten
tekst zosta³ umieszczony. Wskaünik
ma rozmiar tylko dwÛch bajtÛw, nie
tak jak tekst, ktÛry moøe zaj¹Ê znacz-
nie wiÍcej komÛrek pamiÍci. Opera-
cja S++; przesuwa wskazanie na na-
stÍpny znak w†³aÒcuchu. Kompilator
sam dba o†to, aby zwiÍkszanie
wskaünika powodowa³o wskazanie na
nastÍpny znak. Nie musisz przejmo-
waÊ siÍ liczb¹ bajtÛw inkrementacji
jeøeli wskaünik ma przypisane wska-
zanie do okreúlonego typu elementu.
PÍtla while koÒczy siÍ, gdy wskaü-
nik S pokaøe znak o†kodzie 0. Znak
ten umieszczany jest przez kompila-
tor zawsze na koÒcu tekstu. RÛwno-
czeúnie z† S zwiÍkszana jest wspÛ³-
rzÍdna x . Jeúli wartoúÊ x przekroczy
maksymaln¹ liczbÍ znakÛw w†wier-
szu, nastÍpuje zwiÍkszenie y i†przej-
úcie do nastÍpnej linii na wyúwietla-
czu LCD.
Podobnie jest realizowana funkcja
DefineSpecialCharacters , ale jest
ona nieco prostsza, bo nie oblicza
øadnych wartoúci x†i†y, a†jedynie
przesuwa wskazania na nastÍpny bajt
tablicy. RÛwnieø i†tutaj w†pÍtli whi-
le napisaÊ moøna warunek while
(*ptr ), poniewaø pojawienie siÍ zna-
ku o†kodzie 0, while traktuje jako
warunek koÒca (0 jest rÛwnowaøne
false ). Jednak dla wiÍkszej czytelnoú-
ci programu i†wyraünego zaakcento-
wania w†jaki sposÛb koÒczy siÍ tab-
lica definicji, zosta³ uøyty zapis whi-
le (*ptr != 0) .
W†funkcji DefineSpecialCharac-
ters znaleüÊ moøemy jeszcze dwie
nowe konstrukcje, ktÛrych nie uøy-
waliúmy wczeúniej. W wywo³aniu
funkcji DefineSpecialCharacters
znajduj¹cym siÍ w programie
LcdEnable = 1;
// impuls na E
PORT &= 0x3F;
// ustawienie wartosci inicjujacej
LcdEnable = 0;
Delay(5);
}
LcdEnable = 1;
// wpisanie wartosci 2 do rejestru kontrolnego
PORT &= 0x2F;
// tylko “górne” 4 bity
LcdEnable = 0;
Delay(1);
WriteToLcdCtrlRegister(0x28);
// interfejs 4 bity,znaki 5x7
WriteToLcdCtrlRegister(0x08);
// wylaczenie LCD
WriteToLcdCtrlRegister(0x01);
// kasowanie ekranu, powrót do pozycji home
WriteToLcdCtrlRegister(0x06);
// przesuwanie kursora z inkrementacja
WriteToLcdCtrlRegister(0x0C);
// zalaczenie wyswietlacza
}
// ustawia kursor na wspólrzednych x,y
void GotoXY(char x, char y)
{
switch (y)
// obliczenie o ile nalezy zwiekszyc x w zaleznosci od wartosci y
{
case 0:
x += 0x80; // x = x + 0x80
break;
case 1:
x += 0xC0; // x = x + 0xC0
break;
case 2:
x += 0x94; // x = x + 0x94
break;
case 3:
x += 0xD4; // x = x + 0xD4
break;
}
WriteToLcdCtrlRegister(x);
}
// wyswietla tekst na wspólrzednych x, y
void WriteTextXY(char x, char y, char *S)
{
while (*S)
// petla dziala dotad, az napotkany zostanie znak konca lancuch (/0)
{
GotoXY(x, y); // wyliczenie adresu dla znaku
LcdWrite(*S); // wyswietlenie pojedynczego znaku
x++;
// nastepna pozycja x na ekranie
S++;
// nastepna pozycja wskaznika, tzn. nastepny znak napisu
if (x > 19)
// jesli x>19 to nastepna linia
{
x = 0;
y++;
}
}
}
// wyświetla tekst rozpoczynając od aktualnego położenia kursora
void WriteText(char *S)
{
while (*S)
// petla dziala dotad,az napotkany zostanie znak konca lancucha (/0)
{
LcdWrite(*S); // wyswietlenie pojedynczego znaku
S++;
}
}
// definiowanie znaków z tablicy CGRom
void DefineSpecialCharacters(char *ptr)
{
WriteToLcdCtrlRegister(0x40); // ustawienie trybu definicji
while (*ptr != 0) // petla wykonywana do napotkania znaku konca tablicy
{
LcdWrite(*ptr); // zapis znaku do lcd cgram
ptr++;
// nastepna pozycja tablicy (wskaznika)
}
WriteToLcdCtrlRegister(0x80);
// przelaczenie do trybu wyswietlania
}
// program glówny
void main(void)
{
char ix = 1, iy = 1, x, y, i = 0;
LcdInitialize();
DefineSpecialCharacters(&CGRom);
while (1)
{
WriteTextXY(x, y, “ “);
if (ix == 1) x++; else x--;
if (iy == 1) y++; else y--;
if (x == 19) ix = 0;
if (x == 0) ix = 1;
if (y == 3) iy = 0;
if (y == 0) iy = 1;
WriteTextXY(x, y, 0x01);
Delay(50);
}
}
Elektronika Praktyczna 7/2002
83
32267170.003.png
K U  R S
g³Ûwnym, znaleüÊ moøemy pewn¹
konstrukcjÍ, ktÛrej nie uøywaliúmy
wczeúniej. Jest to przypisanie
wskaünikowi ptr adresu tablicy
CGRom . Jednoargumentowy operator
& tym razem nie oznacza iloczynu -
podaje adres tablicy CGRom w
pamiÍci mikrokontrolera
Jak juø wspomnia³em przy okazji
omawiania przerwaÒ, program g³Ûw-
ny w†C jest to funkcja o†nazwie
main . W†programach pisanych dla
mikrokontrolerÛw najczÍúciej jest ona
typu void z†pust¹ list¹ parametrÛw
(rÛwnieø void ). Naleøy jednak pamiÍ-
taÊ, øe wykonywanie programu napi-
sanego dla mikrokontrolera nigdy nie
moøe siÍ skoÒczyÊ. Nawet jeúli zro-
bi³ on juø swoje i†nie ma øadnych
dalszych zadaÒ do realizacji, to fun-
kcjÍ main naleøy zakoÒczyÊ pÍtl¹
nieskoÒczon¹ tak¹, jak: while(1) albo
for(;;) . Mikrokontroler nie posiada
bowiem øadnego systemu operacyjne-
go takiego jak DOS, ktÛry po zakoÒ-
czeniu pracy programu przejmie kon-
trolÍ.
kilkuset linii programu tego paramet-
ru, ktÛry ma byÊ zmieniony? Odpo-
wiedzi¹ na tak postawione pytania s¹
tak zwane pliki nag³Ûwkowe ( header
files ), ktÛre umoøliwiaj¹ podzielenie
programu na mniejsze fragmenty
i†mog¹ zawieraÊ definicje sta³ych oraz
zmiennych uøywanych zarÛwno przez
program g³Ûwny, jak i†przez bibliote-
ki funkcji. W†jÍzyku C, zbiory na-
g³Ûwkowe, wyrÛønia rozszerzenie . h
nazwy (na przyk³ad lcd4bit.h ). Tak
moøe wygl¹daÊ plik nag³Ûwkowy
utworzony dla biblioteki funkcji wy-
úwietlacza LCD z†poprzedniego przy-
k³adu.
// wyświetla tekst od miejsca,
// w którym znajduje się kursor
void WriteText(char *S);
// definiowanie znaków z tablicy
// wskazywanej przez ptr
void DefineSpecialCharacters(char
*ptr);
Jak widaÊ, jest to bardzo krÛtki
zbiÛr tekstowy zawieraj¹cy podstawo-
we definicje zmiennych i†funkcji.
ZbiÛr ten do³¹czamy do programu
g³Ûwnego za pomoc¹ dyrektywy #in-
clude , podobnie jak postÍpowaliúmy
z†definicj¹ rejestrÛw mikrokontrolera
(notabene teø jest to zbiÛr nag³Ûw-
kowy). W†takiej sytuacji, program
ürÛd³owy naszej biblioteki nie moøe
zawieraÊ funkcji main() . Zostanie
ona zdefiniowana w†programie g³Ûw-
nym.
Tworz¹c pliki nag³Ûwkowe trzeba
zachowaÊ ostroønoúÊ. Moøna bowiem
samemu stworzyÊ pewien ìba³aganî
polegaj¹cy na tym, øe maleÒki nawet
program bÍdzie mia³ dostÍp do wie-
lu danych, ktÛrych w†praktyce nie
potrzebuje. BÍdzie to rzutowaÊ rÛw-
nieø na rozmiar kodu wynikowego
oraz utrudni zachowanie porz¹dku
w†deklaracjach zmiennych i†funkcji.
WiÍcej informacji o†plikach nag³Ûwko-
wych przedstawimy w†nastÍpnym
przyk³adzie programu w†jÍzyku C (za
miesi¹c w†EP). Aby wykorzystaÊ bo-
wiem mechanizm tworzenia plikÛw
nag³Ûwkowych, musimy siÍ nauczyÊ
jak tworzyÊ project files i†do czego
one s³uø¹.
Jacek Bogusz, AVT
jacek.bogusz@ep.com.pl
// port, do którego podłączono
// wyświetlacz LCD
#define PORT P2
// bity sterujące LCD
sbit LcdEnable = PORT^0;
sbit LcdRead = PORT^3;
sbit LcdReg = PORT^2;
// opóźnienie około k* 1 milisekundy
// dla kwarcu 7,3728MHz
void Delay (unsigned int k);
// zapis bajtu do lcd
void WriteByteToLcd(char X);
// zapis bajtu do rejestru
// kontrolnego LCD
void WriteToLcdCtrlRegister(char X);
// zapis bajtu do pamięci obrazu
void LcdWrite(char X);
// czyszczenie ekranu LCD
void LcdClrScr(void);
// inicjalizacja wyświetlacza LCD
// w trybie 4 bity
void LcdInitialize(void);
// ustawia kursor na współrzędnych
// x,y
void GotoXY(char x, char y);
// wyświetla tekst na współrzędnych
// x, y
void WriteTextXY(char x, char y,
char *S)
Pliki nag³Ûwkowe ( *.h )
Rozwaømy teraz pewn¹ moøli-
woúÊ. Mamy juø napisany program
w†jÍzyku C, mamy w†nim pewne fun-
kcje, o†ktÛrych wiadomo, øe przyda-
dz¹ siÍ nam rÛwnieø w†wielu innych
przypadkach. Chociaøby nasz pierw-
szy program steruj¹cy wyúwietlaczem.
Z†ca³¹ pewnoúci¹ przyda siÍ na rÛw-
nieø w innych aplikacjach.
Pojawia siÍ wiÍc pytanie: czy
moøna z†takich programÛw stworzyÊ
bibliotekÍ, ktÛr¹ bÍdzie moøna do³¹-
czyÊ do w³asnego programu i†uøywaÊ
zawsze wtedy, gdy jest to potrzebne?
A†co z†modyfikacj¹ pewnych paramet-
rÛw procedur? Czy zawsze trzeba
mieÊ dostÍp do kodu ürÛd³owego
programu i†szukaÊ, nierzadko wúrÛd
Dodatkowe informacje
Ewaluacyjn¹ wersjê pakietu firmy Raisonance
oraz Ÿródo programu prezentowanego w artykule
zamieœciliœmy na CD-EP7/2002B.
84
Elektronika Praktyczna 7/2002
32267170.004.png
Zgłoś jeśli naruszono regulamin