[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