在Linux

时间:2018-05-15 23:46:15

标签: c++ linux arm uart

我正在尝试写入串口(发送握手),然后我尝试读取串口。在读取端口时,我注意到我正在进行垃圾读取(即使没有连接到RX线路)或者我正在发送到TX线路的部分写入字符串。为什么我会收到该字符串的一部分?我不应该看到这个!

这是我的代码:

   class UART{

    public:
        UART();
        ~UART();
        int open_port();
        int configure_port(); // All port configurations such as parity, baud rate, hardware flow, etc
        int uart_write(std::string);     // Send characters to the serial port
        int uart_read(std::string*, int);            // Read from serial port
        // Close
        void close_port();

    private:
        int fd;

uart.cpp:

UART::UART(){
    open_port();
    configure_port();
}

UART::~UART(){
    close_port();
}

int UART::open_port()
{
    // Open ttys4
    fd = open("/dev/ttyS4", O_RDWR | O_NOCTTY | O_NDELAY);

    if(fd == -1) // if open is unsucessful
    {
        //perror("open_port: Unable to open /dev/ttyS0 - ");
        printf("open_port: Unable to open /dev/ttyS4. \n");
    }
    else
    {
        fcntl(fd, F_SETFL, 0);
        printf("port is open.\n");
    }

    return(fd);
} //open_port

// configure the port
int UART::configure_port()      
{
    struct termios port_settings;      // structure to store the port settings in

    cfsetispeed(&port_settings, B9600);    // set baud rates
    cfsetospeed(&port_settings, B9600);

    port_settings.c_cflag &= ~PARENB;    // set no parity, stop bits, data bits
    port_settings.c_cflag &= ~CSTOPB;
    port_settings.c_cflag &= ~CSIZE;
    port_settings.c_cflag |= CS8;
    port_settings.c_cflag |=  CREAD | CLOCAL;     // turn on READ & ignore ctrl lines

    port_settings.c_cc[VTIME]     =   10;                  // n seconds read timeout
    port_settings.c_iflag     &=  ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
    port_settings.c_lflag     &=  ~(ICANON | ECHO | ECHOE | ISIG); // make raw
    port_settings.c_oflag     &=  ~OPOST;              // make raw

    tcsetattr(fd, TCSANOW, &port_settings);    // apply the settings to the port
    return(fd);
} 

 // Write to serial port
int UART::uart_write(string data)  
{
    int buffer_size = data.length();
    char * data_write = new char[data.length()+1];
    strcpy (data_write, data.c_str());

    int n = write(fd, data_write, buffer_size);  //Send data

    usleep(1000);
    tcdrain(fd);

    printf("Wrote the bytes. \n");

    /* Error Handling */
    int status = 0;
    if (n < 0)
    {
         cout << "Error Writing: " << strerror(errno) << endl;
         status = 0;
    }else{
        status = 1;
    }

    delete[] data_write;

    return status;
}

int UART::uart_read(string *data,int buffer_size)
{
    // Buffer
    char * buf = new char[buffer_size+1];

    usleep(1000);
    tcflush(fd, TCIOFLUSH);

    // Read
    /*I NEED THIS PART TO BE BLOCKING*/
    int n = read( fd, buf , buffer_size );

    /* Error Handling */
    if (n < 0)
    {
         cout << "Error reading: " << strerror(errno) << endl;
    }

    // String received
    string data_received(buf,buffer_size);
    *data = data_received;

    delete[] buf;

    cout << "data_received: " << *data << endl;

    // Did we get blank data?
    if( data_received.length() == 0 )
        return 0;
    else
        return 1;
}

int main()
{ 
    UART uart_connection;

    string handshake = "handshake!";
    uart_connection.uart_write(handshake);

    string data;
    string *data_ptr = &data;
    uart_connection.uart_read(data_ptr );

    cout << data << endl;

}

打印收到的数据时,我通常会收到部分已发送的数据。所以在cout&lt;&lt;数据&lt;&lt;我得到以下内容:

dshake

以及之后的一些奇怪的字符,或者如果我没有写任何东西到串口,那么我只是得到随机字符。

具体来说,我希望 int n = read(fd,buf,buffer_size); 是一个阻塞函数,显然它没有发生......它只是通过并返回一堆奇怪的字符或它读取写入发送的字符串的一部分。

请注意代码有效,当我确实向RX线发送内容时,我可以正常阅读。但是,我发现很难发送大块数据而不会导致错误的读取。

我相信如果我能使read()函数成为阻塞函数,并且避免它读取那些奇怪的字符,这一切都可以解决。

1 个答案:

答案 0 :(得分:2)

始终允许

Read读取的内容少于您的要求。使其成为&#34;阻止&#34;在你读完了足够多的字符之后,你需要把它包装成一个循环并调用它,直到你读了很多你想要的字节为止。

在您的代码中,n是成功读取的字节数。你只能检查它是非负面的。

循环可能如下所示:

size_t read_count = 0;
while (read_count < buffer_size)
{
    ssize_t read_result = read(fd, buf + read_count, buffer_size - read_count);
    if (read_result < 0)
    {
        cout << "Error reading: " << strerror(errno) << endl;
        break;
    }
    read_count += read_result;
}

请注意,一般来说,read是一个低级别的界面,有许多容易错过的细微之处。例如,出错时,值得检查EINTR以及其他几个。

在我的头顶,FILE*功能没有这些问题,您可以使用fdopenfread来始终如一地获得您想要的内容。

虽然看起来您还没有遇到这个问题,但write有同样的问题。它也允许写入比你给出的更少的字节,也可以中断。但是,这种情况很少发生在小写中。