In order to communicate with the serial port, you can use this solution. It works on Win32 so far.
Create a new file, paste this contents into it and add it to your project:
// --------------------------------- //
// Project: SerialPort
// Start: Wednesday, March 12, 2008
// IDE Version: 5.199
TYPE TComTimeouts
ReadIntervalTimeout%
ReadTotalTimeoutMultiplier%
ReadTotalTimeoutConstant%
WriteTotalTimeoutMultiplier%
WriteTotalTimeoutConstant%
ENDTYPE
INLINE
} // namespace
#ifdef WIN32 // ### WINDOWS ###
#define DWORD unsigned long
#define WINAPI __stdcall
#define __in
#define __inout
#define __in_opt
#define BOOL int
typedef HANDLE HLOCAL;
#define INVALID_HANDLE ((HANDLE)-1)
HANDLE g_hSerialFile[8]={INVALID_HANDLE,INVALID_HANDLE,INVALID_HANDLE,INVALID_HANDLE, INVALID_HANDLE,INVALID_HANDLE,INVALID_HANDLE,INVALID_HANDLE};
#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;
extern "C"
{
#ifdef UNICODE
HANDLE __stdcall CreateFileW (const wchar_t*,DWORD,DWORD,void*,DWORD,DWORD,HANDLE);
#else
HANDLE __stdcall CreateFileA (const char*,DWORD,DWORD,void*,DWORD,DWORD,HANDLE);
#endif
BOOL __stdcall GetCommState(HANDLE, LPDCB);
BOOL __stdcall SetCommState(HANDLE, LPDCB);
BOOL __stdcall GetCommTimeouts(HANDLE, COMMTIMEOUTS*);
BOOL __stdcall SetCommTimeouts(HANDLE, COMMTIMEOUTS*);
BOOL __stdcall WriteFile(HANDLE, const void*, DWORD numwrite, DWORD* nwritten, const void* overlapped);
BOOL __stdcall ReadFile(HANDLE, void*, DWORD numread, DWORD* nread, const void* overlapped);
BOOL __stdcall CloseHandle(HANDLE);
DWORD __stdcall GetLastError(void);
#ifdef UNICODE
DWORD __stdcall FormatMessageW(DWORD dwFlags, void* lpSource, DWORD dwMessageId, DWORD dwLanguageId, wchar_t* lpBuffer, DWORD nSize, void *Arguments);
#else
DWORD __stdcall FormatMessageA(DWORD dwFlags, void* lpSource, DWORD dwMessageId, DWORD dwLanguageId, char* lpBuffer, DWORD nSize, void *Arguments);
#endif
int __stdcall MessageBoxW(HWND hWnd, const wchar_t* lpText, const wchar_t* lpCaption, unsigned int uType);
}
#if 0
#ifdef WINCE
#define SERDLL "corelib.dll"
#else
#define SERDLL "kernel32.dll"
#endif
#ifdef UNICODE
DECLARE(CreateFileW, SERDLL, (const wchar_t*,DWORD,DWORD,void*,DWORD,DWORD,HANDLE),HANDLE);
#else
DECLARE(CreateFileA, SERDLL, (const char*,DWORD,DWORD,void*,DWORD,DWORD,HANDLE),HANDLE);
#endif
DECLARE(GetCommState, SERDLL, (HANDLE, LPDCB), BOOL);
DECLARE(SetCommState, SERDLL, (HANDLE, LPDCB), BOOL);
DECLARE(GetCommTimeouts, SERDLL, (HANDLE, COMMTIMEOUTS*), BOOL);
DECLARE(SetCommTimeouts, SERDLL, (HANDLE, COMMTIMEOUTS*), BOOL);
DECLARE(WriteFile, SERDLL, (HANDLE, const void*, DWORD numwrite, DWORD* nwritten, const void* overlapped), BOOL);
DECLARE(ReadFile, SERDLL, (HANDLE, void*, DWORD numread, DWORD* nread, const void* overlapped), BOOL);
DECLARE(CloseHandle, SERDLL, (HANDLE), BOOL);
// error handling
DECLARE(GetLastError, SERDLL, (void), DWORD);
#ifdef UNICODE
DECLARE(FormatMessageW, SERDLL, (DWORD dwFlags, void* lpSource, DWORD dwMessageId, DWORD dwLanguageId, wchar_t* lpBuffer, DWORD nSize, void *Arguments), DWORD);
#else
DECLARE(FormatMessageA, SERDLL, (DWORD dwFlags, void* lpSource, DWORD dwMessageId, DWORD dwLanguageId, char* lpBuffer, DWORD nSize, void *Arguments), DWORD);
#endif
#endif
#else // ### NOT WINDOWS ###
// Prototypes for Linux
extern "C"
{
typedef long off_t;
typedef int speed_t;
#define ssize_t int
typedef unsigned int size_t;
typedef int mode_t;
#define O_NOCTTY 0x8000
#define O_RDWR 2
#define O_NONBLOCK 0x0004
#define O_NDELAY O_NONBLOCK
#define TCIFLUSH 0
#define TCSANOW 0
#define EAGAIN 11
/* c_cflag bit meaning */
#define CBAUD 0000017
#define B0 0000000 /* hang up */
#define B50 0000001
#define B75 0000002
#define B110 0000003
#define B134 0000004
#define B150 0000005
#define B200 0000006
#define B300 0000007
#define B600 0000010
#define B1200 0000011
#define B1800 0000012
#define B2400 0000013
#define B4800 0000014
#define B9600 0000015
#define B19200 0000016
#define B38400 0000017
#define EXTA B19200
#define EXTB B38400
#define CSIZE 0000060
#define CS5 0000000
#define CS6 0000020
#define CS7 0000040
#define CS8 0000060
#define CSTOPB 0000100
#define CREAD 0000200
#define CPARENB 0000400
#define CPARODD 0001000
#define HUPCL 0002000
#define CLOCAL 0004000
#define CIBAUD 03600000 /* input baud rate (not used) */
#define CRTSCTS 020000000000 /* flow control */
#define NCCS 17
struct termios {
unsigned long c_iflag; /* input mode flags */
unsigned long c_oflag; /* output mode flags */
unsigned long c_cflag; /* control mode flags */
unsigned long c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[NCCS]; /* control characters */
};
int open(const char *pathname, mode_t mode);
int errno;
char *strerror(int errnum);
int tcgetattr(int fildes, struct termios *termios_p);
int tcsetattr(int fildes, int optional_actions, struct termios *termios_p);
int tcflush(int fildes, int queue_selector);
int cfsetospeed(struct termios *termios_p, speed_t speed);
int ioctl(int fildes, int request, ... /* arg */);
int open(const char *pathname, int flags);
ssize_t read(int fd, void *buf, size_t count);
int write(int fildes, const char * buf, off_t count);
int close(int fildes);
int printf(char*, ...);
}
#define INVALID_HANDLE 0
static int g_hSerialFile[8] = {INVALID_HANDLE,INVALID_HANDLE,INVALID_HANDLE,INVALID_HANDLE, INVALID_HANDLE,INVALID_HANDLE,INVALID_HANDLE,INVALID_HANDLE};
// closes the serial port
void CloseAdrPort(int iSlot)
{
// you may want to restore the saved port attributes
if (g_hSerialFile[iSlot] != INVALID_HANDLE)
{
close(g_hSerialFile[iSlot]);
} // end if
g_hSerialFile[iSlot] = INVALID_HANDLE;
} // end CloseAdrPort
// opens the serial port
// return code:
// > 0 = fd for the port
// -1 = open failed
int OpenAdrPort(int iSlot, int iRS232Port)
{
DGStr sPortName = "/dev/ttyS"+iRS232Port;
// make sure port is closed
CloseAdrPort();
g_hSerialFile[iSlot] = open(sPortName.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
if (fd < 0)
{
STDERR (CGStr("open error ")+DGNat(errno)+CGStr(" ")+CGStr(strerror(errno))+CGStr("\n"));
}
return g_hSerialFile[iSlot];
}
// 0 OK
// <0 failed
int SetAdrPortMode(int iSlot, int baud)
{
if(g_hSerialFile[iSlot] != INVALID_HANDLE)
{
struct termios my_termios;
tcgetattr(g_hSerialFile[iSlot], &my_termios);
/*
printf("fd is %d\n", g_hSerialFile[iSlot]);
// NOTE: you may want to save the port attributes
// here so that you can restore them later
printf("old cflag=%08x\n", my_termios.c_cflag);
printf("old oflag=%08x\n", my_termios.c_oflag);
printf("old iflag=%08x\n", my_termios.c_iflag);
printf("old lflag=%08x\n", my_termios.c_lflag);
printf("old line=%02x\n", my_termios.c_line);
*/
tcflush(g_hSerialFile[iSlot], TCIFLUSH);
my_termios.c_cflag = 0;
switch(baud)
{
#define MKB(a) case a: my_termios.c_cflag |= B ## a; break;
MKB(0);
MKB(50);
MKB(75);
MKB(110);
MKB(150);
MKB(200);
MKB(300);
MKB(600);
MKB(1200);
MKB(1800);
MKB(2400);
MKB(4800);
MKB(9600);
MKB(19200);
MKB(38400);
default:
return -1;
}
my_termios.c_cflag |= (CS8 |CREAD | CLOCAL | HUPCL);
cfsetospeed(&my_termios, B9600);
tcsetattr(g_hSerialFile[iSlot], TCSANOW, &my_termios);
printf("new cflag=%08x\n", my_termios.c_cflag);
printf("new oflag=%08x\n", my_termios.c_oflag);
printf("new iflag=%08x\n", my_termios.c_iflag);
printf("new lflag=%08x\n", my_termios.c_lflag);
printf("new line=%02x\n", my_termios.c_line);
} // end if
return 0;
}
// writes zero terminated string to the serial port
// return code:
// >= 0 = number of characters written
// -1 = write failed
int WriteAdrPort(int iSlot, const char* psOutput, int outlen)
{
return write(g_hSerialFile[iSlot], psOutput, outlen);
}
// read string from the serial port
// return code:
// >= 0 = number of characters read
// -1 = read failed
int ReadAdrPort(int iSlot, char* psResponse, int iMax)
{
int iIn;
iIn = read(g_hSerialFile[iSlot], psResponse, iMax-1);
if (iIn < 0)
{
if (errno == EAGAIN)
{
return 0; // assume that command generated no response
}
}
return iIn;
}
#endif // ### WIN / LINUX ###
namespace __GLBASIC__ {
ENDINLINE
FUNCTION DebugLastError:
INLINE
#ifdef WIN32
DWORD err = ::GetLastError();
// DGStr serr = DGStr("Error number: ") + (DGNat)err;
// MessageBoxW((HWND)GLBASIC_HWND(), serr.w_str(), L"Debug:", 1);
#ifdef UNICODE
wchar_t lpMsgBuf[1024];
FormatMessageW(0x00001000 | 0x00000200, NULL, err, 1<<10, lpMsgBuf, 1024, NULL);
// MessageBoxW((HWND)GLBASIC_HWND(), lpMsgBuf, L"Debug:", 1);
#else
char lpMsgBuf[1024];
FormatMessageA(0x00001000 | 0x00000200, NULL, err, 1<<10, lpMsgBuf, 1024, NULL);
#endif
DEBUG(DGStr(lpMsgBuf));
DEBUG(DGStr("\n"));
#else
DEBUG(CGStr(strerror(errno)) + CGStr("\n"));
#endif
ENDINLINE
ENDFUNCTION
FUNCTION COM_Open: iSlot%, port%, bRead, bWrite
INLINE
#ifdef WIN32
DGStr port_Str = CGStr("COM") + port + CGStr(":");
#ifdef UNICODE
g_hSerialFile[iSlot] = ::CreateFileW(port_Str.w_str(), (bRead?GENERIC_READ:0)|(bWrite?GENERIC_WRITE:0),0,0,OPEN_EXISTING, 0,0);
#else
g_hSerialFile[iSlot] = ::CreateFileA(port_Str.c_str(), (bRead?GENERIC_READ:0)|(bWrite?GENERIC_WRITE:0),0,0,OPEN_EXISTING, 0,0);
#endif
if(g_hSerialFile[iSlot] == INVALID_HANDLE)
{
port_Str = CGStr("Error opening port: ")+port_Str;
DebugLastError();
}
return (g_hSerialFile[iSlot]!=INVALID_HANDLE) ? TRUE:FALSE;
#else
return (OpenAdrPort(iSlot, port) < 0) ? FALSE:TRUE;
#endif
ENDINLINE
ENDFUNCTION
FUNCTION COM_Close: iSlot%
INLINE
#ifdef WIN32
if(g_hSerialFile[iSlot] != INVALID_HANDLE)
{
::CloseHandle(g_hSerialFile[iSlot]);
g_hSerialFile[iSlot]=INVALID_HANDLE;
}
#else
CloseAdrPort(iSlot);
#endif
ENDINLINE
ENDFUNCTION
// parity: 0 = none, 1=even, 2=mark, 3=space
FUNCTION COM_SetComState: iSlot%, baud, parity, databits, stopbits
INLINE
#ifdef WIN32
DCB MyDCB;
for(int i=0; i<sizeof(DCB); ++i)
{
((char*)&MyDCB)[i] = 0;
}
MyDCB.DCBlength = sizeof(DCB);
if( GetCommState(g_hSerialFile[iSlot], &MyDCB))
{
MyDCB.BaudRate=(int)baud;
MyDCB.Parity = (int)parity;
MyDCB.ByteSize = (int)databits;
MyDCB.StopBits = (int)stopbits;
return SetCommState(g_hSerialFile[iSlot], &MyDCB);
}
return FALSE;
#else
SetAdrPortMode(iSlot, baud);
// #NEED parity and shit
#endif
ENDINLINE
ENDFUNCTION
FUNCTION COM_SetCommTimeouts%: iSlot%, tout AS TComTimeouts
INLINE
#ifdef WIN32
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[iSlot], &co);
#else
// ???
#endif
ENDINLINE
ENDFUNCTION
FUNCTION COM_Read$: iSlot%, nbytes% = 1024
INLINE
DGStr buf;
#ifdef WIN32
DWORD nread =0;
ReadFile(g_hSerialFile[iSlot], buf.getbuffer(nbytes+1), nbytes, &nread, NULL);
#else
int nread = ReadAdrPort(iSlot, buf.getbuffer(nbytes+1), nbytes);
#endif
if(nread > 0)
{
buf[(int)nread] = '\0';
buf.setlength(nread);
return buf;
}
return DGStr("");
ENDINLINE
ENDFUNCTION
FUNCTION COM_Write%: iSlot%, text$
INLINE
#ifdef WIN32
DWORD nwrite =0;
if( WriteFile(g_hSerialFile[iSlot], text_Str.c_str(), (DWORD)LEN(text_Str), &nwrite, NULL))
return nwrite;
return 0;
#else
return WriteAdrPort(iSlot, text_Str.c_str(), LEN(text_Str));
#endif
ENDINLINE
ENDFUNCTION
Here's a test program for the library:
// --------------------------------- //
// Project: SerialPort
// Start: Wednesday, March 12, 2008
// IDE Version: 5.199
port% = 1 // COM1 / /dev/ttyS1
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(0, port, FALSE, TRUE) = FALSE THEN Error("open COM2 failed")
// Set Baud rate and handshake
IF COM_SetComState(0, baud, parity, datab, stop) = FALSE THEN Error("Failed to set com state")
// optionally set com timeouts
// LOCAL tout AS TComTimeouts
// tout.ReadIntervalTimeout = 0xffffffff
// tout.ReadTotalTimeoutMultiplier = 0
// tout.ReadTotalTimeoutConstant = 0
// tout.WriteTotalTimeoutMultiplier= 0
// tout.WriteTotalTimeoutConstant = 0
// COM_SetCommTimeouts(0, tout)
// Write something
IF COM_Write(0, "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(0)
MOUSEWAIT
END
FUNCTION Error: txt$
PRINT txt$, 0,0
SHOWSCREEN
MOUSEWAIT
END
ENDFUNCTION