"); //-->
对应的头文件serial.h:
#ifndef _SERIAL_H #define _SERIAL_H 1 typedef int INT32; typedef short INT16; typedef char INT8; typedef unsigned int UNIT32; typedef unsigned short UINT16; typedef unsigned char UINT8; /* serial.c */ INT32 OpenComPort (INT32 ComPort, INT32 baudrate, INT32 databit, const char *stopbit, char parity); void CloseComPort (void); INT32 ReadComPort (void *data, INT32 datalength); INT32 WriteComPort (UINT8 * data, INT32 datalength); /** * export serial fd to other program to perform * directly read, write to serial. * * @return serial's file description */ int getPortFd(); #endif /* serial.c *
serial.c 串口基本操作的封装:
#include <termios.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/signal.h> #include <sys/types.h> #include <string.h> #include <limits.h> #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); } }
serial_test.c 测试程序:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include "serial.h" #define ttyS1 1 #define ttyS2 2 #define ttyS3 3 #define ttyTX0 4 #define ttyTX1 5 static int n_com_port = ttyTX0; int main (int argc, char *argv[]) { int ret = -1; int len_tty = -1; int fd_rs485; unsigned char buf_tty[256]; if (argc > 1) { n_com_port = strtol( argv[1], NULL, 10 ); } ret = OpenComPort(n_com_port, 115200, 8, "1", 'N'); if (ret < 0) { fprintf(stderr, "Error: Opening Com Port %d\n", n_com_port); return ret; } else { printf("Open Com Port %d Success, Now going to read port\n", n_com_port); } while (1) { bzero(buf_tty, sizeof(buf_tty)); len_tty = ReadComPort(buf_tty, 255); if (len_tty < 0) { printf("Error: Read Com Port\n"); break; } if (len_tty == 0) { write(STDOUT_FILENO, ".", sizeof(".")); continue; } printf("Recv: %d bytes, [%s]\n", len_tty, buf_tty); len_tty = WriteComPort(buf_tty, len_tty); WriteComPort(" recved:", sizeof(" recved:")); if (len_tty < 0) { printf("Error: WriteComPort Error\n"); } // delay 500 ms to let data transfer complete // here will cause bugs usleep(500 * 1000); } CloseComPort(); printf("Program Terminated\n"); return(0); }
测试结果和现象:
root@omap3evm:/app/uart# ./test_uart-ttyS0
comport fd = 3
Open Com Port 0 Success, Now going to read port
Recv: 16 bytes, [1234567890abcdef]
Recv: 16 bytes, [1234567890abcdef]
Recv: 16 bytes, [1234567890abcdef]
Recv: 16 bytes, [1234567890abcdef]
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。