748


Prof.nadzw.dr hab.inż. Władysław Brzozowski Cz*stochowa-Gliwice, 15.02.1999 r.

Politechnika Częstochowska

Instytut Elektroenergetyki

Wykłady z przedmiotu:

TECHNIKA PROGRAMOWANIA

studia magisterskie, kierunek Elektrotechnika,

specjalno** Informatyka w Elektroenergetyce, sem.VI

Wyk*ad 5. J*zyk Turbo-Pascal. Grafika w systemie Turbo-Pascal 7.0. Przerwania

5.1. Inicjowanie trybu graficznego

Podobnie jak to by*o z innymi elementami systemu, nie bed* omawiane wszystkie elementy grafiki, a jedynie ciekawsze lub mo*e trudniejsze.

Aby program mog* dzia*a* w trybie graficznym, do pami*ci operacyjnej mikrokomputera musi zosta* wczytany program sterownika tego trybu, czyli tzw. driver. Program ten dla karty graficznej EGA/VGA/SVGA nosi nazwe EGAVGA.BGI.

Ka*dy tego typu sterownik mo*e organizowa* kilka tryb*w graficznych ekranowych, cechuj*cych si* r**n* liczb* punkt*w graficznych ekranu tzw. pixli (pixel) oraz stron ekranowych. W danym momencie czasu wizualizowana jest jedna strona ekranowa, a pozosta*e mog* by* generowane (tworzone). Prze**czanie stron dokonuje si* b*yskawicznie, w spos*b niezauwa*alny dla u*ytkownika. Strony ekranowe wykorzystuje si* szczeg*lnie w animacji komputerowej, np. w grach. Im dany tryb ekranowy dopuszcza wi*cej stron, tym z regu*y daje gorszy obraz (mniejsza liczba pixli).

Sterownik trybu graficznego zostaje za*adowany do pami*ci operacyjnej instrukcj* - procedur* standardow* InitGraph. W systemie Borland Pascal 7.0 przewidziano mo*liwo** za*adowania w*asnego programu - sterownika graficznego u*ytkownika, inn* instrukcj*, mianowicie InstallUserDriver. Oczywi*cie sterownik taki musi by* wcze*niej napisany przez u*ytkownika i musi prawid*owo wsp**pracowa* z kart* graficzn* mikrokomputera.

5.2. Organizacja ekranu. Strony ekranowe i animacja komputerowa

Ekran graficzny w trybie graficznym jest okre*lony liczb* pixli wzd*u* osi x oraz y. Numer pixla po y narasta z g*ry na d** (odwrotnie ni* w geometrii). Wszystkie instrukcje graficzne operuj* wy**cznie numerami pixli po x i po y. Ekran monitora nie mo*e r*wnocze*nie pracowa* w trybie graficznym i w trybie znakowym w tym sensie, *e cz*** ekranu pracuje w trybie graficznym a cz*** w tekstowym.

Mo*na okre*li* okno graficzne, ale tylko jako wyr**nion* cz*** og*lnego ekranu graficznego. Okno graficzne generowane jest przez procedur* standardow* SetViewPort.

Strony ekranowe sa numerowane liczbami 0, 1, 2 itd. Chc*c aby na ekranie zosta*a zwizualizowana strona o numerze np. 1 nale*y wywo*a* procedur* standardow* SetVisualPage(1). W czasie tej wizualizacji, je*li chcemy generowa* np. stron* 3, nale*y wcze*niej wywo*a* procedur* standardow* SetActivePage(3). Prze**czenie tych dwu stron polega na powt*rnym wywo*aniu w/w procedur, ale z zamienionymi numerami stron, czyli

SetVisualPage(3);

SetActivePage(1);

Generuj*c i prze**czaj*c kolejne strony ekranowe z nieznaczn* zmian* po*o*enia jakich* przedmiot*w lub wizerunk*w ludzi w okre*lonych kierunkach, realizujemy tzw. animacj* komputerow*. Numery stron w procedurach jw. mo*na r*wnie* podstawia* jako zmienne typu word.

5.3. Graficzne procedury tekstowe

S*owo „tekstowe” nie oznacza tu trybu tekstowego, a jedynie wyprowadzanie napis*w w trybie graficznym. Podstawowymi procedurami w tym zakresie s* SetTextStyle oraz OutTextXY z odpowiednimi parametrami.

Je*li do wyprowadzenia napisu u*yto niepodstawowego kroju czcionki, np. SmallFont, to zbi*r z parametrami tego kroju, w tym przypadku o nazwie litt.chr musi znajdowa* si* w katalogu bie**cym. Je*li zbioru tego niema, to napis zostanie wyprowadzony ale podstawowym krojem czcionki.

Tekst na ekranie mo*na dowolnie zwi*ksza* lub zmniejsza*. Aby to zrealizowa*, to przed wyprowadzeniem napisu nale*y wywo*a* procedur* standardow* SetUserCharSize z odpowiednimi parametrami.

5.4. Kopiowanie fragment*w obrazu graficznego

Mo*liwe jest skopiowanie do pami*ci operacyjnej mikrokomputera dowolnego prostok*tnego wycinka ekranu w trybie graficznym. Realizuje si* to procedur* standardow* GetImage z odpowiednimi parametrami. Wycinek ten mo*na p**niej odtworzy* wielokrotnie w dowolnych miejscach ekranu, procedura PutImage.

Procedury te w szczeg*lno*ci b*dziemy wykorzystywa* przy animacji komputerowej, gdy chodzi o maksymalne skr*cenie czasu generowania obrazu (np. w grach komputerowych).

Powy*ej om*wiono, i to pobie*nie, jedynie niekt*re elementy trybu graficznego w systemie Turbo Pascal 7.0. Aby m*c programowa* z wykorzystaniem tego trybu konieczna jest *mudna osobista nauka praktyczna na komputerze, na podstawie szczeg**owego podr*cznika systemu (uwaga dotyczy generalnie ca*ego procesu programowania).

5.5. Przyk*adowy program dydaktyczny wykorzystuj*cy tryb graficzny i animacj* komputerow* (zegar.pas)

Uwaga: tekst tego programu pod edytorem Word (podobnie jak innych program*w dydaktycznych za**czonych do wyk*adu) mo*na wykorzysta* jako plik *r*d*owy systemu Turbo Pascal, zaznaczaj*c tekst i zapisuj*c go na dysk jako tekst ASCII ze znakami zmiany wiersza oraz z rozszerzeniem .pas).

{$A+,B-,D+,E+,F-,I+,L+,N-,O-,R-,S+,V+}

{$M 16384,0,655360}

program ZEGAR;

{Program graficzny symulujacy dzialanie zegara.

Autor: Brzozowski W., 1990 r.

Program przeznaczony na komputer z karta VGA/SVGA.}

uses Crt,Dos,Graph;

const

Opozn=100;

{Stala Opozn nalezy korygowac w zaleznosci od szybkosci uzytego

komputera - dla AT 386 dobiera sie ok. 100. Dla komputera szybszego

wiecej, wolniejszego mniej (jednak nie mniej niz 0). O wielkosc Opozn

w milisekundach zostanie dodatkowo opozniony czas wizualizacji strony

tak aby skok wskazowki sekundowej wynosil dokladnie 1s.

Niezaleznie od wartosci Opozn program dziala poprawnie jednakze

skok wskazowki sekundowej nie jest rowny 1s.}

var

Sterownik,Tryb:integer;

Znak:char;

StrWidz,StrZap,SkokKata,SzerokPodz,WskazGodz,WskazMin,WskazSek,X0,Y0,

Prom,DeltaX,DeltaY,I,I1,I2,I3,I4 :integer;

PromNogi,DeltaXNogi,DeltaYNogi: integer;

Kat,KatGodz,KatMin,KatSek,X1 :real;

Opis :string[2];

CzasNum: string[11];

Godz,Min,Sek,Setna :word;

label

Nawrot;

procedure Korekta;

begin

if Copy(Opis,1,1)=' '

then

Opis:='0'+Copy(Opis,2,1);

if Copy(Opis,2,1)=' '

then

Opis:=Copy(Opis,1,1)+'0'

end; {procedure Korekta}

begin

ClrScr;

while KeyPressed do Znak:=ReadKey;

Sterownik:=Vga;

Tryb:=VgaMed;

InitGraph(Sterownik,Tryb,'D:\Pascal');

ClearDevice;

StrWidz:=0;

StrZap:=1;

Nawrot:

{generowanie strony zapisywanej - wizualizacja strony widzialnej}

SetActivePage(StrZap);

SetVisualPage(StrWidz);

SetViewPort(0,0,GetMaxX,GetMaxY,Clipon);

SetBkColor(Black);

ClearViewPort;

{generowanie ksztaltu zegara i tarczy godzinowej}

X0:=360;

Y0:=150;

Prom:=130; {wewnetrzny okreg podzialki}

WskazGodz:=80;

WskazMin:=100;

WskazSek:=120;

SzerokPodz:=10;

DeltaXNogi:=90;

DeltaYNogi:=123;

PromNogi:=20;

SetLineStyle(SolidLn,0,ThickWidth);

SetColor(Red);

Circle(X0-DeltaXNogi,Y0+DeltaYNogi,Promnogi);

SetLineStyle(SolidLn,0,ThickWidth);

Circle(X0+DeltaXNogi,Y0+DeltaYNogi,PromNogi);

SetLineStyle(SolidLn,0,ThickWidth);

Circle(X0,Y0,Prom+35); {zewnetrzny okrag obudowy}

SetColor(Green);

SetLineStyle(SolidLn,0,NormWidth);

Circle(X0,Y0,Prom+30); {wewnetrzny okrag obudowy}

SetColor(Magenta);

Circle(X0,Y0,Prom+SzerokPodz); {zewnetrzny okrag podzialki}

Circle(X0,Y0,Prom); {wewnetrzny okrag podzialki}

SetLineStyle(SolidLn,0,NormWidth);

X1:=1.33;

{wspolczynnik korekcyjny wymiarow zalezny od typu karty graficznej

i trybu graficznego - dla VGA, VgaMed - 1.33}

SetColor(LightBlue);

for SkokKata:=1 to 60 do

begin

Kat:=SkokKata*Pi/30;

I1:=Round(Prom*Sin(Kat));

I2:=Round(Prom*Cos(Kat)/X1);

I3:=Round((Prom+SzerokPodz)*Sin(Kat));

I4:=Round((Prom+SzerokPodz)*Cos(Kat)/X1);

Line(X0+I1,Y0-I2,X0+I3,Y0-I4);

end; {for SkokKata:=1 to 60 do}

SetColor(LightGreen);

SetLineStyle(SolidLn,0,ThickWidth);

for SkokKata:=1 to 12 do

begin

SetColor(White);

Kat:=SkokKata*Pi/6;

Line(X0+Round(Prom*Sin(Kat)),

Y0-Round(Prom*Cos(Kat)/X1),

X0+Round((Prom+SzerokPodz)*Sin(Kat)),

Y0-Round((Prom+SzerokPodz)*Cos(Kat)/X1));

Str(SkokKata:2,Opis);

DeltaX:=-10;

DeltaY:=0;

if (SkokKata<3) or (SkokKata>10)

then

DeltaY:=10;

if SkokKata=3

then

DeltaX:=DeltaX+3;

if (SkokKata=9) or (SkokKata=10)

then

DeltaX:=DeltaX-3;

if (SkokKata=11) or (SkokKata=12)

then

DeltaY:=DeltaY-3;

OutTextXY(X0+DeltaX+Round((Prom+SzerokPodz+5)*Sin(Kat)),

Y0-DeltaY-Round((Prom+SzerokPodz+5)*Cos(Kat)/X1),

Opis)

end; {for SkokKata:=1 to 12 do}

{nazwa firmy}

OutTextXY(X0-20,Y0+10,'SEIKO');

OutTextXY(X0-22,Y0+20,'QUARTZ');

{odczyt czasu}

GetTime(Godz,Min,Sek,Setna);

{generowanie czasu numerycznego}

Str(Godz:2,Opis);

Korekta;

CzasNum:=Opis;

Str(Min:2,Opis);

Korekta;

CzasNum:=CzasNum+'.'+Opis;

Str(Sek:2,Opis);

Korekta;

CzasNum:=CzasNum+'.'+Opis;

OutTextXY(X0-33,Y0-50,CzasNum);

{generowanie czasu graficznego}

{wskazowka godzinowa}

SetColor(LightCyan);

KatGodz:=((Godz mod 12)*30+Min/2)*2*Pi/360;

SetLineStyle(SolidLn,0,ThickWidth);

Line(

X0-Round(WskazGodz/5*Sin(KatGodz)),

Y0+Round(WskazGodz/5*Cos(KatGodz)/X1),

X0+Round(WskazGodz*Sin(KatGodz)),

Y0-Round(WskazGodz*Cos(KatGodz)/X1));

{wskazowka minutowa}

SetColor(LightMagenta);

KatMin:=(Min*6+Sek*0.1)*2*Pi/360;

Line(

X0-Round(WskazMin/5*Sin(KatMin)),

Y0+Round(WskazMin/5*Cos(KatMin)/X1),

X0+Round(WskazMin*Sin(KatMin)),

Y0-Round(WskazMin*Cos(KatMin)/X1));

{wskazowka sekundowa}

SetColor(Yellow);

KatSek:=(Sek*6+Setna*0.06)*2*Pi/360;

SetLineStyle(SolidLn,0,NormWidth);

Line(

X0-Round(WskazSek/5*Sin(KatSek)),

Y0+Round(WskazSek/5*Cos(KatSek)/X1),

X0+Round(WskazSek*Sin(KatSek)),

Y0-Round(WskazSek*Cos(KatSek)/X1));

Delay(Opozn);

{komunikat}

OutTextXY(10,330,'Celem wyjscia z programu przycisnij dowolny klawisz');

if KeyPressed

then

begin

CloseGraph;

Halt

end

else

{zamiana stron z zapisywanej na widzialna i vice versa}

begin

I:=StrWidz;

StrWidz:=StrZap;

StrZap:=I;

goto Nawrot

end; {if KeyPressed}

end. {koniec programu ZEGAR}

5.6. Przerwanie

Przerwaniem nazywa si* chwilowe zawieszenie realizacji programu celem wykonania przez mikroprocesor okre*lonej operacji. Operacj* t* mo*e by* np. przyj*cie z portu szeregowego danych (bajt*w) wynikaj*cych z uruchomienia myszy przez u*ytkownika. Poniewa* dane takie powinny zosta* przyj*te (gdy* domniemywa si*, *e w danym programie dzia*anie myszy jest istotne), realizacja dotychczasowego programu musi by* chwilowo wstrzymana, a po dokonaniu operacji przywr*cona - bez *adnej zmiany, tak jakby przerwania nie by*o.

W dowolnym momencie czasu stan komputera mo*na precyzyjnie odtworzy*, je*li odtworzy si* stan (zawarto**) wszystkich rejestr*w mikroprocesora. Zatem w momencie wyst*pienia przerwania mikroprocesor przepisuje do pami*ci operacyjnej stany swoich rejestr*w, a po realizacji (m*wimy: obs*udze) przerwania odtwarza stan tych rejestr*w odczytuj*c te stany z pami*ci operacyjnej. Ka*de przerwanie ma sw*j w*asny, *ci*le okre*lony adres pami*ci operacyjnej, pod kt*rym nast*puje zapis stan*w rejestr*w. R*wnocze*nie pod tym adresem rezyduje w pami*ci operacyjnej podprogram obs*ugi przerwania.

Stany wszystkich rejestr*w mikroprocesora nazywamy wektorem przerwania (sk*adowymi tego wektora s* poszczeg*lne rejestry). Wektor przerwa* w j*zyku Borland Pascal jest typem rekordowym o predefiniowanej nazwie Registers. Polami tego rekordu s* stany poszczeg*lnych rejestr*w mikroprocesora.

Pola te s* oznaczone symbolami: AX, BX, CX, DX, BP, SI, DI, DS, ES, Flags, AL, AH, BL, BH, CL, CH, DL, DH (opis i funkcje rejestr*w mikroprocesora - [4], cz. Ic, pkt. 20).

Wszystkie przerwania dzielimy na sprz*towe i programowe.

*r*d*em przerwa* sprz*towych s* urz*dzenia wej*cia - wyj*cia.

*r*d*em przerwa* programowych s* programy, rozumiej*c tu: program BIOS, system operacyjny DOS, *rodowisko Windows oraz programy u*ytkowe (aplikacje).

W mikrokomputerze PC zdefiniowano standardowy zbi*r 256 przerwa* o kolejnych numerach. Przyk*adowo: przerwanie o numerze $0C (liczba heksadecymalna r*wna dziesi*tnej 12) pochodzi od portu szeregowego COM1 (jak na wst*pie).

Ka*demu z powy*szych przerwa* przypisany jest adres pami*ci operacyjnej, jak opisano powy*ej. Adres ten mo*na zlokalizowa* procedur* standardow* GetIntVec.

Programista, pisz*c program w j*zyku Borland Pascal, mo*e:

5.7. Przyk*adowy podprogram realizuj*cy przerwanie programowe

procedure KopEkr(X0,Y0{parametry skrajnego punktu wydruku na papierze w dotach, np. X0=200, Y0=100},Rozdziel{rozdzielczosc drukarki laserowej, np. Rozdziel=0}: integer);

{Procedura realizuje zrzut ekranu (tzw. hard copy) w trybie graficznym na drukarke

laserowa LaserJet5L lub wczesniejsza. Autor: Brzozowski W., 1998 (rozbudowany podprogram z ksiazki Waclawek R.: Programowa obsluga drukarek laserowych)}

const

WspPoXHCMed: real=1.3; {wspolczynnik korekcyjny szerokosci wydruku po x - dobrac eksperymentalnie}

WspPoYHCMed: real=1.1; {wspolczynnik korekcyjny szerokosci wydruku po y - dobrac eksperymentalnie}

KolTlSzk:= word=0; {kolor tla ekranu w trybie graficznym - tu black}

EC=#27;

Waga: array[0..7] of byte=(1,2,4,8,16,32,64,128);

var

DrajwerGraf,TrybGraf: integer;

Lst_Result: boolean;

Max_X,Max_Y,X,Y: integer;

SL_Bajtow,LSter,LX0,LY0: string;

Bajt: byte;

procedure WriteLst(Lpt: byte; Tekst: string);

var

Rejestry: Registers;

I: integer;

begin

Lst_Result:=True;

with Rejestry do

for I:=1 to Length(Tekst) do

begin

{ustawienie rejestrow mikroprocesora}

AH:=0;

DX:=Lpt-1;

AL:=Byte(Tekst[I]);

Intr($17,Rejestry); {instrukcja przerwania}

{zwrotna zawartosc rejestrow mikroprocesora}

if (AH and $38)<>$10

then

Lst_Result:=False

end {for I:=1 to Length(Tekst) do}

end; {procedure WriteLst(Lpt{numer portu rownoleglego}: byte; Tekst: string)}

begin

DrajwerGraf:=Detect;

Max_X:=Round(GetMaxX*WsPoXHCMed);

Max_Y:=Round(GetMaxY*WsPoYHCMed);

Str((Max_Y div 8)+1,SL_Bajtow);

if (Rozdziel<>75) and (Rozdziel<>100) and (Rozdziel<>150) and

(Rozdziel<>300)

then

Rozdziel:=75;

Str(Rozdziel,LSter);

X0:=X0+(Max_X+1)*(300 div Rozdziel);

ReWrite(Lst);

WriteLst(1,EC+'E'+#27+'&l1O'); {orientation landscape}

WriteLst(1,EC+'*t'+LSter+'R'); {ustalenie rozdzielczosci}

Str(X0,LX0);

Str(Y0,LY0);

WriteLst(1,EC+'*p'+LX0+'x'+LY0+'Y'+EC+'*r1A'); {punkt poczatkowy bitmapy}

for X:=Max_X downto 0 do

begin

Bajt:=0;

WriteLst(1,EC+'*b'+SL_Bajtow+'W');

for Y:=0 to Max_Y do

begin

if GetPixel(Round(X/WsPoXHCMed),Round(Y/WsPoYHCMed))<>KolTlSzk

then

Bajt:=Bajt+Waga[7-(Y mod 8)];

if (Y mod 8)=7

then

begin

WriteLst(1,Chr(Bajt));

Bajt:=0

end {if (Y mod 8)=7}

end; {for Y:=0 to Max_Y do}

if (Y mod 8)<>7

then

WriteLst(1,Chr(Bajt));

end; {for X:=Max_X downto 0 do}

WriteLst(1,EC+'*rB'); {koniec bitmapy}

WriteLst(1,#12);

Close(Lst)

end; {procedure KopEkr(X0,Y0,Rozdziel: integer)}

 Koniec wyk*adu 5

Plik W5TEPR99.DOC

Edytor WORD 6.0 PL



Wyszukiwarka

Podobne podstrony:
748
748
III CKN 748 00 id 210234 Nieznany
748
748
748
748
26 748 p
748 749
748
748
748
748
Lofting Hugh Ogrod zoologiczny doktora Dolittle (SCAN dal 748)
000 748

więcej podobnych podstron