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

📄 tty.c

📁 Linux下对串口进行编程
💻 C
字号:
/* * File         : tty.c * Author       : yfy001 * Date         : 2002-04-20 * Description  : To provide underlying serial port function, *                for high level applications. * Copyright (C) 2001, 2002  yfy001 */#include <stdio.h>              // perror, printf, puts, fprintf, fputs#include <unistd.h>             // read, write, close#include <termios.h>            // tcgetattr, tcsetattr#include <fcntl.h>              // open#include <sys/signal.h>         // sigaction#include <sys/types.h>          // pid_t#include <string.h>             // bzero, memcpy#include <limits.h>             // CHAR_MAX#include <sys/ioctl.h>          // ioctl#include "types.h"              // int32, int16, int8, uint32, uint16, uint8#include "tty.h"                // tty_open, tty_close, tty_read, tty_write#include "prompt.h"             // promptstatic INT8 firstrecv = 1;      // whether data receivedstatic int fd = -1;             // File descriptor for the port static struct termios termios_old, termios_new;static struct timeval tv_timeout;static void tty_sig_handler();static void tty_set_baudrate(int);static int tty_get_baudrate();static void tty_set_databit(INT8 databit);static int tty_set_attr(const portinfo_t * p_portinfo);static void tty_set_stopbit(INT8 stopbit);static void tty_set_parity_check(INT8 parity);static void tty_set_flow_control(INT8 fctrl);static INT8 tty_is_open();/* * Arguments    : const portinfo_t* p_portinfo; * Return value : 0 on success, ERROR on failure. * Description  : Open serial port ComPort at baudrate baud rate. */int tty_open(const portinfo_t * p_portinfo){    char *p_tty;    int retval;    if (tty_is_open()) {        return (0);    }    if (0 == p_portinfo->tty) {        p_tty = "/dev/ttyS0";    } else if (1 == p_portinfo->tty) {        p_tty = "/dev/ttyS1";    } else if (2 == p_portinfo->tty) {        p_tty = "/dev/ttyS2";    } else if (3 == p_portinfo->tty) {        p_tty = "/dev/ttyS3";    } else if (4 == p_portinfo->tty) {        p_tty = "/dev/ttyS4";    } else if (5 == p_portinfo->tty) {        p_tty = "/dev/ttyS5";    } else if (6 == p_portinfo->tty) {        p_tty = "/dev/ttyS6";    } else if (7 == p_portinfo->tty) {        p_tty = "/dev/ttyS7";    } else {        p_tty = "/dev/ttyS0";    }    fd = open(p_tty, O_RDWR | O_NOCTTY | O_NONBLOCK);    if (-1 == fd) {        fprintf(stderr, "cannot open port %s\n", p_tty);        return (E_OPEN);    }    tcgetattr(fd, &termios_old);        // save old termios value     // 0 on success, -1 on failure     retval = tty_set_attr(p_portinfo);    if (-1 == retval) {        fprintf(stderr, "\nport %s cannot set baudrate at %d\n", p_tty,                p_portinfo->baudrate);        return (E_SET_BAUDRATE);    }    return (0);}/*  * Arguments    : none * Return value : none * Description  : close serial port by use of file descriptor fd */void tty_close(){    if (!tty_is_open()) {        return;    }    tcsetattr(fd, TCSAFLUSH, &termios_old);    close(fd);    fd = -1;}/*  * Arguments    : void *data, int 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. */int tty_read(void *data, int datalength){    int retval = 0;    fd_set fs_read;    if (!tty_is_open()) {        return (E_NOTOPEN);    }    FD_ZERO(&fs_read);    FD_SET(fd, &fs_read);    tv_timeout.tv_sec = TIMEOUT_SEC(datalength, tty_get_baudrate());    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);    }}/*  * Arguments    : uint8 *data, int datalength; * Return value : bytes written * Description  : Write datalength bytes in buffer given by uint8 *data, */int tty_write(uint8 * data, int datalength){    int retval, len = 0, total_len = 0;    fd_set fs_write;    if (!tty_is_open()) {        return (E_NOTOPEN);    }    FD_ZERO(&fs_write);    FD_SET(fd, &fs_write);    tv_timeout.tv_sec = TIMEOUT_SEC(datalength, tty_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);}/* * Arguments    : INT8 databit;	 * Description  : Set databit;  */static void tty_set_databit(INT8 databit){    termios_new.c_cflag &= ~CSIZE;    if (7 == databit) {        termios_new.c_cflag |= CS7;    } else if (6 == databit) {        termios_new.c_cflag |= CS6;    } else if (5 == databit) {        termios_new.c_cflag |= CS5;    } else {        termios_new.c_cflag |= CS8;    }}/* * Arguments    : int stopbit; * Description  : Set Stop Bit  */static void tty_set_stopbit(INT8 stopbit){    if (2 == stopbit) {        termios_new.c_cflag |= CSTOPB;  // 2 stop bits     } else {        termios_new.c_cflag &= ~CSTOPB; // 1 stop bit     }}/* * Arguments    : INT8 parity;	 * Description  : Set Parity Check  */static void tty_set_parity_check(INT8 parity){    parity = parity % 3;    if (2 == parity) {          // even         termios_new.c_cflag |= PARENB;        termios_new.c_cflag &= ~PARODD;    } else if (1 == parity) {   // odd         termios_new.c_cflag |= PARENB;        termios_new.c_cflag |= ~PARODD;    } else {                    // no parity check         termios_new.c_cflag &= ~PARENB;    }}/* * Arguments    : int fctrl; *     0: No Flow Control; *     1: Hardware Control; *     2: Software Control; * Return value : none * Description  : set flow control of fd wth fctrl */static void tty_set_flow_control(INT8 fctrl){    if (0 == fctrl) {           // no flow control         termios_new.c_cflag &= ~CRTSCTS;    } else if (1 == fctrl) {    // hardware flow control         termios_new.c_cflag |= CRTSCTS;    } else if (2 == fctrl) {    // software flow control         termios_new.c_iflag |= IXON | IXOFF | IXANY;    }}/* * Arguments    : const portinfo_t* p_portinfo; * Description  : Set Attribute of serial port */static int tty_set_attr(const portinfo_t * p_portinfo){    bzero(&termios_new, sizeof(termios_new));    cfmakeraw(&termios_new);    tty_set_baudrate(p_portinfo->baudrate);    termios_new.c_cflag |= CLOCAL | CREAD;    tty_set_flow_control(p_portinfo->fctrl);    tty_set_databit(p_portinfo->databit);    tty_set_parity_check(p_portinfo->parity);    tty_set_stopbit(p_portinfo->stopbit);    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));}/*  * Arguments    : int baudrate; * Description  : set serial port baudrate by use of file descriptor fd */static void tty_set_baudrate(int baudrate){    if (0 == baudrate) {    } else if (50 == baudrate) {        termios_new.c_cflag = B50;    } else if (75 == baudrate) {        termios_new.c_cflag = B75;    } else if (110 == baudrate) {        termios_new.c_cflag = B110;    } else if (134 == baudrate) {        termios_new.c_cflag = B134;    } else if (150 == baudrate) {        termios_new.c_cflag = B150;    } else if (200 == baudrate) {        termios_new.c_cflag = B200;    } else if (300 == baudrate) {        termios_new.c_cflag = B300;    } else if (600 == baudrate) {        termios_new.c_cflag = B600;    } else if (1200 == baudrate) {        termios_new.c_cflag = B1200;    } else if (2400 == baudrate) {        termios_new.c_cflag = B2400;    } else if (9600 == baudrate) {        termios_new.c_cflag = B9600;    } else if (19200 == baudrate) {        termios_new.c_cflag = B19200;    } else if (38400 == baudrate) {        termios_new.c_cflag = B38400;    } else if (57600 == baudrate) {        termios_new.c_cflag = B57600;    } else if (115200 == baudrate) {        termios_new.c_cflag = B115200;    } else {        termios_new.c_cflag = B38400;    }}/* * Arguments    : void; * Description  : get serial port baudrate */static int tty_get_baudrate(){    switch (cfgetospeed(&termios_new)) {    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);    }}/* * Arguments    : const char *pathname, int echo; * Return value : none * Description  : send a file */int tty_send_file(const char *pathname, INT8 echo){    int 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 = tty_write(buf, buflen)) != buflen) {            fprintf(stderr, "write %d bytes for %d bytes\n", len, buflen);            fprintf(stderr, "to tty_close()\n");            tty_close();            close(fd);            fprintf(stderr, "tty_close() completed\n");            return (-1);        }    }    fflush(stdout);    fflush(stderr);    close(fd);    return (0);}/* * Arguments    : none * Return value : none * Description  : Read the data ready. */static void tty_sig_handler(){    char recvbuf[CHAR_MAX + 1];    int retval;    fd_set fs_read;    int byte_recv = 0;    FD_ZERO(&fs_read);    FD_SET(fd, &fs_read);    tv_timeout.tv_sec = 0;    tv_timeout.tv_usec = 500;    while (1) {        retval = select(fd + 1, &fs_read, NULL, NULL, &tv_timeout);        if (retval) {            byte_recv = read(fd, recvbuf, sizeof(recvbuf) - 1);            if (firstrecv) {    // first recieve                printf("\n");                firstrecv = 0;            }        } else {            if (byte_recv && p_args->p_portinfo->prompt) {                prompt();            }            break;        }        if (byte_recv > 0) {            recvbuf[byte_recv] = '\0';            fprintf(stderr, "%s", recvbuf);            if (DEBUG)                fprintf(stderr, "%d-byte\n", byte_recv);            fflush(stderr);        }        if (byte_recv > 80) {            tv_timeout.tv_sec = 0;            tv_timeout.tv_usec = 500;        } else {            tv_timeout.tv_sec = 0;            tv_timeout.tv_usec = 200;        }    }}/* * Arguments    : none	 * Return value : none * Description  : Set Signal for read; */int tty_set_sig_on(){    // install the signal handler before making the device asynchronous     static struct sigaction sigaction_io;    sigaction_io.sa_handler = tty_sig_handler;    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);    } else if (-1 == fcntl(fd, F_SETOWN, getpid())) {        return (-1);    }    return (0);}/* * Arguments    : none  * Return value : INT8, 0: closed, 1: open * Description  : return whether /dev/ttyS[tty] is open */static INT8 tty_is_open(){    return -1 == fd ? 0 : 1;    // fd == -1, return 0       }

⌨️ 快捷键说明

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