#include <termios.h> /* tcgetattr, tcsetattr */ #include <stdio.h> /* perror, printf, puts, fprintf, fputs */ #include <unistd.h> /* read, write, close */ #include <fcntl.h> /* open */ #include <sys/signal.h> #include <sys/types.h> #include <string.h> /* bzero, memcpy */ #include <limits.h> /* CHAR_MAX */
#include "serial.h"
/* * Decription for TIMEOUT_SEC(buflen,baud); * baud bits per second, buflen bytes to send. * buflen*20 (20 means sending an octect-bit data by use of the maxim bits 20) * eg. 9600bps baudrate, buflen=1024B, then TIMEOUT_SEC = 1024*20/9600+1 = 3 * don't change the two lines below unless you do know what you are doing. */ #define TIMEOUT_SEC(buflen,baud) (buflen*20/baud+2) #define TIMEOUT_USEC 0
#define CH_TO_WAIT 5 #define CH_BITS 11
#define BUFFER_LEN 1024 /* sendfile() */
static INT32 fd; //File descriptor for the port
static struct termios termios_old, termios_new; static fd_set fs_read, fs_write; static struct timeval tv_timeout;
static void set_baudrate (INT32); static INT32 get_baudrate (); static void set_data_bit (INT32 databit); static INT32 baudrate2Bxx (INT32 baudrate); static INT32 Bxx2baudrate (INT32 _baudrate); static INT32 set_port_attr ( INT32 baudrate, //
INT32 databit, const char *stopbit, char parity); static void set_stopbit (const char *stopbit); static void set_parity (char parity);
/* Open serial port ComPort at baudrate baud rate. */ INT32 OpenComPort (INT32 ComPort, INT32 baudrate, INT32 databit, const char *stopbit, char parity) { char *pComPort; INT32 retval;
switch (ComPort) { case 0: pComPort = "/dev/ttyS0"; break; case 1: pComPort = "/dev/ttyS1"; break; case 2: pComPort = "/dev/ttyS2"; break; case 3: pComPort = "/dev/ttyS3"; break; case 4: pComPort = "/dev/ttyTX0"; break; case 5: pComPort = "/dev/ttyTX1"; break; default: pComPort = "/dev/ttyS0"; break; }
fd = open (pComPort, O_RDWR | O_NOCTTY); // | O_NONBLOCK);
if (-1 == fd) { fprintf (stderr, "cannot open port %s\n", pComPort); return (-1); }
printf("comport fd = %d\n", fd);
tcgetattr (fd, &termios_old); /* save old termios value */ /* 0 on success, -1 on failure */ retval = set_port_attr (baudrate, databit, stopbit, parity); if (-1 == retval) { fprintf (stderr, "\nport %s cannot set baudrate at %d\n", pComPort, baudrate); } return (retval); }
/* close serial port by use of file descriptor fd */ void CloseComPort () { /* flush output data before close and restore old attribute */ tcsetattr (fd, TCSADRAIN, &termios_old); close (fd); }
int getPortFd(){ return fd; }
INT32 ReadComPort (void *data, INT32 datalength) { INT32 retval = 0; FD_ZERO (&fs_read); FD_SET (fd, &fs_read); tv_timeout.tv_sec = TIMEOUT_SEC (datalength, get_baudrate ()); tv_timeout.tv_usec = TIMEOUT_USEC; retval = select (fd + 1, &fs_read, NULL, NULL, &tv_timeout); if (retval > 0) { retval = read (fd, data, datalength); return (retval); } else { if (0 == retval ) { return (0); }else{ return (-1); } }
}
INT32 ReadComPortA (void *data, INT32 datalength) { INT32 retval = 0; int bytes_read; int readlen;
/** * caculate the time of 5 characters and get the maxim * with 3ms and 5 ch's time */ tv_timeout.tv_sec = 0; tv_timeout.tv_usec = ( (CH_TO_WAIT * CH_BITS) * (1000000/get_baudrate())); //printf("port read timeout:%dus\n",tv_timeout.tv_usec);
bytes_read = 0; while(bytes_read<datalength){ tv_timeout.tv_sec = 0; tv_timeout.tv_usec = ( (CH_TO_WAIT * CH_BITS) * (1000000/get_baudrate())); FD_ZERO (&fs_read); FD_SET (fd, &fs_read); retval = select (fd + 1, &fs_read, NULL, NULL, &tv_timeout); if ( retval >0 ) { readlen = read (fd, (data+bytes_read), datalength); bytes_read += readlen; } else return (bytes_read==0?-1:bytes_read); }
return -1;
} /* * Write datalength bytes in buffer given by UINT8 *data, * return value: bytes written * Nonblock mode */ INT32 WriteComPort (UINT8 * data, INT32 datalength) { INT32 retval, len = 0, total_len = 0;
FD_ZERO (&fs_write); FD_SET (fd, &fs_write); tv_timeout.tv_sec = TIMEOUT_SEC (datalength, get_baudrate ()); tv_timeout.tv_usec = TIMEOUT_USEC;
for (total_len = 0, len = 0; total_len < datalength;) { retval = select (fd + 1, NULL, &fs_write, NULL, &tv_timeout); if (retval) { len = write (fd, &data[total_len], datalength - total_len); if (len > 0) { total_len += len; } } else { tcflush (fd, TCOFLUSH); /* flush all output data */ break; } }
return (total_len); }
/* get serial port baudrate */ static INT32 get_baudrate () { return (Bxx2baudrate (cfgetospeed (&termios_new))); }
/* set serial port baudrate by use of file descriptor fd */ static void set_baudrate (INT32 baudrate) { termios_new.c_cflag = baudrate2Bxx (baudrate); /* set baudrate */ }
static void set_data_bit (INT32 databit) { termios_new.c_cflag &= ~CSIZE; switch (databit) { case 8: termios_new.c_cflag |= CS8; break; case 7: termios_new.c_cflag |= CS7; break; case 6: termios_new.c_cflag |= CS6; break; case 5: termios_new.c_cflag |= CS5; break; default: termios_new.c_cflag |= CS8; break; } }
static void set_stopbit (const char *stopbit) { if (0 == strcmp (stopbit, "1")) { termios_new.c_cflag &= ~CSTOPB; /* 1 stop bit */ } else if (0 == strcmp (stopbit, "1.5")) { termios_new.c_cflag &= ~CSTOPB; /* 1.5 stop bits */ } else if (0 == strcmp (stopbit, "2")) { termios_new.c_cflag |= CSTOPB; /* 2 stop bits */ } else { termios_new.c_cflag &= ~CSTOPB; /* 1 stop bit */ } }
static void set_parity (char parity) { switch (parity) { case 'N': /* no parity check */ termios_new.c_cflag &= ~PARENB; break; case 'E': /* even */ termios_new.c_cflag |= PARENB; termios_new.c_cflag &= ~PARODD; break; case 'O': /* odd */ termios_new.c_cflag |= PARENB; termios_new.c_cflag |= ~PARODD; break; default: /* no parity check */ termios_new.c_cflag &= ~PARENB; break; } }
static INT32 set_port_attr ( INT32 baudrate, // 1200 2400 4800 9600 .. 115200
INT32 databit, // 5, 6, 7, 8
const char *stopbit, // "1", "1.5", "2"
char parity) // N(o), O(dd), E(ven)
{ bzero(&termios_new, sizeof (termios_new)); cfmakeraw (&termios_new);
set_baudrate (baudrate); termios_new.c_cflag |= CLOCAL | CREAD; /* | CRTSCTS */ set_data_bit (databit); set_parity (parity); set_stopbit (stopbit); termios_new.c_oflag = 0; termios_new.c_lflag |= 0; termios_new.c_oflag &= ~OPOST; termios_new.c_cc[VTIME] = 1; /* unit: 1/10 second. */ termios_new.c_cc[VMIN] = 255; /* minimal characters for reading */ tcflush (fd, TCIFLUSH);
return (tcsetattr (fd, TCSANOW, &termios_new)); }
/** * baudrate xxx to Bxxx * * @@param baudrate xxx * * @@return */ static INT32 baudrate2Bxx (INT32 baudrate) { switch (baudrate) { case 0: return (B0); case 50: return (B50); case 75: return (B75); case 110: return (B110); case 134: return (B134); case 150: return (B150); case 200: return (B200); case 300: return (B300); case 600: return (B600); case 1200: return (B1200); case 2400: return (B2400); case 9600: return (B9600); case 19200: return (B19200); case 38400: return (B38400); case 57600: return (B57600); case 115200: return (B115200); default: return (B9600); } }
/** * get boundrate from Bxxx * * @@param baudrate Bxxx refers to bound rate * * @@return */ static INT32 Bxx2baudrate (INT32 _baudrate) { /* reverse baudrate */ switch (_baudrate) { case B0: return (0); case B50: return (50); case B75: return (75); case B110: return (110); case B134: return (134); case B150: return (150); case B200: return (200); case B300: return (300); case B600: return (600); case B1200: return (1200); case B2400: return (2400); case B9600: return (9600); case B19200: return (19200); case B38400: return (38400); case B57600: return (57600); case B115200: return (115200); default: return (9600); } }
|