|
Win32-API Parallele Schnittstelle :
Während ältere Betriebssysteme (DOS, Win95/98) den direkten Zugriff auf Register erlaubten,
und dem Programmierer damit ermöglichten, auch die Druckerschnittstelle (Printer-Port, LPT-Port) zur
eigenen Ein- und Ausgabe zu nutzen, so wird dies ab Win2000, WinXP usw. verhindert.
Es gibt jedoch einige Programme und Programmiermöglichkeiten, um diese Hürde zu umgehen
(userport.exe, WinIO.dll, InpOut32.dll, InpOut64.dll u.ä.).
Das folgende Beispiel verwendet die kostenfreie inpout32.dll, die im Programmverzeichnis stehen muß und die Sie sich von
http://www.logix4u.net/inpout32.htm
herunterladen können.
Im Laufe der Computerentwicklung wurde auch die parallele Schnittstelle mehrfach Verbesserungen
unterzogen. Häufig findet man im BIOS-Setup des Motherboards entsprechende Konfigurationsmöglichkeiten:
SPP (Standard Parallel Port, unidirektional)
EPP (Extended Parallel Port, bidirektional und schneller als SPP)
ECP (Extended Capycity Port, bidirektional, aber mit erweiterter Kommunikation)
Zum Programmieren benötigt man hauptsächlich drei aufeinanderfolgende Adressen des betreffenden Ports. Man findet
sie in den Windows-Systemeinstellungen. Üblich für LPT1 sind:
h378 DATEN-Byte (D0 bis D7)
h379 STATUS-Byte
h37A CONTROL-Byte
In diesem Beispiel ändert ein Timer die Ausgänge (DATA- und CONTROL-Bytes) und liest die Eingänge (STATUS-Byte). Die
Inhalte der drei Register werden am Schirm angezeigt. Um verwirrende zusätzliche Programmzeilen zu vermeiden, dient die
Titelleiste des Fensters wieder als Ausgabefeld.
|
|
// Win32-API: Parallel Port with timer (Author: Claude Jacobs, 2013)
// inpout32.dll muss im Programmverzeichnis stehen
#include <windows.h>
#include <stdio.h>
#include <math.h> // für pow( )
//============== Globale Variablen deklarieren =====================
HWND hFenster ; // Handle des Fensters deklarieren
int Timer1Nummer;
//------------------------------------------------------------------
int i; char STR[255];
BYTE DatenByte, StatusByte, ControlByte; // Ein/Ausgabe-Bytes deklarieren
//------------------------------------------------------------------
HINSTANCE hInpOutDll;
typedef void (__stdcall *lpOut32)(short, short);
typedef short (__stdcall *lpInp32)(short);
typedef BOOL (__stdcall *lpIsInpOutDriverOpen)(void);
typedef BOOL (__stdcall *lpIsXP64Bit)(void);
lpOut32 PortSchreiben;
lpInp32 PortLesen;
lpIsInpOutDriverOpen gfpIsInpOutDriverOpen;
lpIsXP64Bit gfpIsXP64Bit;
//============== Prozedur des Fensters =============================
LRESULT CALLBACK FensterProzedur (HWND hFenster, UINT Befehle, WPARAM wParam, LPARAM lParam)
{ switch (Befehle) // Befehle unterscheiden
{case WM_DESTROY: {PostQuitMessage (0); break;} // Programm beenden
default: {return DefWindowProc (hFenster, Befehle, wParam, lParam);}
}
return 0; }
//================= Timer-Prozedur ===============================
void CALLBACK ZeitProzedur(HWND hFenster, UINT Befehle, UINT idEvent, DWORD dwTime)
{DatenByte++; ControlByte=ControlByte^0x0F;
PortSchreiben (0x378, DatenByte); // Datenbyte schreiben
StatusByte = PortLesen (0x379)^0xF8; // Statusbyte lesen (nur erste 5 Bit)
PortSchreiben (0x37A, ControlByte); // Controlbyte schreiben
strcpy(STR,"LPT1 DATA(h378): "); // Text für Titelleiste vorbereiten
for (i=7; i>=0; i--) {if ((int)pow(2,i)&DatenByte) {strcat(STR,"1");} else {strcat(STR,"0");}}
strcat(STR," STATUS(h379): ");
for (i=7; i>=3; i--) {if ((int)pow(2,i)&StatusByte) {strcat(STR,"1");} else {strcat(STR,"0");}}
strcat(STR,"xxx CONTROL(h37A): xxxx");
for (i=3; i>=0; i--) {if ((int)pow(2,i)&ControlByte) {strcat(STR,"1");} else {strcat(STR,"0");}}
SendMessage(hFenster, WM_SETTEXT, 0, (LPARAM)STR);
}
//============== HAUPTFUNKTION (und das Fenster erzeugen) ===========
int WINAPI WinMain (HINSTANCE hInstanz, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFensterStil)
{ MSG Befehle; // eine Message-Variable deklarieren
WNDCLASSEX Klasse; // eine Fensterklassen-Variable deklarieren (für wichtige Parameter des Fensters)
Klasse.lpszClassName = "Hauptfenster" ; // Klassenname
Klasse.lpfnWndProc = FensterProzedur ; // Name der Prozedur dieses Fensters
Klasse.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
Klasse.hCursor = LoadCursor (NULL, IDC_ARROW);
Klasse.cbSize = sizeof (WNDCLASSEX);
Klasse.hInstance = hInstanz;
Klasse.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
Klasse.hIcon = LoadIcon (NULL, IDI_APPLICATION);
Klasse.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
Klasse.lpszMenuName = NULL; // Fenster hat kein Menü
Klasse.cbClsExtra = 0;
Klasse.cbWndExtra = 0;
if ( ! RegisterClassEx (&Klasse)) // Klasse registrieren (oder Fehler anzeigen)
{MessageBox(hFenster,"Fensterklasse konnte\n nicht rgistriert werden","Fehler", MB_OK); return 0;}
hFenster = CreateWindow ("Hauptfenster", "Titel des Fensters", WS_OVERLAPPEDWINDOW,
// Hauptfenster erzeugen :
40, 20, 600, 300, HWND_DESKTOP, NULL, hInstanz, NULL);
ShowWindow (hFenster, nFensterStil); // ... und sichtbar machen
Timer1Nummer=SetTimer(hFenster, 1, 250, ZeitProzedur); // Timer "ZeitProzedur" starten (250 ms)
//------
hInpOutDll = LoadLibrary ( "inpout32.dll" ) ;
if ( hInpOutDll != NULL )
{PortSchreiben = (lpOut32)GetProcAddress(hInpOutDll, "Out32");
PortLesen = (lpInp32)GetProcAddress(hInpOutDll, "Inp32");
gfpIsInpOutDriverOpen = (lpIsInpOutDriverOpen)GetProcAddress(hInpOutDll, "IsInpOutDriverOpen");
gfpIsXP64Bit = (lpIsXP64Bit)GetProcAddress(hInpOutDll, "IsXP64Bit");
}
else
{MessageBox(hFenster,"Could not load INPOUT32.DLL\n (Ports not accessible)","Error",MB_OK|MB_ICONERROR);}
//------
while (GetMessage (&Befehle, NULL, 0, 0)) // Dauerschleife (sendet Befehle an obige Fensterprozedur)
{TranslateMessage(&Befehle); DispatchMessage(&Befehle);}
return Befehle.wParam; }
|
|
|
Man kann nun leicht prüfen, ob das Programm tatsächlich den Zugriff auf die betreffende parallele Schnittstelle gestattet,
indem man einen Ausgang (DATEN oder CONROL) mit einem der Eingänge (STATUS) verbindet (Abb.:1). In der Titelleiste des
Fensters sollte das entsprechende Bit des dargestellten Status-Registers dann ebenfalls die Impulse zeigen, eventuell invertiert.
Um nur die Ausgänge zu testen, kann auch eine Leuchtdiode über einen Widerstand (etwa 330R ... 1k) angesteuert werden.
(Abb.:2). Bei einigen älteren Computer waren die Ausgänge häufig einfache Open-Collector-Schaltungen und
benötigten einen zusätzlichen Pull-Up-Widerstand nach 5V (hier grau eingezeichnet).
|
|
|
Win32-API Serielle Schnittstelle und Datenübertragung:
Dieses kleine Programm zeigt eine einfache Datenübertragung in beide Richtungen zwischen zwei Computer
über ein NULL-Modem-Kabel. Dazu muß es auf beiden Computer gleichzeitig laufen. In diesem Beispiel werden
im Sekundentakt jeweils drei aufeinanderfolgende ASCII-Zeichen an den Empfänger gesendet.
Die recht aufwendige Initialisierung serieller Schnittstellen erfolgt hier in einer Prozedur, die eine Änderung der
Hauptparameter (bzw. die COM-Port-Nummer OeffneCom (Nummer, x,x,x,x) )
vereinfacht.
Um verwirrende zusätzliche Programmzeilen zu vermeiden, dient die
Titelleiste des Fensters wieder als Ausgabefeld.
|
|
// Win32-API: simple Serial Port communication (Author: Claude Jacobs, 2013)
//bei den Projektoptionen die Bibliothek user32.lib hinzufügen !
#include <windows.h>
//============== Globale Variablen deklarieren =====================
HWND hFenster ; // Handle des Fensters deklarieren
HWND hComDatei; // Handle der COM-Schnittstelle
//------------------------------------------------------------------
int i,j;
int Anzahl=3; // Anzahl der zusammen gesendeten Bytes
char SchreibPuffer[255], LesePuffer[255];
DWORD SchreibMenge, LeseMenge;
//------------------------------------------------------------------
int Timer1Nummer, Timer2Nummer;
//================== COM oeffnen u. konfigurieren ==================
int OeffneCom(int ComNr, int baud, char Par, int BitZahl, float StopBits )
{
char c[255];
if (ComNr==1) {strcpy(c,"COM1");}
if (ComNr==2) {strcpy(c,"COM2");}
if (ComNr==3) {strcpy(c,"COM3");}
if (ComNr==4) {strcpy(c,"COM4");}
BYTE p=0;
if (Par=='n') {p=0;}
if (Par=='o') {p=1;}
if (Par=='e') {p=2;}
if (Par=='m') {p=3;}
if (Par=='s') {p=4;}
BYTE s=0;
if (StopBits<1.5) {s=0;}
if (StopBits==1.5) {s=1;}
if (StopBits>1.5) {s=2;}
hComDatei=CreateFile(c,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
if(hComDatei==INVALID_HANDLE_VALUE) return 0;
DCB SerKonf;
memset(&SerKonf,0,sizeof(SerKonf));
SerKonf.DCBlength = sizeof(SerKonf);
SerKonf.BaudRate = baud;
SerKonf.fParity = FALSE;
SerKonf.fBinary = TRUE;
SerKonf.Parity = p;
SerKonf.StopBits = s;
SerKonf.fOutxCtsFlow = FALSE;
SerKonf.fOutxDsrFlow = FALSE;
SerKonf.fDtrControl = DTR_CONTROL_ENABLE;
SerKonf.fRtsControl = RTS_CONTROL_ENABLE;
SerKonf.fDsrSensitivity = FALSE;
SerKonf.fAbortOnError = FALSE;
SerKonf.ByteSize = BitZahl;
if(!SetCommState(hComDatei,&SerKonf)) {CloseHandle(hComDatei); return 0; }
COMMTIMEOUTS SerZeit;
SerZeit.ReadIntervalTimeout = MAXDWORD;
SerZeit.ReadTotalTimeoutMultiplier = 0;
SerZeit.ReadTotalTimeoutConstant = 0;
SerZeit.WriteTotalTimeoutMultiplier= 1;
SerZeit.WriteTotalTimeoutConstant = 2;
if(!SetCommTimeouts((HANDLE)hComDatei,&SerZeit)) {CloseHandle(hComDatei); return 0;}
return 0;}
//================= Schreib-Timer ==================================
void CALLBACK SchreibIntervall(HWND hFenster, UINT Befehle, UINT idEvent, DWORD dwTime)
{for (j=0;j < Anzahl; j++) {SchreibPuffer[j]=i; i++; if (i>122) {i=48;}}
WriteFile(hComDatei, SchreibPuffer, Anzahl, &SchreibMenge, 0);
}
//================= Lese-Timer =====================================
void CALLBACK LeseIntervall(HWND hFenster, UINT Befehle, UINT idEvent, DWORD dwTime)
{ ReadFile (hComDatei,LesePuffer,20,&LeseMenge,0);
if (LeseMenge>0) // es wurden Bytes empfangen
{LesePuffer[LeseMenge]=0; // NULL-terminieren
SendMessage(hFenster, WM_SETTEXT, 0, (LPARAM)LesePuffer);} // Empfangener String in Titelleiste schreiben
}
//============== Prozedur des Fensters =============================
LRESULT CALLBACK FensterProzedur (HWND hFenster, UINT Befehle, WPARAM wParam, LPARAM lParam)
{ switch (Befehle) // Befehle unterscheiden
{case WM_DESTROY: {CloseHandle(hComDatei); PostQuitMessage (0); break;} // Programm beenden
default: {return DefWindowProc (hFenster, Befehle, wParam, lParam);}
}
return 0; }
//============== HAUPTFUNKTION (und das Fenster erzeugen) ===========
int WINAPI WinMain (HINSTANCE hInstanz, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFensterStil)
{ MSG Befehle; // eine Message-Variable deklarieren
WNDCLASSEX Klasse; // eine Fensterklassen-Variable deklarieren (für wichtige Parameter des Fensters)
Klasse.lpszClassName = "Hauptfenster" ; // Klassenname
Klasse.lpfnWndProc = FensterProzedur ; // Name der Prozedur dieses Fensters
Klasse.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
Klasse.hCursor = LoadCursor (NULL, IDC_ARROW);
Klasse.cbSize = sizeof (WNDCLASSEX);
Klasse.hInstance = hInstanz;
Klasse.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
Klasse.hIcon = LoadIcon (NULL, IDI_APPLICATION);
Klasse.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
Klasse.lpszMenuName = NULL; // Fenster hat kein Menü
Klasse.cbClsExtra = 0;
Klasse.cbWndExtra = 0;
if ( ! RegisterClassEx (&Klasse)) // Klasse registrieren (oder Fehler anzeigen)
{MessageBox(hFenster,"Fensterklasse konnte\n nicht registriert werden","Fehler", MB_OK); return 0;}
hFenster = CreateWindow ("Hauptfenster", "Warten auf Empfang", WS_OVERLAPPEDWINDOW,
// Hauptfenster erzeugen :
40, 20, 400, 300, HWND_DESKTOP, NULL, hInstanz, NULL);
ShowWindow (hFenster, nFensterStil); // ... und sichtbar machen
//------------------------------------------------------------------
Timer1Nummer=SetTimer(hFenster, 1, 1000, SchreibIntervall);
Timer2Nummer=SetTimer(hFenster, 2, 50, LeseIntervall);
//------------------------------------------------------------------
i = 48; // erstes ASCII-Zeichen soll 48 ('0') sein
OeffneCom(1, 9600, 'n', 8, 1); // Schnittstelle oeffnen und konfigurieren
//------------------------------------------------------------------
while (GetMessage (&Befehle, NULL, 0, 0)) // Dauerschleife (sendet Befehle an obige Fensterprozedur)
{TranslateMessage(&Befehle); DispatchMessage(&Befehle);}
return Befehle.wParam; }
|
DISCLAIMER: THIS SITE CONTAINS LINKS TO THIRD-PARTY WEBSITES, WHICH ARE NOT UNDER THE CONTROL OF STS.
THESE LINKS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
|
© 2013: STS Selected Technology Sites, all rights reserved.
|
|