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
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
s¹
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
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
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
Plik z chomika:
kendzior21
Inne pliki z tego folderu:
1.PDF
(295 KB)
27_31.PDF
(758 KB)
127_129.PDF
(198 KB)
14_19.PDF
(564 KB)
121_124.PDF
(338 KB)
Inne foldery tego chomika:
01.02
02.02
03.02
04.02
05.02
Zgłoś jeśli
naruszono regulamin