Um mit der seriellen Schnittsstelle zu kommunizieren kann man diese Lösung verwenden. Derzeit nur unter Win32 möglich.
Eine neue Datei anlegen, diesen Inhalt reinkopieren und zum Projekt hinzufügen:
// --------------------------------- //
// Project: SerialPort
// Start: Wednesday, March 12, 2008
// IDE Version: 5.199
TYPE TComTimeouts
ReadIntervalTimeout
ReadTotalTimeoutMultiplier
ReadTotalTimeoutConstant
WriteTotalTimeoutMultiplier
WriteTotalTimeoutConstant
ENDTYPE
INLINE
#define DWORD unsigned long
#define WINAPI __stdcall
#define __in
#define __inout
#define __in_opt
#define BOOL int
HANDLE g_hSerialFile=0;
} // namespace
#define GENERIC_READ (0x80000000L)
#define GENERIC_WRITE (0x40000000L)
#define CREATE_NEW 1
#define CREATE_ALWAYS 2
#define OPEN_EXISTING 3
#define OPEN_ALWAYS 4
typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout;
DWORD ReadTotalTimeoutMultiplier;
DWORD ReadTotalTimeoutConstant;
DWORD WriteTotalTimeoutMultiplier;
DWORD WriteTotalTimeoutConstant;
} COMMTIMEOUTS,
*LPCOMMTIMEOUTS;
typedef struct _DCB {
DWORD DCBlength;
DWORD BaudRate;
DWORD fBinary;
DWORD fParity;
DWORD fOutxCtsFlow;
DWORD fOutxDsrFlow;
DWORD fDtrControl;
DWORD fDsrSensitivity;
DWORD fTXContinueOnXoff;
DWORD fOutX;
DWORD fInX;
DWORD fErrorChar;
DWORD fNull;
DWORD fRtsControl;
DWORD fAbortOnError;
DWORD fDummy2;
WORD wReserved;
WORD XonLim;
WORD XoffLim;
BYTE ByteSize;
BYTE Parity;
BYTE StopBits;
char XonChar;
char XoffChar;
char ErrorChar;
char EofChar;
char EvtChar;
WORD wReserved1;
} DCB,
*LPDCB;
DECLARE(CreateFileA, "kernel32.dll", (LPCTSTR,DWORD,DWORD,void*,DWORD,DWORD,HANDLE),HANDLE);
DECLARE(GetCommState, "kernel32.dll", (HANDLE, LPDCB), BOOL);
DECLARE(SetCommState, "kernel32.dll", (HANDLE, LPDCB), BOOL);
DECLARE(GetCommTimeouts, "kernel32.dll", (HANDLE, COMMTIMEOUTS*), BOOL);
DECLARE(SetCommTimeouts, "kernel32.dll", (HANDLE, COMMTIMEOUTS*), BOOL);
DECLARE(WriteFile, "kernel32.dll", (HANDLE, void*, DWORD numwrite, DWORD* nwritten, void* overlapped), BOOL);
DECLARE(ReadFile, "kernel32.dll", (HANDLE, void*, DWORD numread, DWORD* nread, void* overlapped), BOOL);
DECLARE(CloseHandle, "kernel32.dll", (HANDLE), BOOL);
// error handling
DECLARE(GetLastError, "kernel32.dll", (void), DWORD);
DECLARE(FormatMessageA, "kernel32.dll", (DWORD dwFlags, void* lpSource, DWORD dwMessageId, DWORD dwLanguageId, char** lpBuffer, DWORD nSize, void *Arguments), DWORD);
DECLARE(LocalFree, "kernel32.dll", (HANDLE), HANDLE);
namespace __GLBASIC__ {
ENDINLINE
FUNCTION DebugLastError:
INLINE
DWORD err = ::GetLastError();
char* lpMsgBuf;
FormatMessageA(0x00000100 | 0x00001000 | 0x00000200, NULL, err, 1<<10, &lpMsgBuf, 0, NULL);
DEBUG(CGStr(lpMsgBuf));
DEBUG(DGStr("\n"));
LocalFree((HANDLE)lpMsgBuf);
ENDINLINE
ENDFUNCTION
FUNCTION COM_Open: port$, bRead, bWrite
INLINE
g_hSerialFile = ::CreateFileA(port_Str.c_str(), (bRead?GENERIC_READ:0)|(bWrite?GENERIC_WRITE:0),0,0,OPEN_EXISTING, 0,0);
if((int)g_hSerialFile == -1)
DebugLastError();
return ((int)g_hSerialFile!=-1) ? TRUE:FALSE;
ENDINLINE
ENDFUNCTION
FUNCTION COM_Close:
INLINE
::CloseHandle(g_hSerialFile);
g_hSerialFile=0;
ENDINLINE
ENDFUNCTION
// parity: 0 = none, 1=even, 2=mark, 3=space
FUNCTION COM_SetComState: baud, parity, databits, stopbits
INLINE
DCB MyDCB;
for(int i=0; i {
((char*)&MyDCB)[i] = 0;
}
MyDCB.DCBlength = sizeof(DCB);
if( GetCommState(g_hSerialFile, &MyDCB))
{
MyDCB.BaudRate=(int)baud;
MyDCB.Parity = (int)parity;
MyDCB.ByteSize = (int)databits;
MyDCB.StopBits = (int)stopbits;
return SetCommState(g_hSerialFile, &MyDCB);
}
return FALSE;
ENDINLINE
ENDFUNCTION
FUNCTION COM_SetCommTimeouts: tout AS TComTimeouts
INLINE
COMMTIMEOUTS co;
co.ReadIntervalTimeout =tout.ReadIntervalTimeout;
co.ReadTotalTimeoutMultiplier =tout.ReadTotalTimeoutMultiplier;
co.ReadTotalTimeoutConstant =tout.ReadTotalTimeoutConstant;
co.WriteTotalTimeoutMultiplier=tout.WriteTotalTimeoutMultiplier;
co.WriteTotalTimeoutConstant =tout.WriteTotalTimeoutConstant;
::SetCommTimeouts(g_hSerialFile, &co);
ENDINLINE
ENDFUNCTION
FUNCTION COM_Read: buffer[], nbytes
INLINE
char buf[1024];
DWORD nread =0;
if( ReadFile(g_hSerialFile, buf, nbytes, &nread, 0))
{
DIM(buffer, nread);
for(int i=0; i buffer(i) = buf[i];
return nread;
}
return 0;
ENDINLINE
ENDFUNCTION
FUNCTION COM_Read$:
INLINE
char buf[1024];
DWORD nread =0;
if( ReadFile(g_hSerialFile, buf, 1024, &nread, 0))
{
buf[nread] = '\0';
DGStr str(CGStr((const char*)buf));
return str;
}
return CGStr("");
ENDINLINE
ENDFUNCTION
FUNCTION COM_Write: buffer[], nbytes
INLINE
char buf[1024];
DWORD nwrite =0;
for(int i=0; i<(int)nbytes; ++i)
buf[i] = (char)buffer(i);
buf[(int)nbytes]='\0';
if( WriteFile(g_hSerialFile, buf, (DWORD)nbytes, &nwrite, 0))
{
return nwrite;
}
return 0;
ENDINLINE
ENDFUNCTION
FUNCTION COM_WriteStr: text$
LOCAL buf[], i, n
n = LEN(text$)
DIM buf[n]
FOR i=0 TO n-1
buf[i] = ASC(MID$(text$, i,1))
NEXT
RETURN COM_Write(buf[], n)
ENDFUNCTION
Hier ein Testporgramm:
// --------------------------------- //
// Project: SerialPort
// Start: Wednesday, March 12, 2008
// IDE Version: 5.199
port$ = "COM1"
baud = 19200 // baud rate
parity = 0 // 0=none, 1=odd, 2=even, 3=mark, 4=space
datab = 8 // data bits
stop = 0 // stop bits: 0=1 (ONE) stop bit, 1=1.5 bits, 2=2 bits
// Open COM port for writing
IF COM_Open(port$, FALSE, TRUE) = FALSE THEN Error("open COM2 failed")
// Set Baud rate and handshake
IF COM_SetComState(baud, parity, datab, stop) = FALSE THEN Error("Failed to set com state")
// optionally set com timeouts
// LOCAL tout AS TComTimeouts
// tout.ReadIntervalTimeout = ..
// tout.ReadTotalTimeoutMultiplier = ..
// tout.ReadTotalTimeoutConstant = ..
// tout.WriteTotalTimeoutMultiplier= ..
// tout.WriteTotalTimeoutConstant = ..
// COM_SetCommTimeouts(tout)
// Write something
IF COM_WriteStr("ABC\n")=0 THEN Error("Failed to write data")
// Read something - make sure you COM_Open(..., TRUE, ...) before
// read$ = COM_Read$()
// close COM port
COM_Close()
MOUSEWAIT
END
FUNCTION Error: txt$
PRINT txt$, 0,0
SHOWSCREEN
MOUSEWAIT
END
ENDFUNCTION
habe mich mal an den "dev-c++ version 4.9.9.2" ran gemacht.
der c-compiler ist faszinierend für die verbindung mit glbasic und auch um programme für den gp2x (gpe) herzustellen.
es lohnt sich das ding runterzuladen und damit zu spielen.
habe auch hier nach eine lösung gesucht um für das glbasic routinen zu ergänzen die man evtl braucht.
natürlich dll-routinen. und als übung natürlich wieder die com-schnittstelle , funktionieren fehlerfrei.
war eine googlerei für diese routinen.
FUNCTION glb_empfchar
FUNCTION glb_sendtext: txt$, zahl
FUNCTION glb_sendchar: zahl
FUNCTION glb_open:
FUNCTION glb_close:
a$ = "1234567890"+CHR$(13)
glb_open()
SLEEP 100
glb_sendtext(a$,11)
//glb_sendchar(66)
//glb_sendchar(13)
SLEEP 500
FOR c=1 TO 10
SLEEP 500
b=glb_empfchar()
PRINT b,100,100
SHOWSCREEN
NEXT
glb_close()
MOUSEWAIT
FUNCTION nichts:
ENDFUNCTION
INLINE
DECLARE(close_com2, "com-dll.dll", (), void);
DECLARE(open_com2, "com-dll.dll", (), void);
DECLARE(sendtext_com2, "com-dll.dll", (const char*, unsigned int), void);
DECLARE(sendchar_com2, "com-dll.dll", (int), void);
DECLARE(empfchar_com2, "com-dll.dll", (), unsigned int);
ENDINLINE
FUNCTION glb_empfchar:
LOCAL result
INLINE
result = empfchar_com2();
ENDINLINE
RETURN result
ENDFUNCTION
FUNCTION glb_sendtext: txt$, zahl
INLINE
sendtext_com2(txt_Str.c_str(),zahl);
ENDINLINE
ENDFUNCTION
FUNCTION glb_sendchar: zahl
INLINE
sendchar_com2(zahl);
ENDINLINE
ENDFUNCTION
FUNCTION glb_open:
INLINE
open_com2();
ENDINLINE
ENDFUNCTION
FUNCTION glb_close:
INLINE
close_com2();
ENDINLINE
ENDFUNCTION
und hier mal den code zum spielen für die com-dll :
1. die datei wo die dll mit hergestellt wird
2. die dazugehörige comtools.cpp
3. die dazugehörige comtools.h
com2 mit 19200 baud, kann aber geändert werden.
könnte man auch dynamisch ändern/proggen mit übergaben an die routine.
#include
#include "ComTools.h"
#define COM1 0
#define COM2 1
#define COM3 2
#define COM4 3
extern "C" __declspec(dllexport) int __stdcall open_com2()
{
ComOpen(COM2,19200,P_NONE,S_1BIT,D_8BIT);
}
extern "C" __declspec(dllexport) int __stdcall close_com2()
{
ComClose(COM2);
}
extern "C" __declspec(dllexport) int __stdcall sendtext_com2(int *cBuffer, int anzahl)
{
ComWrite(COM2,cBuffer,anzahl);
}
extern "C" __declspec(dllexport) int __stdcall sendchar_com2(int zahl)
{
ComWritechar(COM2,zahl);
}
extern "C" __declspec(dllexport) int __stdcall empfchar_com2()
{
char c;
c=ComReadchar(COM2);
return c;
}
#include
#include "ComTools.h"
#define MAX_COM_PORTS 8
static HANDLE hComFile[MAX_COM_PORTS];
static BOOL bIsOpen [MAX_COM_PORTS];
//*****************************************************************************
//*
//* ComOpen
//*
//*****************************************************************************
// Öffnet eine serielle Verbindung
// Nr : Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
// Baud : Ist die Bautrate
// Parity : 0 = kein Parity Bit
// 1 = gerade
// 2 = ungerade
// 3 = immer 0
// 4 = immer 1
// Stopbits : 0 = Ein Stopbit
// 1 = Ein/einhalb Stopbits
// 2 = Zwei Stopbits
// Bits : 0 = 7 Datenbits
// 1 = 8 Datenbits
// 7 = 7 Datenbits
// 8 = 8 Datenbits
// Ergibt 1 wenn eine Schnittstelle geöffnet wurde
int ComOpen(unsigned Nr,int Baud,int Parity,int Stopbits,int Databits)
{
static const int iPMode[]={NOPARITY,EVENPARITY,ODDPARITY,SPACEPARITY,MARKPARITY};
static const int iSMode[]={ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS,ONESTOPBIT};
char cName[]="COM2";
HANDLE hFile;
COMMTIMEOUTS sTo;
DCB sDcb;
if(Nr>=MAX_COM_PORTS)return 0;
if(bIsOpen[Nr])return 0;
cName[7]='1'+Nr;
hFile= CreateFile(cName,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if(hFile==INVALID_HANDLE_VALUE)
{
hFile=0;
return 0;
}
if(Databits==7)Databits=0;
memset(&sDcb,0,sizeof(sDcb));
sDcb.DCBlength=sizeof(sDcb);
sDcb.BaudRate = Baud;
sDcb.fParity = (Parity!=0)? TRUE:FALSE;
sDcb.fBinary = TRUE;
sDcb.Parity = iPMode[Parity];
sDcb.StopBits = iSMode[Stopbits&3];
sDcb.fOutxCtsFlow = FALSE;
sDcb.fOutxDsrFlow = FALSE;
sDcb.fDtrControl = DTR_CONTROL_ENABLE;
sDcb.fRtsControl = RTS_CONTROL_ENABLE;
sDcb.fDsrSensitivity= FALSE;
sDcb.fAbortOnError = FALSE;
sDcb.ByteSize = (Databits)? 8:7;
if(!SetCommState(hFile,&sDcb))
{
CloseHandle(hFile);
return 0;
}
sTo.ReadIntervalTimeout = MAXDWORD; // 0 ms Read-Tomeout
sTo.ReadTotalTimeoutMultiplier = 0;
sTo.ReadTotalTimeoutConstant = 0;
sTo.WriteTotalTimeoutMultiplier= 12000/Baud+1; // ? ms Write timeout per byte
sTo.WriteTotalTimeoutConstant = sTo.WriteTotalTimeoutMultiplier+1;
if(!SetCommTimeouts((HANDLE)hFile,&sTo))
{
CloseHandle(hFile);
return 0;
}
hComFile[Nr]=hFile;
bIsOpen [Nr]=TRUE;
return 1;
}
//*****************************************************************************
//*
//* ComClose
//*
//*****************************************************************************
// Schließt eine serielle Verbindung
// Nr : Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
// Ergibt 1 wenn eine Schnittstelle geschlossen wurde
int ComClose(unsigned Nr)
{
if(Nr>=MAX_COM_PORTS)return 0;
if(!bIsOpen[Nr])return 0;
CloseHandle(hComFile[Nr]);
hComFile[Nr]=0;
bIsOpen [Nr]=FALSE;
return 1;
}
//*****************************************************************************
//*
//* ComReadchar
//*
//*****************************************************************************
// Ein Zeichen lesen
// Nr : Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
// Ergibt -1 wenn nichts gelesen wurde sonst das Zeichen
int ComReadchar(unsigned Nr)
{
unsigned char c;
DWORD dwCount;
if(Nr>=MAX_COM_PORTS)return -1;
if(!bIsOpen[Nr])return -1;
if(!ReadFile(hComFile[Nr],&c,1,&dwCount,0))return -1;
if(dwCount!=1)return -1;
return c;
}
//*****************************************************************************
//*
//* ComRead
//*
//*****************************************************************************
// Mehrere Zeichen lesen
// Nr : Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
// Buffer : Buffer in dem die Zeichen gespeichert werden
// Max : Maximale Anzahl der zu lesenden Zeichen
// Ergibt die Anzahl der gelesenen Zeichen
int ComRead(unsigned Nr,void *Buffer,int Max)
{
DWORD dwCount;
if(Nr>=MAX_COM_PORTS)return 0;
if(!bIsOpen[Nr])return 0;
ReadFile(hComFile[Nr],Buffer,Max,&dwCount,0);
return dwCount;
}
//*****************************************************************************
//*
//* ComWritechar
//*
//*****************************************************************************
// Ein Zeichen senden
// Nr : Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
// Zeichen : Ist das Zeichen das gesendet werden soll.
// Ergibt die Anzahl der gesendeten Zeichen
int ComWritechar(unsigned Nr,int Zeichen)
{
DWORD dwCount;
if(Nr>=MAX_COM_PORTS)return 0;
if(!bIsOpen[Nr])return 0;
WriteFile(hComFile[Nr],&Zeichen,1,&dwCount,0);
return dwCount;
}
//*****************************************************************************
//*
//* ComWrite
//*
//*****************************************************************************
// Mehrere Zeichen schreiben
// Nr : Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
// Buffer : Buffer in dem die Zeichen gespeichert werden
// Count : Anzahl der zu sendenden Zeichen
// Ergibt die Anzahl der gesendeten Zeichen
int ComWrite(unsigned Nr,void *Buffer,int Count)
{
DWORD dwCount;
if(Nr>=MAX_COM_PORTS)return 0;
if(!bIsOpen[Nr])return 0;
WriteFile(hComFile[Nr],Buffer,Count,&dwCount,0);
return dwCount;
}
//*****************************************************************************
//*
//* ComGetReadCount
//*
//*****************************************************************************
// Ergibt die Anzahl der Bytes die im Lesepuffer der Schnittstelle sind
// Nr : Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
// Ergibt die Anzahl der Bytes im Buffer
int ComGetReadCount(unsigned Nr)
{
COMSTAT sComStat;
DWORD dwErrorFlags;
if(Nr>=MAX_COM_PORTS)return 0;
if(!bIsOpen[Nr])return 0;
dwErrorFlags=0;
if(!ClearCommError(hComFile[Nr], &dwErrorFlags, &sComStat))return 0;
return sComStat.cbInQue;
}
//*****************************************************************************
//*
//* ComGetWriteCount
//*
//*****************************************************************************
// Ergibt die Anzahl der Bytes die im Schreibpuffer der Schnittstelle sind
// Nr : Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
// Ergibt die Anzahl der Bytes im Buffer
int ComGetWriteCount(unsigned Nr)
{
COMSTAT sComStat;
DWORD dwErrorFlags;
if(Nr>=MAX_COM_PORTS)return 0;
if(!bIsOpen[Nr])return 0;
dwErrorFlags=0;
if(!ClearCommError(hComFile[Nr], &dwErrorFlags, &sComStat))return 0;
return sComStat.cbOutQue;
}
#ifndef __COM_TOOLS_H__
#define __COM_TOOLS_H__
// Konstanden für Parity
#define P_NONE 0 // 0 = kein Parity Bit
#define P_EVEN 1 // 1 = gerade
#define P_ODD 2 // 2 = ungerade
#define P_SPACE 3 // 3 = immer 0
#define P_MARK 4 // 4 = immer 1
#define D_7BIT 0 // 7-Databits
#define D_8BIT 1 // 8-Databits
#define S_1BIT 0 // 1 Stopbit
#define S_1_5BIT 1 // 1.5 Stopbits
#define S_2BIT 2 // 2 Stopbits
int ComOpen (unsigned Nr,int Baud=19200,int Parity=P_NONE,int Stopbits=S_1BIT,int Databits=D_8BIT);
int ComClose(unsigned Nr);
int ComRead (unsigned Nr,void *Buffer,int Max);
int ComReadchar (unsigned Nr);
int ComWrite(unsigned Nr,void *Buffer,int Count);
int ComWritechar(unsigned Nr,int Zeichen);
int ComGetReadCount (unsigned Nr);
int ComGetWriteCount(unsigned Nr);
#endif
hallo gernot , kannst du noch einmal nach der read$ schauen, die geht nicht :
read$ = COM_Read$()
mfg
Hast Du COM_Open mit bRead=TRUE gemacht?
Was sendest Du?
muss eigentlich eine leere test[] übergeben werden für diese : FUNCTION COM_Read: buffer[], nbytes
DIM test[55]
zahl = COM_Read(test[],55)
mfg
ist egal. Macht ein DIM intern.
Schnalt der doch net was du mit Intern meinst ;)