在遇到中断时尝试读取linux中的串口的行为?

时间:2012-07-10 01:32:15

标签: c linux serial-port

修改

我实际上认为我可能已经弄明白了:有没有人知道如果某个程序在串口上阻塞并且使用控件+ c终止会发生什么,会发生什么?

看起来答案可能是端口无法配置,因为它已被锁定或其他东西。我很感激这个问题的答案,但如果答案是“行为未定义,我不会感到惊讶!”

以下是我提出的原始问题。


我有一些代码,我已经使用了多年来从linux中的串口读取和写入,突然间它正在起作用。我希望我犯了一些相对明显的错误,但是我已经对代码敲了几天而且没有取得任何进展。

代码来自较旧版本的cutecom,然后从minicom获取代码,但在我试图弄清楚为什么cutecom工作时我的横冲直撞导致我只是直接复制例程最新版的cutecom。

基本的失败模式如下:要么我得到一堆空字符(即我发送一个字节并取回三个字节的空),或者我得到其他乱码(即0xff字符,只有两个或三个)更长的字符串)。这发生在多个USB到串行适配器上,并且似乎表明某种波特率不匹配......

提前抱歉关于巨大的代码blob,但我试图留下我认为可能导致问题的部分(文件打开,termios设置和读取)......

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 
#include <stdint.h> 
#include <ctype.h> 
// UNIX Includes 
#include <unistd.h> 
#include <termios.h> 
#include <fcntl.h> 
#include <sys/types.h> 
#include <sys/stat.h>
#include <sys/ioctl.h>

int main(int argc, char *argv[])
{
    int i, baud= 9600, fd_port= -1;
    unsigned char in_c, valid= 0;
    char *devname= NULL;
    unsigned char inbuf[BUFSZ]; 

    /* some code which reads in and parses parameters omitted */

    fd_port= open(devname, O_RDWR); //| O_NOCTTY, O_ASYNC); // weird options don't help!

    if(fd_port < 0) {
        fprintf(stderr, "Failed to open port\"%s\"\n", devname);
        exit(-1);
    }

    setPortOptions(fd_port, baud, 8, 0, 1, false, false);

    while(1) {
        readb= 0;
        while(recvstr[readb] != '\0') {
            ret= read(fd_port, &in_c, 1);

            if(ret < 0) {
                fprintf(stderr, "Error reading from port!\n");
                exit(-1);
            } else if(ret > 0 && recvstr[readb] != in_c) {
                fprintf(stderr, "Discarding \"%02x\" from input\n", in_c);
                break;
            } else if(ret == 0) {
                fprintf(stderr, "Reached EOF\n");
                exit(-1);
            } else {
                readb+= ret;
            }
        }

        /* Some code which does some stuff after getting an init string */
    }

    // cleanup
}
/* setPortOptions - takes in a set of options and applies it to fd
    in  - a file descriptor, baud rate, data bits, parity (0, 1, 2),
            stop (1 or 2), soft handshake (bool), hardware handshake (bool)
    out - nothing

    This function was taken and modified from cutecom 1.12, qcppdialogimpl.cpp
    This function features some code from minicom 2.0.0, src/sysdep1.c
 */
void setPortOptions(int fd, int baudrate, int databits, int parity, int stop,
        bool softwareHandshake, bool hardwareHandshake)
{
    struct termios newtio;
    //   memset(&newtio, 0, sizeof(newtio));
    if(tcgetattr(fd, &newtio) != 0) {
        fprintf(stderr, "tcgetattr() 3 failed\n");
    }

    speed_t _baud= -1;
    switch (baudrate)
    {
#ifdef B0
        case      0: _baud= B0;      break;
#endif
#ifdef B50
        case     50: _baud= B50;     break;
#endif
        /* This continues for quite a while */
#ifdef B921600
        case 921600: _baud= B921600; break;
#endif
        default:
            fprintf(stderr, "Invalid baud, not changing!\n");
            break;
    }

    if(_baud != -1) {
        cfsetospeed(&newtio, _baud);
        cfsetispeed(&newtio, _baud);
    }

    switch(databits) {
        case 5:
            newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS5;
            break;
        /* same code for 6 and 7 bits */
        case 8:
        default:
            newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8;
            break;
    }

    // ignore modem control lines and enable the receiver
    newtio.c_cflag |=  CLOCAL | CREAD;

    // parity (0 == no parity, 1 == odd, 2 == even)
    newtio.c_cflag &= ~(PARENB | PARODD);
    if(parity == 2) {
        newtio.c_cflag |= PARENB;
    } else if(parity == 1) {
        newtio.c_cflag |= (PARENB | PARODD);
    } else if(parity != 0) {
        fprintf(stderr, "Invalid parity!\n");
    }

    // disable hardware handshake
    newtio.c_cflag &= ~CRTSCTS;

    // Set 1 stopbit
    newtio.c_cflag &= ~CSTOPB;

    if(stop == 2) {
        newtio.c_cflag |= CSTOPB;
    } else if(stop != 1) {
        fprintf(stderr, "Invalid stop bit selection! Must be 1 or 2\n"
                "Defaulting to 1\n");
    }

    // Ignore "BREAK" condition on input
    newtio.c_iflag= IGNBRK;

    // software handshake (non-zero == enabled, zero == disabled)
    if(softwareHandshake) {
        newtio.c_iflag |= IXON | IXOFF;
    } else {
        newtio.c_iflag &= ~(IXON | IXOFF | IXANY);
    }

    // clear out the local and output modes
    newtio.c_lflag= 0;
    newtio.c_oflag= 0;

    // Set timeout to 0
    newtio.c_cc[VTIME]= 0;

    // 1 char minimum for a non-canonical read
    newtio.c_cc[VMIN]= 1;

    // tcflush(fd, TCIFLUSH);
    if(tcsetattr(fd, TCSANOW, &newtio) != 0)
        fprintf(stderr, "tcsetattr() 1 failed\n");

    int mcs= 0;
    ioctl(fd, TIOCMGET, &mcs);
    mcs |= TIOCM_RTS;
    ioctl(fd, TIOCMSET, &mcs);

    if(tcgetattr(fd, &newtio) != 0)
        fprintf(stderr, "tcgetattr() 4 failed\n");

    // hardware handshake
    if(hardwareHandshake) {
        newtio.c_cflag |= CRTSCTS;
    } else {
        newtio.c_cflag &= ~CRTSCTS;
    }

    if(tcsetattr(fd, TCSANOW, &newtio) != 0)
        fprintf(stderr, "tcsetattr() 2 failed\n");
}

0 个答案:

没有答案