[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