REFERAT-MenüDeutschGeographieGeschichteChemieBiographienElektronik
 EnglischEpochenFranzösischBiologieInformatikItalienisch
 KunstLateinLiteraturMathematikMusikPhilosophie
 PhysikPolitikPsychologieRechtSonstigeSpanisch
 SportTechnikWirtschaftWirtschaftskunde  



Druckeransteuerung unter Turbo-Pascal fur DOS




Druckeransteuerung unter Turbo-Pascal für DOS





Annotation:    Diese Facharbeit beschäftigt sich mit der Problematik der Druckeransteuerung

im Allgemeinen und deren technischer Realisierung mit Hilfe eines in der Programmiersprache PASCAL geschriebenen Programmes. Es soll eine beliebige Datei (ASCII-codiert) gedruckt werden. Das Programm ist von der graphischen Oberfläche her bewußt einfach gehalten, um den Nutzer nicht vom Wesentlichen abzulenken.   






Gliederung:

Benutzer-Dokumentation

Zweck und Anwendungsbereich

Anweisungen


Entwickler-Dokumentation

Lösungsideen und Algoritmen


Zusammenfassung








































Zweck und Anwendungsbereich


Dieses Druckprogramm ist nur für den Schul- und Hausgebrauch geeignet, obwohl es leicht zu bedienen und einfach aufgebaut ist, verfügt es aber nicht über einstellbare Druckoptionen. Dieses Programm wurde im Informatikunterricht und teils in Heimarbeit, unter der Projektaufgabe 'Entwickeln und testen sie ein Pascal-Programm, mit dessen Hilfe ASCII-Textdateien auf einem Drucker durch direkte Druckeransteuerung ausgedruckt werden können,' entwickelt und geschrieben. In diesem Pascal-Programm wurden die geforderten Richtlinien erfüllt, sowie einige der möglichen Erweiterungen eingebunden.


Spezifikationen :


- Das Datenübertragungsprotokoll zum Drucker ist ADQ-Handshake.

- Es wird auf DIN A4-Einzelblätter mit insgesamt 58 Zeilen/Druckseite gedruckt.

- Nach dem Druck jeder Seite, jedoch nicht nach der letzten, ist auf dem Bildschirm eine

Meldung auszugeben, mit der der Benutzer aufgefordert wird, ein neues Blatt in den

Drucker einzulegen sowie der Hinweis, daß erst dann weitergedruckt wird, wenn die

ESC-Taste - und nur diese - gedrückt wurde.


Erweiterungen :


die Textzeilen sind fortlaufend numeriert

auf Seite 1 wird der Dateiname ausgedruckt

des weiteren wird das aktuelle Systemdatum auf Seite 1 ausgedruckt

ebenfalls nützlich bei der Archivierung ist die fortlaufende Seitennumerierung mit Angabe

der Gesamtanzahl der Seiten und der Drucker wird nach dem Druck einer Datei auf seine Standardeinstellungen zurückgesetzt


Anweisungen


Bei der Benutzung dieses Druck-Programms braucht der Anwender nur sehr wenig zu beachten, da es nur wenige, dafür aber eindeutige Anweisungen gibt. Aus diesem Grund ist ein leichtes, problemloses Arbeiten möglich.

Voraussetzung für den Ausdruck ist, daß der Drucker eingeschaltet und das bei Programmstart Papier im Drucker ist. Ansonsten meldet sich das Programm mit einer Fehlermeldung und der Aufforderung den Drucker einzuschalten bzw. Papier einzulegen. Das Programm wird nach diesen Fehlermeldungen beendet und kann nach Behebung der Fehler erneut gestartet werden.

Die Arbeitsanweisungen beschränken sich auf das Eingeben des Dateinamens, der zum Ausdruck gewünschten Datei, sowie dem Blatteinlegen. Der Dateiname darf nicht mehr als 8 Zeichen und die Dateiendung nicht mehr als 3 Zeichen lang sein. Das sind jedoch Beschränkungen der FAT (File Allocation Table = Dateizuordnungstabelle) von DOS. Erst mit VFAT unter Windows 95 bzw. mit NTFS, dem File System von Windows NT könnten theoretisch auch mehr Dateizeichen verwendet werden. Microsoft bietet zum Zweck der Erweiterung der Funktionalität von DOS-Programmen unter Windows ab Version 95 ein Support Pack für Programmierer an, um dann auch mit mehr als 8 Zeichen zu arbeiten. Die Eingabe des Dateinamens wird dann mit <Enter> bestätigt.


Entwickler-Dokumentation


Lösungsideen und Teilalgorithmen


Die gestellte Aufgabe aus dem Bereich der Technischen Informatik befaßt sich mit dem Thema der direkten Druckeransteuerung über die Centronics-Schnittstelle. Diese Schnittstelle ist eine spezielle parallele Schnittstelle, bei der die Daten bit-parallel auf 8 parallelen Datenleitungen übertragen werden. Für die Übertragungung der Zeichen vom Computer zum Drucker wurde in diesem Druck-Programm ein einfaches, aber erprobtes Übertragungsprotokoll, das ADQ-Handshake oder ADQ-Protokoll verwendet. Obwohl der Aufbau der CENTRONICS-Schnittstelle die Realisierung unterschiedlicher Übertragungsprotokolle zuläßt, so ist das ADQ-Handshake doch eines der zuverlässigsten und wurde auch verwendet, damit die Arbeit mit dem Programm problemlos erfolgen kann.

Zunächst habe ich mich mit dem Aufbau der Druckerschnittstelle und den Zuständen ausgewählter Register-Signale beschäftigt, worauf erste kleine Pascal-Programme folgten, die durch Bitmanipulation in Bytes Zugriff auf die Register der Schnittstelle erhielten. Diese Programme nutzen selbstentwickelte Bit-Filter, die Bit-Masken einsetzen. Dabei verwendet man die in PASCAL zulässige Verknüpfung von Bytes mit Hilfe der logischen Operatoren AND, OR sowie XOR. Um die Codierung dieser Programme in PASCAL zu erleichtern, sollte man Lösungsalgorithmen aufstellen, in denen eindeutig der Programmablauf mit eigenen Worten beschrieben ist.



Um eine komplette und umfangreiche Datei fehlerfrei auszudrucken, waren die Prozeduren Zeilenvorschub und Seitenvorschub notwendig. Alle globalen Variablen des Programms sind im Programmkopf vereinbart worden, weil mehrere Prozeduren mit ihnen arbeiten. Dagegen sind viele Variablen lokal deklariert, da die Prozeduren und Funktionen ähnliche Programmabläufe haben, und man deshalb Variablennamen mehrmals verwenden kann, ohne das Komplikationen auftreten.

Ich habe mir zur Aufgabe gestellt, die wichtigsten Prozeduren zu erläutern, da ein PASCAL-Programm meistens aus mehreren Prozeduren besteht, die miteinander verknüpft zusammenarbeiten. Den Anfang macht hierbei die Prozedur strobeimpuls.

Quelltext:

procedure strobeimpuls;

var steuer_byte,ergebnis_byte,maske:byte;

begin

maske:=1;

steuer_byte:=port[890];

ergebnis_byte:=(steuer_byte XOR maske);

port[890]:=ergebnis_byte;

delay(10);

port[890]:=steuer_byte;

end;

Diese Prozedur ist charakteristisch für das Druck-Programm, da sie eine der wichtigsten im ganzen Programm ist und da sie nach dem Prinzip der Bitmanipulation arbeiten.Die Aufgabe der Prozedur liegt in der Aussendung eines Signals, das dem Drucker mitteilt, daß ein Datenwort zu 'Weiterverarbeitung' bereits im Datenregister vorhanden ist.

Die Realisierung erfolgt, indem der PC dem Drucker mitteilt, daß er das Steuerbyte A0 mindestens 10 Millisekunden lang auf Eins setzt, somit einen Bitwechsel vollführt, der ein Signal darstellt.




In der ersten Zeile wird formal der Prozedurname festgelegt, ihm folgt in der zweiten Zeile

die Deklaration der zu benutzenden Variabeln steuer_byte, ergebnis_byte und der Bitmaske des Typus byte. Die Anweisungen beginnen mit dem Setzen der Bitmaske auf 1. Dann wird aus dem Steuerregister mit der Adresse 890 dez das steuer_byte ausgelesen. Da die Maske 1 ist, wird nun mit Hilfe der Operation XOR das ergebnis_byte auf jeden Fall auf 1 gesetzt. Das ergebnis_byte wird nun in das Steuerregister mit der Adresse 890 dez zurückgeschrieben. Eine Pause von 10 ms ermöglicht dem PC die Auswertung und Reaktion auf das ergebnis_byte. Der Strobeimpuls wird generiert, womit die Aufgabe ein Signal abzugeben erfüllt wurde. Anschließend wird das Byte steuer_byte in das Steuerregister mit der Adresse 890 dez zurückgeschrieben.

Die Prozedur strobeimpuls wird in meinem Programm in 50% aller Prozeduren verwendet, man benötigt diese Prozedur zum Druck jeden Zeichens, sowie zur Konfigurierung des Druckers, sie ist für mich ein kausales Hilfsmittel.

Bevor die Daten ausgedruckt werden können, müssen sie jedoch erst einmal aus der Datei ausgelesen werden. Dies geschieht mit Hilfe der Prozedur datei_sequentiell_lesen.

Quelltext:

procedure datei_sequentiell_lesen;

var znummer, zzaehler, seite:integer;

s,seiten:string;


begin

seitenanzahl;

seite:=1;

str(seite,seiten);

wort_drucken('Seite'+' '+Seiten+' '+'von'+' '+gesamt);

zeilenvorschub;

reset(quelldatei);

znummer:=0;

while not eof(quelldatei) do


begin

znummer:=znummer+1;

str(znummer,s);

readln(quelldatei,zeile);

zeile:=s+' '+zeile;

wort_drucken(zeile);

if ((znummer MOD 58=0) AND (not eof(quelldatei)))

then

begin

seitenvorschub;

seite:=seite+1;

str(seite,seiten);

writeln('Bitte neues Blatt einlegen, wenn Drucker fertig ist!');

delay(10000);

writeln('Weiter mit Escape-Taste!');

repeat until readkey=escape;

wort_drucken('Seite'+' '+Seiten+' '+'von'+' '+gesamt);

zeilenvorschub;

clrscr;

end;

end;

if eof(quelldatei) then

begin

clrscr;

writeln('Drucken beendet');

seitenvorschub;

end;

end;


Wieder wird zunächst der Prozedurname festgelegt. In dieser Prozedur kommen schon einige Erweiterungen zum Einsatz. Zum Beispiel wird jede einzelne Zeile der auszulesenden Datei numeriert. Dies geschieht über den Zähler znummer, der bei jedem Durchlauf der While not

Eof Schleife um 1 hochgesetzt wird, also bei jeder neu eingelesenen Zeile. Der Zähler wird über den Befehl str dann noch ins String-Format übersetzt, um dann zusammen mit der Zeile

ausgedruckt zu werden. Wenn der Zähler znummer 58 oder ein Vielfaches davon beträgt, wird ein Seitenvorschub gestartet; eine im Programm definierte Prozedur. Die aktuelle Seitenanzahl Seite, die zuvor auf 1 gesetzt wurde, wird nun um 1 erhöht, um dann auf der nächsten Seite zusammen mit der in der Prozedur seitenanzahl ermittelten Gesamtseitenzahl gesamt ausgedruckt zu werden. Um dem Anwender jedoch Zeit zum Neueinlegen eines Blattes Papier zu geben, wird der Seiteneinzug solange verzögert, bis der Anwender die Escape-Taste betätigt hat. Dann wird der Druck der restlichen Zeilen der Datei fortgesetzt, immer mit einem Seitenvorschub und einem darauf folgenden Seiteneinzug führt. Der Seiteneinzug ist aber nur eine Folge des Strobeimpulses, der in der Prozedur wort_drucken durchgeführt wird, um die nach dort übergebene Variable zeile auszudrucken.

Hier noch einmal zum näheren Verständnis der Quelltext der Prozedur wort_drucken:

procedure wort_drucken(zeile: string) ;

var zk_laenge,i:integer;

zeichen:char;

begin

zk_laenge:=length(zeile);

For i:=1 to zk_laenge do

begin

zeichen:=zeile[i];

port[888]:=ord(zeichen);

strobeimpuls;

delay(10);

end;

zeilenvorschub;

end;


Wie sehr schön zu erkennen ist, findet sich hier unsere eingelesene Zeile aus der Prozedur datei_sequentiell_lesen wieder. Diese wird jetzt auf ihre Länge hin untersucht. Vom ersten Zeichen an bis zum letzten der Zeichenkette wird nun das jeweilige Zeichen ins Datenregister

verschoben, um von dort per Strobeimpuls an den Drucker zu wandern. Dieser führt dann noch einen Zeilenvorschub aus, um schließlich die nächste Zeile zu drucken. Es sei an dieser Stelle angemerkt, daß der Computer die Zeilen viel schneller aus der Datei ausliest, als diese gedruckt werden können. Das stellt jedoch keinen Nachteil dar, da der Puffer im Drucker groß

genug ist, die ankommenden Daten zwischenzuspeichern.




Das war eigentlich schon der gesamte Vorgang des Druckens samt Auslesen der Informationen aus der ASCII-Datei. Der Auslesevorgang findet sich, diesmal aber ohne Druckvorgang, auch noch einmal in der Prozedur seitenanzahl. Sie dient lediglich dazu, im voraus die Gesamtanzahl der Zeilen der Datei festzustellen, um diese dann später immer mit

der aktuellen Seitenzahl auszudrucken, wenn eine neue Seite beginnt. Hier der Quelltext der Prozedur Seitenanzahl:

procedure seitenanzahl;

var zeilennummer, seitenzahl:integer;


begin

reset(quelldatei);

zeilennummer:=0;

while not eof(quelldatei) do

begin

zeilennummer:=zeilennummer+1;

readln(quelldatei);

end;

seitenzahl:=zeilennummer div 58;

if zeilennummer mod 58 <> 0 then seitenzahl:=seitenzahl+1;

str(seitenzahl, gesamt);

close(quelldatei);

end;


Dividiert man die Anzahl der Zeilen, gespeichert in der Variablen zeilennummer durch die Anzahl der Zeilen pro Seite, so ergibt sich daraus die Gesamtseitenzahl. Bei einer nicht ganzen Zahl ist die Seitenzahl entsprechend immer einen Zähler höher. Die Prozeduren online_test (Abfrage, ob der Drucker eingeschaltet bzw. neudeutsch "online"Ist), busy (Abfrage der Verfügbarkeit des Druckers) fragen mittels bestimmter Bitmasken das Statusregister des Druckers mit der Adresse 889 dez ab und sind im Hauptprogramm dem eigentlichen Druckvorgang vorgestellt, ebenso wie die Prozedur prüfen.


In der Prozedur pruefen wird beim Öffnen der zu druckenden Datei auf das IO-Ergebnis gewartet und entsprechend seinem Wert der Vorgang weitergeführt oder mit einem Hinweis auf die nicht vorhandene Datei beeendet.


Besonders erwähnenswert ist die Prozedur datum_drucken. In ihr wird das Systemdatum mit Hilfe des Befehls getDate ausgelesen. Mittels eines Datenfeldes werden den Werten 0 bis 6, je nach Wochentag, der Variable dow, die Wochentage zugeordnet und dann zusammen mit dem Datum gedruckt. Hier der Quelltext:

procedure datum_drucken;

var

Jahr, Monat, tag:string; const Tage: array [0..6] of String[10] =('Sonntag','Montag','Dienstag',

'Mittwoch','Donnerstag','Freitag','Samstag');

var

y, m, d, dow : Word;

begin

GetDate(y,m,d,dow);

str(y,Jahr);

str(m,Monat);

str(d,Tag);

wort_drucken(Tage[dow]+','+' '+'der'+' '+

Tag+'.'+Monat+'.'+Jahr);zeilenvorschub;end;



Zusammenfassung


Obwohl heute sicherlich niemand mehr einen Druckertreiber für DOS schreiben würde, der derart generelle Funktionen bietet, war die Arbeit an diesem Projekt doch sehr interessant. Ob nun DOS oder Windows, die Prinzipien der Bitmaskenprogrammierung kommen in allen möglichen Gerätetreibern und bei allen Betriebssystemen zum Einsatz.


vollständiger Sourcecode

program druck;

uses dos, crt;

var quelldatei:text;

quelldateiname:string[12];

zeile:string[125];

busy_wert:integer;

druck_string:string[125];

zeichen:char;

datei_vorhanden:boolean;

taste:char;

gesamt:string;

const escape=chr(27);






procedure busy;

var status_byte,maske,ergebnis_byte:byte;

begin

clrscr;

maske:=128;

status_byte:=port[889];

ergebnis_byte:=(status_byte and maske);

if ergebnis_byte=maske then busy_wert:=1 else busy_wert:=0;

end;


procedure strobeimpuls;

var steuer_byte,ergebnis_byte,maske:byte;

begin

maske:=1;

steuer_byte:=port[890];

ergebnis_byte:=(steuer_byte XOR maske);

port[890]:=ergebnis_byte;

delay(10);

port[890]:=steuer_byte;

end;
















procedure zeilenvorschub;

begin

port[888]:=10;

strobeimpuls;

end;


procedure wort_drucken(zeile: string) ;

var zk_laenge,i:integer;

zeichen:char;

begin

zk_laenge:=length(zeile);

For i:=1 to zk_laenge do

begin

zeichen:=zeile[i];

port[888]:=ord(zeichen);

strobeimpuls;

delay(10);

end;

zeilenvorschub;

end;




procedure online_test;

var status_byte, neu_byte, maske:byte;

bit_wert,i:integer;

begin

i:=1;

repeat

clrscr;

maske:=16;

status_byte:=port[889];

neu_byte:=(status_byte AND maske);

if neu_byte=maske then bit_wert:=1 else bit_wert:=0;

if bit_wert=0 then writeln('Bitte schalten Sie den Drucker ein!');



delay (1000);

i:=i+1;

until (neu_byte=maske) or (i=15);

if neu_byte<>maske then

begin

writeln('Abbruch des Druckprogrammes');

delay(5000);

halt;

end;

end;


procedure druckerpuffer_leeren;

begin

port[888]:=13;

strobeimpuls;

end;


procedure seitenvorschub;

begin

port[888]:=12;

strobeimpuls;

end;







procedure seitenanzahl;

var zeilennummer, seitenzahl:integer;


begin

reset(quelldatei);

zeilennummer:=0;

while not eof(quelldatei) do

begin

zeilennummer:=zeilennummer+1;

readln(quelldatei);

end;

seitenzahl:=zeilennummer div 58;

if zeilennummer mod 58 <> 0 then seitenzahl:=seitenzahl+1;

str(seitenzahl, gesamt);

close(quelldatei);

end;



procedure datei_sequentiell_lesen;

var znummer, zzaehler, seite:integer;

s,seiten:string;


begin

seitenanzahl;

seite:=1;

str(seite,seiten);

wort_drucken('Seite'+' '+Seiten+' '+'von'+' '+gesamt);

zeilenvorschub;

reset(quelldatei);

znummer:=0;

while not eof(quelldatei) do


begin

znummer:=znummer+1;

str(znummer,s);

readln(quelldatei,zeile);

zeile:=s+' '+zeile;

wort_drucken(zeile);

if ((znummer MOD 58=0) AND (not eof(quelldatei)))

then

begin

seitenvorschub;

seite:=seite+1;

str(seite,seiten);

writeln('Bitte neues Blatt einlegen, wenn Drucker fertig ist!');

delay(10000);

writeln('Weiter mit Escape-Taste!');

repeat until readkey=escape;

wort_drucken('Seite'+' '+Seiten+' '+'von'+' '+gesamt);

zeilenvorschub;

clrscr;

end;

end;

if eof(quelldatei) then

begin

clrscr;

writeln('Drucken beendet');

seitenvorschub;

end;

end;




procedure pruefen (VAR quelldatei:text;

var datei_vorhanden:boolean);

begin

(*$I-*)

reset (quelldatei);

(*$I+*)

if IOresult <> 0

then

begin

datei_vorhanden:=false;

end

else

begin

datei_vorhanden:=true;

close(quelldatei);

end;

end;


procedure kopfzeile_drucken;

begin

wort_drucken(quelldateiname);

zeilenvorschub;

end;


procedure datum_drucken;

var

Jahr, Monat, tag:string;

const Tage: array [0..6] of String[10] =

('Sonntag','Montag','Dienstag',

'Mittwoch','Donnerstag','Freitag',

'Samstag');

var

y, m, d, dow : Word;


begin

GetDate(y,m,d,dow);

str(y,Jahr);

str(m,Monat);

str(d,Tag);

wort_drucken(Tage[dow]+','+' '+'der'+' '+

Tag+'.'+Monat+'.'+Jahr);

zeilenvorschub;

end;



begin

clrscr;

online_test;

write('Welche Datei soll gedruckt werden? :');readln(quelldateiname);

assign(quelldatei,quelldateiname);

pruefen(quelldatei,datei_vorhanden);

if datei_vorhanden=false then

begin

writeln('Die zu druckende Datei ist nicht da');

readln;

halt;

end;


busy;

if busy_wert=1 then

begin

kopfzeile_drucken;

datum_drucken;

datei_sequentiell_lesen;

close(quelldatei);

delay(10);

druckerpuffer_leeren;

seitenvorschub;

end;

end.











Haupt | Fügen Sie Referat | Kontakt | Impressum | Nutzungsbedingungen







Neu artikel