Author Topic: Serielle Schnittstelle (COM port)  (Read 5629 times)

Offline Kitty Hello

  • code monkey
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 10695
  • here on my island the sea says 'hello'
    • View Profile
    • http://www.glbasic.com
Serielle Schnittstelle (COM port)
« on: 2008-Mar-12 »
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:
Code: GLBasic [Select]
// --------------------------------- //
// 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<sizeof(DCB); ++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<nread; ++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:
Code: GLBasic [Select]
// --------------------------------- //
// 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

sechsrad

  • Guest
Serielle Schnittstelle (COM port)
« Reply #1 on: 2008-Mar-13 »
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:

Code: GLBasic [Select]
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.

Code: GLBasic [Select]
#include <windows.h>
#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;
}
Code: GLBasic [Select]
#include        <windows.h>
#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;
}
Code: GLBasic [Select]
#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

sechsrad

  • Guest
Serielle Schnittstelle (COM port)
« Reply #2 on: 2008-Mar-13 »
hallo gernot , kannst du noch einmal nach der read$ schauen, die geht nicht  :
read$ = COM_Read$()

mfg

Offline Kitty Hello

  • code monkey
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 10695
  • here on my island the sea says 'hello'
    • View Profile
    • http://www.glbasic.com
Serielle Schnittstelle (COM port)
« Reply #3 on: 2008-Mar-14 »
Hast Du COM_Open mit bRead=TRUE gemacht?
Was sendest Du?

sechsrad

  • Guest
Serielle Schnittstelle (COM port)
« Reply #4 on: 2008-Mar-15 »
muss eigentlich eine leere test[] übergeben werden für diese : FUNCTION COM_Read: buffer[], nbytes

DIM test[55]
zahl = COM_Read(test[],55)

mfg

Offline Kitty Hello

  • code monkey
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 10695
  • here on my island the sea says 'hello'
    • View Profile
    • http://www.glbasic.com
Serielle Schnittstelle (COM port)
« Reply #5 on: 2008-Mar-15 »
ist egal. Macht ein DIM intern.

Offline Schranz0r

  • Premium User :)
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 5013
  • O Rly?
    • View Profile
Serielle Schnittstelle (COM port)
« Reply #6 on: 2008-Mar-15 »
Schnalt der doch net was du mit Intern meinst ;)
I <3 DGArray's :D

PC:
AMD RYzen 7 1700 @3.9Ghz, 16GB HyperX Fury 2666Mhz Ram, ASUS ROG GTX 1060 STRIX 6GB, Windows 10 Pro 64Bit, MSi Tomahawk B350 Mainboard