⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial.c

📁 linux下的一个串口调试程序的源代码
💻 C
字号:
/* * Program: 	serial.c * Author:  	Paul Dean * Date:    	2002-02-19 * Description: To provide underlying serial port function, *              for high level applications. * */#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 "types.h"              //* INT32, INT16, INT8, UINT32, UINT16, UINT8 */#include "serial.h"#include "prompt.h"static INT32    fd;             //* File descriptor for the port */static INT32    bOpen = 0;      //* flag of whether serial opened */static struct termios termios_old, termios_new;static struct timeval tv_timeout;static void     SignalHandlerIO ();static void     SetBaudrate (INT32);static INT32    GetBaudrate ();static void     SetDataBit (INT32 databit);static INT32    BAUDRATE (INT32 baudrate);static INT32    _BAUDRATE (INT32 baudrate);static INT32    SetPortAttr (const P_PORT_INFO pPortInfo);static void     SetStopBit (const char *stopbit);static void     SetParityCheck (char parity);static void     SetFlowControl (INT32 fctrl);/* * Function:	INT32 OpenComPort (const P_PORT_INFO pPortInfo) * Arguments:	const P_PORT_INFO pPortInfo; * Description:	Open serial port ComPort at baudrate baud rate. */INT32 OpenComPort (const P_PORT_INFO pPortInfo){    char           *pComPort;    INT32           retval;    switch (pPortInfo->port) {    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/ttyS4";        break;    case 5:        pComPort = "/dev/ttyS5";        break;    case 6:        pComPort = "/dev/ttyS6";        break;    case 7:        pComPort = "/dev/ttyS7";        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);        bOpen = 0;        return (E_OPEN);    }    tcgetattr (fd, &termios_old);       //* save old termios value */    //* 0 on success, -1 on failure */    retval = SetPortAttr (pPortInfo);    if (-1 == retval) {        fprintf (stderr, "\nport %s cannot set baudrate at %d\n", pComPort,                 pPortInfo->baudrate);        return (E_SET_BAUDRATE);    }    bOpen = 1;    return (0);}/*  * Function:	void CloseComPort() * Arguments:	void; * Description:	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);    bOpen = 0;}/*  * Function:	INT32 ReadComPort (void *data, INT32 datalength) * Arguments:	void *data, INT32 datalength;	 * Description:	Read data ready from serial port	 * Return value: * 				E_NOTOPEN: port isn't open. * 				E_NODATA:  no data has arrived before time is out. */INT32 ReadComPort (void *data, INT32 datalength){    INT32           retval = 0;    fd_set          fs_read;    if (!bOpen) {        return (E_NOTOPEN);    }    FD_ZERO (&fs_read);    FD_SET (fd, &fs_read);    tv_timeout.tv_sec = TIMEOUT_SEC (datalength, GetBaudrate ());    tv_timeout.tv_usec = TIMEOUT_USEC;    retval = select (fd + 1, &fs_read, NULL, NULL, &tv_timeout);    if (retval) {        return (read (fd, data, datalength));    }    else {        return (E_NODATA);    }}/*  * 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_set          fs_write;    if (!bOpen) {        return (E_NOTOPEN);    }    FD_ZERO (&fs_write);    FD_SET (fd, &fs_write);    tv_timeout.tv_sec = TIMEOUT_SEC (datalength, GetBaudrate ());    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);}/* * Function:	static INT32 GetBaudrate() * Arguments:	void; * Description:	get serial port baudrate */static INT32 GetBaudrate (){    return (_BAUDRATE (cfgetospeed (&termios_new)));}/*  * Function:	static void SetBaudrate (INT32 baudrate) * Arguments:	INT32 baudrate; * Description:	set serial port baudrate by use of file descriptor fd */static void SetBaudrate (INT32 baudrate){    termios_new.c_cflag = BAUDRATE (baudrate);  //* set baudrate */}/* * Function:	static static void SetDataBit (INT32 databit) * Arguments:	INT32 databit;	 * Description:	Set	databit;  */static void SetDataBit (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;    }}/* * Function:	static void SetStopBit (const char *stopbit) * Arguments:	const char *stopbit; * Description:	Set Stop Bit  */static void SetStopBit (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 */    }}/* * Function:	static void SetParityCheck (char parity) * Arguments:	char parity;	 * Description:	Set Parity Check  */static void SetParityCheck (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;    }}/* * Function:	static void SetFlowControl(INT32 fctrl) * Arguments:	INT32 fctrl; * 				0: No Flow Control; *				1: Hardware Control; *				2: Software Control; */static void SetFlowControl (INT32 fctrl){    switch (fctrl) {    case 0:        termios_new.c_cflag &= ~CRTSCTS;        break;    case 1:    default:        termios_new.c_cflag |= CRTSCTS;        break;    case 2:        break;    }}/* * Function:	static INT32 SetPortAttr (const P_PORT_INFO) * Arguments:	const P_PORT_INFO pPortInfo; * Description:	Set Attribute of serial port */static INT32 SetPortAttr (const P_PORT_INFO pPortInfo){    bzero (&termios_new, sizeof (termios_new));    cfmakeraw (&termios_new);    SetBaudrate (pPortInfo->baudrate);    termios_new.c_cflag |= CLOCAL | CREAD;    SetFlowControl (pPortInfo->fctrl);    SetDataBit (pPortInfo->databit);    SetParityCheck (pPortInfo->parity);    SetStopBit (pPortInfo->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] = 1; //* minimal characters for reading */    tcflush (fd, TCIFLUSH);    return (tcsetattr (fd, TCSANOW, &termios_new));}/* * Function:	static INT32 BAUDRATE (INT32 baudrate) * Arguments:	INT32 baudrate; * Description:	convert baudrate from INT32 to MACRO B** */static INT32 BAUDRATE (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);    }}/* * Function:	static INT32 _BAUDRATE (INT32 baudrate) * Arguments:	INT32 baudrate; * Description:	convert baudrate from MACRO B** to INT32 */static INT32 _BAUDRATE (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);    }}/* * Function:	INT32 SendFile (const char *pathname, INT32 echo)	 * Arguments:	const char *pathname, INT32 echo; */INT32 SendFile (const char *pathname, INT32 echo){    INT32           fd, buflen, len;    //*  fd for file */    char            buf[BUFFER_LEN + 1];    fd = open (pathname, O_RDONLY);    if (fd < 0) {        perror (pathname);        return (E_NOTOPEN);    }    while (1) {        bzero (buf, sizeof (buf));        buflen = read (fd, buf, BUFFER_LEN);        if (0 == buflen)            break;        buf[buflen] = 0;        echo ? printf ("%s", buf) : 0;        if ((len = WriteComPort (buf, buflen)) != buflen) {            fprintf (stderr, "write %d bytes for %d bytes\n", len, buflen);            fprintf (stderr, "To CloseComPort()\n");            CloseComPort ();            close (fd);            fprintf (stderr, "CloseComPort completed\n");            return (-1);        }    }                           //* end of while (1) */    fflush (stdout);    fflush (stderr);    close (fd);    return (0);}/* * Function:	static void SignalHandlerIO () * Arguments:	void; * Read the data ready. */static void SignalHandlerIO (){    char            recvbuf[CHAR_MAX + 1];    INT32           retval;    fd_set          fs_read;    FD_ZERO (&fs_read);    FD_SET (fd, &fs_read);    tv_timeout.tv_sec = 0;    tv_timeout.tv_usec = 200;   //* 200 miliseconds */     printf ("\n");    while (1) {        retval = select (fd + 1, &fs_read, NULL, NULL, &tv_timeout);        if (retval) {            retval = read (fd, recvbuf, sizeof (recvbuf) - 1);        }        else {            prompt ();            break;        }        if (DEBUG) {            printf ("received %d-byte data\n", retval);            fflush (stdout);        }        if (retval > 0) {            recvbuf[retval] = '\0';            printf ("%s", recvbuf);            fflush (stdout);        }        else {            prompt ();            break;        }    }}/* * Function:	INT32 SetPortSig() * Arguments:	void;	 * Set Signal for read; */INT32 SetPortSig (){    //* install the signal handler before making the device asynchronous */    static struct sigaction sigaction_io;       //* definition of signal action */    sigaction_io.sa_handler = SignalHandlerIO;    sigemptyset (&(sigaction_io.sa_mask));    sigaction_io.sa_flags = 0;    sigaction_io.sa_restorer = NULL;    sigaction (SIGIO, &sigaction_io, NULL);    //* allow the process to receive SIGIO */    if (-1 == fcntl (fd, F_SETFL, O_ASYNC))        return (-1);    if (-1 == fcntl (fd, F_SETOWN, getpid ()))        return (-1);    /*     * Make the file descriptor asynchronous (the manual page says only     * O_APPEND and O_NONBLOCK, will work with F_SETFL...)     */    return (0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -