[NTLUG:Discuss] serial port revisited.

james osburn jjosburn at hotmail.com
Fri Nov 12 08:25:36 CST 2004


http://www.comptechdoc.org/os/linux/programming/c/linux_pgcserial.html

<html><DIV></DIV></html>



>From: "james osburn" <jjosburn at hotmail.com>
>Reply-To: NTLUG Discussion List <discuss at ntlug.org>
>To: discuss at ntlug.org
>Subject: Re: [NTLUG:Discuss] serial port revisited. Date: Fri, 12 Nov 2004 
>03:58:32 +0000
>
>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
>
>
>
>_______________________________________________
>https://ntlug.org/mailman/listinfo/discuss





More information about the Discuss mailing list