Uwe Osslowsky
05.11.2004, 16:10
Hallo allerseits. Ich habe folgendes Problem: Beim Starten des Programms erhalte ich einige Fehlermeldungen, die mich schon zuviel Zeit und Nerven gekostet haben.
1.Create File: COM5 -> "Zugriff verweigert"
2.GetCommState -> "Handle ist ungültig"
3.SetCommState -> "Handle ist ungültig"
4.GetCommState -> "Handle ist ungültig"
5.SetCommTimeouts -> "Handle ist ungültig"
Danach erst startet das eigentliche Programm. Ich lege den Code mal bei und wäre für Hilfe sehr dankbar.
//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
// #pragma link "ComPort"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void ShowLastError(AnsiString where)
{
// In der VCL einfach mit SysErrorMessage:
MessageBox(NULL,SysErrorMessage(GetLastError()).c_ str(),where.c_str(),MB_OK|MB_ICONERROR);
/* Ohne SysErrorMessage:
LPTSTR lpMsgBuf; // char*
FormatMessage( // siehe Online-Hilfe zu Win32
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)&lpMsgBuf, // Adresse des nullterminierten Meldungstextes
0,
NULL);
MessageBox( NULL, lpMsgBuf,where.c_str(),MB_OK|MB_ICONERROR);
LocalFree( lpMsgBuf ); // Free the buffer.
*/
}
void ShowTextAndValue(TMemo* t,AnsiString s,int Value)
{
t->Lines->Add(s+IntToStr(Value));
}
HANDLE OpenComm(char* Port)//
{
// Öffnet den Port und gibt sein Handle zurück
HANDLE hCom = CreateFile("COM5", // z.B. "COM1",
GENERIC_READ | GENERIC_WRITE, // Zum Senden und Empfangen
0, // Für comm devices exclusive-access notwendig
NULL, // Keine security attributes
OPEN_EXISTING, // Für comm devices OPEN_EXISTING notwendig
0, // In den folgenden Beispielen kein overlapped I/O
NULL); // Für comm devices muß hTemplate NULL sein
if (hCom == INVALID_HANDLE_VALUE)
ShowLastError("CreateFile: "+AnsiString(Port));
return hCom;
}
void showDCB(TMemo* M,HANDLE hCom)
{
DCB dcb; // Device Control Block
BOOL fSuccess = GetCommState(hCom, &dcb); // DCB lesen
if (!fSuccess) ShowLastError("GetCommState");
// DWORD DCBlength; // sizeof(DCB)
// DWORD BaudRate; // current baud rate
ShowTextAndValue(M,"baud rate: ",dcb.BaudRate);
ShowTextAndValue(M,"parity: ",dcb.fParity);
ShowTextAndValue(M,"CTS output flow control: ",dcb.fOutxCtsFlow);
ShowTextAndValue(M,"DSR output flow control: ",dcb.fOutxDsrFlow);
ShowTextAndValue(M,"DTR flow control type: ",dcb.fDtrControl);
ShowTextAndValue(M,"DSR sensitivity: ",dcb.fDsrSensitivity);
ShowTextAndValue(M,"RTS flow control: ",dcb.fRtsControl);
}
void SetDCB(HANDLE hCom)
{
DCB dcb; // Device Control Block
BOOL fSuccess = GetCommState(hCom, &dcb); // DCB lesen
if (!fSuccess) ShowLastError("GetCommState");
// Setze die Baudrate=9600, 8 Datenbits, keine Parity, 1 Stopbit:
dcb.BaudRate = 9600; // Baudrate=9600
dcb.ByteSize = 8; // 8 Datenbits
dcb.Parity = NOPARITY; // keine Parity
dcb.StopBits = ONESTOPBIT; // 1 Stopbit
bool NoFlowControl=false,
HardwareFlowControl=false,
SoftwareFlowControl=true;
// Oft spricht man auch von Hardware- bzw. Software-Handshake
// Die folgenden Ausführungen nach dem MSDN-Artikel
if (NoFlowControl)
{
// kein Hardware Flowcontrol:
dcb.fOutxCtsFlow=false;
dcb.fOutxDsrFlow=false;
// kein Software Flowcontrol:
dcb.fInX=false; // für Empfänger
dcb.fOutX=false; // für Sender
dcb.fDsrSensitivity=false;
}
else
{
if (HardwareFlowControl)
{
dcb.fOutxCtsFlow=true;
dcb.fOutxDsrFlow=true;
}
// Hier kein else: Software- und HardwareFlowControl sind
// gleichzeitig möglich, auch wenn das nicht üblich ist
if (SoftwareFlowControl)
{
dcb.fInX=true; // für Empfänger
dcb.fOutX=true; // für Sender
// Die folgenden Elemente steuern SoftwareFlowControl,
// Sie müssen aber nicht gesetzt werden. Oft reichen die
// Voreinstellungen.
// dcb.fTXContinueOnXoff=false;
// dcb.XonLim = ...;
// dcb.XoffLim = ...;
// dcb.XoffChar = ...;
// dcb.XonChar = ...;
}
}
// SetCommState konfiguriert die serielle Schnittstelle
fSuccess = SetCommState(hCom, &dcb);
if (!fSuccess) ShowLastError("SetCommState");
showDCB(Form1->Memo1,hCom);
}
void SetReadTimeouts(HANDLE hCom)
{ // Der Aufruf von SetCommTimeouts ist notwendig,
// da ohne diesen die Ergebnisse von Readfile undefiniert sind
COMMTIMEOUTS t;
// Alle Wert in Millisekunden
// Werte für ReadFile:
t.ReadIntervalTimeout=100; // Timeout zwischen zwei Zeichen
t.ReadTotalTimeoutMultiplier=10; // pro Zeichen
t.ReadTotalTimeoutConstant=1; //
// Wenn mit ReadFile n Zeichen gelesen werden sollen, tritt ein Timeout
// nach ReadTotalTimeoutMultiplier*n+ReadTotalTimeoutConst ant ms ein.
// Werte für WriteFile: wenn beide 0 sind,
// kein Timeout beim Schreiben
t.WriteTotalTimeoutMultiplier=0;
t.WriteTotalTimeoutConstant=0;
if (!SetCommTimeouts(hCom,&t))
ShowLastError("SetCommTimeouts");
}
void showCommProp(TMemo* M, HANDLE hCom)
{
/*typedef struct _COMMPROP{ // cmmp
WORD wPacketLength; // packet size, in bytes
WORD wPacketVersion; // packet version
DWORD dwServiceMask; // services implemented
DWORD dwReserved1; // reserved
DWORD dwMaxTxQueue; // max Tx bufsize, in bytes
DWORD dwMaxRxQueue; // max Rx bufsize, in bytes
DWORD dwMaxBaud; // max baud rate, in bps
DWORD dwProvSubType; // specific provider type
DWORD dwProvCapabilities; // capabilities supported
DWORD dwSettableParams; // changable parameters
DWORD dwSettableBaud; // allowable baud rates
WORD wSettableData; // allowable byte sizes
WORD wSettableStopParity; // stop bits/parity allowed
DWORD dwCurrentTxQueue; // Tx buffer size, in bytes
WORD dwCurrentRxQueue; // Rx buffer size, in bytes
DWORD dwProvSpec1; // provider-specific data
DWORD dwProvSpec2; // provider-specific data
WCHAR wcProvChar[1]; // provider-specific data
} COMMPROP;
*/
_COMMPROP CP;
GetCommProperties(hCom,&CP);
ShowTextAndValue(M,"max Tx bufsize, in bytes: ",CP.dwMaxTxQueue);
ShowTextAndValue(M,"max Rx bufsize, in bytes: ",CP.dwMaxRxQueue);
ShowTextAndValue(M,"Tx buffer size, in bytes: ",CP.dwCurrentTxQueue);
ShowTextAndValue(M,"Rx buffer size, in bytes: ",CP.dwCurrentRxQueue);
}
HANDLE hComSend,hComReceive;
void __fastcall TForm1::FormCreate(TObject *Sender)
{
BEmpfangClick(Sender);
hComSend=OpenComm("COM5");
hComReceive=OpenComm("COM5");
SetDCB(hComSend);
SetDCB(hComReceive);
SetReadTimeouts(hComReceive);
showCommProp(Form1->Memo1,hComSend);
showCommProp(Form1->Memo1,hComReceive);
}
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
CloseHandle(hComSend);
CloseHandle(hComReceive);
}
int SendData(char Data[],int n)
{
DWORD NumberOfBytesWritten; // Anzahl der gesendeten Bytes
bool b=WriteFile(hComSend,
Data,
n, // Anzahl der zu sendenden Bytes
&NumberOfBytesWritten, // Adresse, an die der Wert geschrieben wird
0); // kein overlapped I/O
if (!b)
ShowLastError("SendData");
return NumberOfBytesWritten;
}
void __fastcall TForm1::BSendenClick(TObject *Sender)
{
// int n=SendData("abcdefghijklmno",10);
int n=SendData(Edit1->Text.c_str(),Edit1->Text.Length());
Memo1->Lines->Add("Written: "+IntToStr(n));
}
DWORD ReceiveData(char* Data,int n)
{
DWORD NumberOfBytesRead; // Anzahl der gelesenen Bytes
bool b=ReadFile(hComReceive, // handle des Com-Ports
Data, // Adresse des Datenpuffers
n, // Anzahl der zu lesenden Bytes
&NumberOfBytesRead, // Adresse, an die der Wert geschrieben wird
0); // kein overlapped I/O
if (!b)
ShowLastError("ReceiveData");
return NumberOfBytesRead;
}
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
const int BufSize = 3;
char Buffer[BufSize]; // address of buffer that receives data
DWORD NumberOfBytesRead=ReceiveData(Buffer,BufSize);
if (NumberOfBytesRead > 0)
{
AnsiString s;
for (DWORD i=0;i<NumberOfBytesRead;i++)
s=s+Buffer[i];
Memo1->Lines->Add("Gelesen n="+IntToStr(NumberOfBytesRead)+" ch="+s);
}
else
{
Memo1->Lines->Add("Nichts empfangen");
}
}
void __fastcall TForm1::BEmpfangClick(TObject *Sender)
{
if (Timer1->Enabled)
{
Timer1->Enabled =false;
BEmpfang->Caption="Read-Timer disabled";
}
else
{
Timer1->Enabled=true;
BEmpfang->Caption="Read-Timer aktiv";
};
}
1.Create File: COM5 -> "Zugriff verweigert"
2.GetCommState -> "Handle ist ungültig"
3.SetCommState -> "Handle ist ungültig"
4.GetCommState -> "Handle ist ungültig"
5.SetCommTimeouts -> "Handle ist ungültig"
Danach erst startet das eigentliche Programm. Ich lege den Code mal bei und wäre für Hilfe sehr dankbar.
//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
// #pragma link "ComPort"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void ShowLastError(AnsiString where)
{
// In der VCL einfach mit SysErrorMessage:
MessageBox(NULL,SysErrorMessage(GetLastError()).c_ str(),where.c_str(),MB_OK|MB_ICONERROR);
/* Ohne SysErrorMessage:
LPTSTR lpMsgBuf; // char*
FormatMessage( // siehe Online-Hilfe zu Win32
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)&lpMsgBuf, // Adresse des nullterminierten Meldungstextes
0,
NULL);
MessageBox( NULL, lpMsgBuf,where.c_str(),MB_OK|MB_ICONERROR);
LocalFree( lpMsgBuf ); // Free the buffer.
*/
}
void ShowTextAndValue(TMemo* t,AnsiString s,int Value)
{
t->Lines->Add(s+IntToStr(Value));
}
HANDLE OpenComm(char* Port)//
{
// Öffnet den Port und gibt sein Handle zurück
HANDLE hCom = CreateFile("COM5", // z.B. "COM1",
GENERIC_READ | GENERIC_WRITE, // Zum Senden und Empfangen
0, // Für comm devices exclusive-access notwendig
NULL, // Keine security attributes
OPEN_EXISTING, // Für comm devices OPEN_EXISTING notwendig
0, // In den folgenden Beispielen kein overlapped I/O
NULL); // Für comm devices muß hTemplate NULL sein
if (hCom == INVALID_HANDLE_VALUE)
ShowLastError("CreateFile: "+AnsiString(Port));
return hCom;
}
void showDCB(TMemo* M,HANDLE hCom)
{
DCB dcb; // Device Control Block
BOOL fSuccess = GetCommState(hCom, &dcb); // DCB lesen
if (!fSuccess) ShowLastError("GetCommState");
// DWORD DCBlength; // sizeof(DCB)
// DWORD BaudRate; // current baud rate
ShowTextAndValue(M,"baud rate: ",dcb.BaudRate);
ShowTextAndValue(M,"parity: ",dcb.fParity);
ShowTextAndValue(M,"CTS output flow control: ",dcb.fOutxCtsFlow);
ShowTextAndValue(M,"DSR output flow control: ",dcb.fOutxDsrFlow);
ShowTextAndValue(M,"DTR flow control type: ",dcb.fDtrControl);
ShowTextAndValue(M,"DSR sensitivity: ",dcb.fDsrSensitivity);
ShowTextAndValue(M,"RTS flow control: ",dcb.fRtsControl);
}
void SetDCB(HANDLE hCom)
{
DCB dcb; // Device Control Block
BOOL fSuccess = GetCommState(hCom, &dcb); // DCB lesen
if (!fSuccess) ShowLastError("GetCommState");
// Setze die Baudrate=9600, 8 Datenbits, keine Parity, 1 Stopbit:
dcb.BaudRate = 9600; // Baudrate=9600
dcb.ByteSize = 8; // 8 Datenbits
dcb.Parity = NOPARITY; // keine Parity
dcb.StopBits = ONESTOPBIT; // 1 Stopbit
bool NoFlowControl=false,
HardwareFlowControl=false,
SoftwareFlowControl=true;
// Oft spricht man auch von Hardware- bzw. Software-Handshake
// Die folgenden Ausführungen nach dem MSDN-Artikel
if (NoFlowControl)
{
// kein Hardware Flowcontrol:
dcb.fOutxCtsFlow=false;
dcb.fOutxDsrFlow=false;
// kein Software Flowcontrol:
dcb.fInX=false; // für Empfänger
dcb.fOutX=false; // für Sender
dcb.fDsrSensitivity=false;
}
else
{
if (HardwareFlowControl)
{
dcb.fOutxCtsFlow=true;
dcb.fOutxDsrFlow=true;
}
// Hier kein else: Software- und HardwareFlowControl sind
// gleichzeitig möglich, auch wenn das nicht üblich ist
if (SoftwareFlowControl)
{
dcb.fInX=true; // für Empfänger
dcb.fOutX=true; // für Sender
// Die folgenden Elemente steuern SoftwareFlowControl,
// Sie müssen aber nicht gesetzt werden. Oft reichen die
// Voreinstellungen.
// dcb.fTXContinueOnXoff=false;
// dcb.XonLim = ...;
// dcb.XoffLim = ...;
// dcb.XoffChar = ...;
// dcb.XonChar = ...;
}
}
// SetCommState konfiguriert die serielle Schnittstelle
fSuccess = SetCommState(hCom, &dcb);
if (!fSuccess) ShowLastError("SetCommState");
showDCB(Form1->Memo1,hCom);
}
void SetReadTimeouts(HANDLE hCom)
{ // Der Aufruf von SetCommTimeouts ist notwendig,
// da ohne diesen die Ergebnisse von Readfile undefiniert sind
COMMTIMEOUTS t;
// Alle Wert in Millisekunden
// Werte für ReadFile:
t.ReadIntervalTimeout=100; // Timeout zwischen zwei Zeichen
t.ReadTotalTimeoutMultiplier=10; // pro Zeichen
t.ReadTotalTimeoutConstant=1; //
// Wenn mit ReadFile n Zeichen gelesen werden sollen, tritt ein Timeout
// nach ReadTotalTimeoutMultiplier*n+ReadTotalTimeoutConst ant ms ein.
// Werte für WriteFile: wenn beide 0 sind,
// kein Timeout beim Schreiben
t.WriteTotalTimeoutMultiplier=0;
t.WriteTotalTimeoutConstant=0;
if (!SetCommTimeouts(hCom,&t))
ShowLastError("SetCommTimeouts");
}
void showCommProp(TMemo* M, HANDLE hCom)
{
/*typedef struct _COMMPROP{ // cmmp
WORD wPacketLength; // packet size, in bytes
WORD wPacketVersion; // packet version
DWORD dwServiceMask; // services implemented
DWORD dwReserved1; // reserved
DWORD dwMaxTxQueue; // max Tx bufsize, in bytes
DWORD dwMaxRxQueue; // max Rx bufsize, in bytes
DWORD dwMaxBaud; // max baud rate, in bps
DWORD dwProvSubType; // specific provider type
DWORD dwProvCapabilities; // capabilities supported
DWORD dwSettableParams; // changable parameters
DWORD dwSettableBaud; // allowable baud rates
WORD wSettableData; // allowable byte sizes
WORD wSettableStopParity; // stop bits/parity allowed
DWORD dwCurrentTxQueue; // Tx buffer size, in bytes
WORD dwCurrentRxQueue; // Rx buffer size, in bytes
DWORD dwProvSpec1; // provider-specific data
DWORD dwProvSpec2; // provider-specific data
WCHAR wcProvChar[1]; // provider-specific data
} COMMPROP;
*/
_COMMPROP CP;
GetCommProperties(hCom,&CP);
ShowTextAndValue(M,"max Tx bufsize, in bytes: ",CP.dwMaxTxQueue);
ShowTextAndValue(M,"max Rx bufsize, in bytes: ",CP.dwMaxRxQueue);
ShowTextAndValue(M,"Tx buffer size, in bytes: ",CP.dwCurrentTxQueue);
ShowTextAndValue(M,"Rx buffer size, in bytes: ",CP.dwCurrentRxQueue);
}
HANDLE hComSend,hComReceive;
void __fastcall TForm1::FormCreate(TObject *Sender)
{
BEmpfangClick(Sender);
hComSend=OpenComm("COM5");
hComReceive=OpenComm("COM5");
SetDCB(hComSend);
SetDCB(hComReceive);
SetReadTimeouts(hComReceive);
showCommProp(Form1->Memo1,hComSend);
showCommProp(Form1->Memo1,hComReceive);
}
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
CloseHandle(hComSend);
CloseHandle(hComReceive);
}
int SendData(char Data[],int n)
{
DWORD NumberOfBytesWritten; // Anzahl der gesendeten Bytes
bool b=WriteFile(hComSend,
Data,
n, // Anzahl der zu sendenden Bytes
&NumberOfBytesWritten, // Adresse, an die der Wert geschrieben wird
0); // kein overlapped I/O
if (!b)
ShowLastError("SendData");
return NumberOfBytesWritten;
}
void __fastcall TForm1::BSendenClick(TObject *Sender)
{
// int n=SendData("abcdefghijklmno",10);
int n=SendData(Edit1->Text.c_str(),Edit1->Text.Length());
Memo1->Lines->Add("Written: "+IntToStr(n));
}
DWORD ReceiveData(char* Data,int n)
{
DWORD NumberOfBytesRead; // Anzahl der gelesenen Bytes
bool b=ReadFile(hComReceive, // handle des Com-Ports
Data, // Adresse des Datenpuffers
n, // Anzahl der zu lesenden Bytes
&NumberOfBytesRead, // Adresse, an die der Wert geschrieben wird
0); // kein overlapped I/O
if (!b)
ShowLastError("ReceiveData");
return NumberOfBytesRead;
}
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
const int BufSize = 3;
char Buffer[BufSize]; // address of buffer that receives data
DWORD NumberOfBytesRead=ReceiveData(Buffer,BufSize);
if (NumberOfBytesRead > 0)
{
AnsiString s;
for (DWORD i=0;i<NumberOfBytesRead;i++)
s=s+Buffer[i];
Memo1->Lines->Add("Gelesen n="+IntToStr(NumberOfBytesRead)+" ch="+s);
}
else
{
Memo1->Lines->Add("Nichts empfangen");
}
}
void __fastcall TForm1::BEmpfangClick(TObject *Sender)
{
if (Timer1->Enabled)
{
Timer1->Enabled =false;
BEmpfang->Caption="Read-Timer disabled";
}
else
{
Timer1->Enabled=true;
BEmpfang->Caption="Read-Timer aktiv";
};
}