[NTLUG:Discuss] serial port revisited.
james osburn
jjosburn at hotmail.com
Thu Nov 11 21:58:32 CST 2004
you wanted to know what it looked like.
#include <stdio.h>
#include "rlserial.h"
#define SERIAL_DEVICE "/dev/ttyS0"
int main(int argc,char *argv[])
{
//open the serial port.
rlSerial tty;
char c;
int ret;
if(tty.openDevice(SERIAL_DEVICE,B9600,1,1,8,1) < 0 )
{
return -1;
}
while(1)
{
c = 0x0ff;
ret = tty.select(1);
if(ret == 1)
{
//tty.readCharEx();
c = tty.readChar();
fprintf(stderr,"%02x\n",(unsigned char)c);
}
}
tty.closeDevice();
return 0;
}
/***************************************************************************
rlserial.cpp - description
-------------------
begin : Sat Dec 21 2002
copyright : (C) 2002 by Rainer Lehrig
email : lehrig at t-online.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* I make one exception to the above statement: *
* You can use this software for commercial purposes *
* if you purchase a license *
* You will not be allowed to make changes to the software *
* *
***************************************************************************/
#include "rlserial.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include "rldefine.h"
/*
static void sighandler(int sig)
{
if(sig == SIGINT)
{
closeDevice();
closeDatabase();
}
}
*/
rlSerial::rlSerial()
{
ttysavefd = -1;
ttystate = RESET;
fd = -1;
trace = 0;
}
rlSerial::~rlSerial()
{
closeDevice();
}
void rlSerial::setTrace(int on)
{
if(on == 1) trace = 1;
else trace = 0;
}
int rlSerial::openDevice(const char *devicename, int speed, int block, int
rtscts, int bits, int stopbits)
{
struct termios buf;
if(fd != -1) return -1;
fd = open(devicename, O_RDWR | O_NOCTTY | O_NDELAY);
if(fd < 0) { return -1; }
//signal(SIGINT, sighandler);
if(tcgetattr(fd, &save_termios) < 0) { return -1; }
buf = save_termios;
buf.c_cflag = speed | CLOCAL | CREAD;
if(rtscts == 1) buf.c_cflag |= CRTSCTS;
if(bits == 7) buf.c_cflag |= CS7;
else buf.c_cflag |= CS8;
if(stopbits == 2) buf.c_cflag |= CSTOPB;
buf.c_lflag = IEXTEN; //ICANON;
buf.c_oflag = OPOST;
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
buf.c_line = 0;
buf.c_iflag = IGNBRK | IGNPAR | IXANY;
if(tcsetattr(fd, TCSAFLUSH, &buf) < 0) { return -1; }
ttystate = RAW;
ttysavefd = fd;
if(block == 1) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
tcflush(fd,TCIOFLUSH);
return 0;
}
int rlSerial::readCharEx()
{
int ret;
unsigned char buf[2];
if(fd == -1)
{
fprintf(stderr,"ret -1\n");
return -1;
}
buf[0]=0x00;
buf[1]=0x00;
ret = read(fd,buf,1);
if(ret == 1)
{
fprintf(stderr,"%x %x\n",buf[0],buf[1]);
return buf[0];
}
if(ret == 0)
{
fprintf(stderr,"ret -2\n");
return -2;
}
return -1;
}
int rlSerial::readChar()
{
int ret;
unsigned char buf[2];
if(fd == -1) return -1;
ret = read(fd,buf,1);
if(ret == 1) return buf[0];
if(ret == 0) return -2;
return -1;
}
int rlSerial::writeChar(unsigned char uchar)
{
int ret;
if(fd == -1) return -1;
if(trace == 1) printf("writeChar %d\n",(int)uchar);
ret = write(fd,&uchar,1);
if(ret < 0) return -1;
//tcflush(fd, TCIOFLUSH);
return ret;
}
int rlSerial::readBlock(void *buf, int len)
{
int ret = -1;
ret = read(fd,buf,len);
return ret;
}
int rlSerial::readBlock(unsigned char *buf, int len)
{
int c;
for(int i=0; i<len; i++)
{
c = readChar();
if(c < 0) return c;
buf[i] = (unsigned char) c;
}
return len;
}
int rlSerial::writeBlock(const unsigned char *buf, int len)
{
int ret;
if(fd == -1) return -1;
if(trace == 1)
{
printf("writeBlock:");
for(int i=0; i<len; i++) printf(" %d",(int) buf[i]);
printf("\n");
}
ret = write(fd,buf,len);
//tcflush(fd, TCIOFLUSH);
return ret;
}
int rlSerial::readLine(unsigned char *buf, int maxlen)
{
int i,c,ret;
if(maxlen <= 1) return -1;
ret = 0;
buf[maxlen-1] = '\0';
for(i=0; i<maxlen-2; i++)
{
ret = i;
c = readChar();
if(c < 0)
{
buf[i] = '\0';
ret = c;
break;
}
buf[i] = (unsigned char) c;
if(c < ' ')
{
buf[i+1] = '\0';
break;
}
}
return ret;
}
int rlSerial::select(int timeout)
{
struct timeval timout;
fd_set wset,rset,eset;
int ret,maxfdp1;
if(timeout <= 0) return 1;
/* setup sockets to read */
maxfdp1 = fd+1;
FD_ZERO(&rset);
FD_SET (fd,&rset);
FD_ZERO(&wset);
FD_ZERO(&eset);
timout.tv_sec = timeout / 1000;
timout.tv_usec = timeout % 1000;
ret = ::select(maxfdp1,&rset,&wset,&eset,&timout);
if(ret == 0) return 0; /* timeout */
return 1;
}
int rlSerial::closeDevice()
{
if(fd == -1) return -1;
if(::tcsetattr(fd,TCSAFLUSH,&save_termios) < 0) return -1;
::close(fd);
ttystate = RESET;
fd = -1;
return 0;
}
/***************************************************************************
rldefine.h - description
-------------------
begin : Wed Dec 04 2002
copyright : (C) 2001 by Rainer Lehrig
email : lehrig at t-online.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* I make one exception to the above statement: *
* You can use this software for commercial purposes *
* if you purchase a license *
* You will not be allowed to make changes to the software *
* *
***************************************************************************/
#ifndef _RL_DEFINE_H_
#define _RL_DEFINE_H_
// define unix if not already defined
#ifdef __unix__
#ifndef unix
#define unix
#endif
#endif
#define rl_PRINTF_LENGTH 4096
#define rl_PRINTF_LENGTH_SPREADSHEET 4096
#define BIT0 1
#define BIT1 2
#define BIT2 4
#define BIT3 8
#define BIT4 16
#define BIT5 32
#define BIT6 64
#define BIT7 128
#define BIT8 256*1
#define BIT9 256*2
#define BIT10 256*4
#define BIT11 256*8
#define BIT12 256*16
#define BIT13 256*32
#define BIT14 256*64
#define BIT15 256*128
#define BIT16 256*256*1
#define BIT17 256*256*2
#define BIT18 256*256*4
#define BIT19 256*256*8
#define BIT20 256*256*16
#define BIT21 256*256*32
#define BIT22 256*256*64
#define BIT23 256*256*128
#define BIT24 256*256*256*1
#define BIT25 256*256*256*2
#define BIT26 256*256*256*4
#define BIT27 256*256*256*8
#define BIT28 256*256*256*16
#define BIT29 256*256*256*32
#define BIT30 256*256*256*64
#define BIT31 256*256*256*128
#endif
#ifndef _RL_MODBUS_H_
#define _RL_MODBUS_H_
#include "rldefine.h"
#include "rlserial.h"
class rlModbus
{
public:
enum Modbus
{
MODBUS_CHECKSUM_ERROR = -2,
MODBUS_ERROR = -1,
MODBUS_SUCCESS = 0,
MODBUS_RTU = 1,
MODBUS_ASCII = 2
};
enum ModbusFunctionCodes
{
ReadCoilStatus = 1,
ReadInputStatus = 2,
ReadHoldingRegisters = 3,
ReadInputRegisters = 4,
ForceSingleCoil = 5,
PresetSingleRegister = 6,
ReadExceptionStatus = 7,
FetchCommEventCtr = 11,
FetchCommEventLog = 12,
ForceMultipleCoils = 15,
PresetMultipleRegs = 16,
ReportSlaveID = 17,
ReadGeneralReference = 20,
WriteGeneralReference = 21,
MaskWrite4XRegisters = 22,
ReadWrite4XRegisters = 23,
ReadFifoQueue = 24
};
rlModbus(long max_telegram_length = 1024, int mode = MODBUS_RTU, char
end_delimitor = 0x0a);
~rlModbus();
int write (int slave, int function, const unsigned char *data, int len);
int request (int slave, int function, int start_adr, int num_register);
int response(int *slave, int *function, unsigned char *data, int
timeout=1000);
int readRequest(int *slave, int *function, unsigned char *data, int
timeout=1000);
void registerSocket(rlSocket *socket);
void registerSerial(rlSerial *serial);
int data2int(const unsigned char *data);
int int2data(int val, unsigned char *data);
int intsize();
private:
int buf2int_rtu(unsigned char *buf);
void int2buf_rtu(int i, unsigned char *buf);
int buf2int_ascii(unsigned char *buf);
void int2buf_ascii(int i, unsigned char *buf);
void insertLRC(int len);
void insertCRC(int len);
int LRCerror(int len);
int CRCerror(int len);
rlSocket *s;
rlSerial *tty;
unsigned char *tel;
long maxtel;
int mode;
char delimitor;
};
/***************************************************************************
rlserial.cpp - description
-------------------
begin : Sat Dec 21 2002
copyright : (C) 2002 by Rainer Lehrig
email : lehrig at t-online.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* I make one exception to the above statement: *
* You can use this software for commercial purposes *
* if you purchase a license *
* You will not be allowed to make changes to the software *
* *
***************************************************************************/
#ifndef _RL_SERIAL_H_
#define _RL_SERIAL_H_
#ifdef unix
#include <termios.h>
#endif
#ifndef B0
// speed will be defined by termios.h, this is just for documentation
#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 B57600 0010001
#define B115200 0010002
#define B230400 0010003
#define B460800 0010004
#define B500000 0010005
#define B576000 0010006
#define B921600 0010007
#define B1000000 0010010
#define B1152000 0010011
#define B1500000 0010012
#define B2000000 0010013
#define B2500000 0010014
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
#endif
class rlSerial
{
public:
rlSerial();
~rlSerial();
int openDevice(const char *devicename, int speed=B9600, int block=1,
int rtscts=1, int bits=8, int stopbits=1);
int select(int timeout=500);
int readChar();
int writeChar(unsigned char uchar);
int readBlock(unsigned char *buf, int len);
int readBlock(void *buf, int len);
int writeBlock(const unsigned char *buf, int len);
int readLine(unsigned char *buf, int maxlen);
int closeDevice();
void setTrace(int on);
int readCharEx();
private:
struct termios save_termios;
enum { RESET, RAW, CBREAK } ttystate;
int ttysavefd;
int fd,trace;
};
#endif
More information about the Discuss
mailing list