C ++ IOCTL()未检测到来自串行通信的文件描述符中的可用字节

时间:2018-10-23 09:18:10

标签: c++ serial-port arduino-uno ioctl termios

我正在编程一个c ++类,用于系统中两个设备之间的串行通信。一种设备是Linux计算机,另一种是微控制器(Arduino Uno)。该类在Linux计算机上使用。到目前为止,该类仅具有函数'Begin()'和'Available()'。

“ Available()”函数存在问题,该函数应返回可读取的字节数。 当我使用命令'Serial.print ln (“ hello world”)'(来自arduino的内置库的命令)从微控制器发送字节后,在语句中添加了'serial.Available()'语句。 Linux计算机将返回数字12。但是,当我忽略arduino一侧的换行符(“ Serial.print()”而不是“ Serial.println()”)时,serial.Available()将返回0字节可用阅读。

我的假设是我滥用了“ serial.Available()”函数中的“ ioctl()”语句,或者“ serial.Begin()”中的串行端口设置存在问题。没有人会知道为什么如果我不在arduino的一面打印换行符,为什么不认为字节可用,同样使用Arduino的'Serial.write()'命令。

任何建议,我们将不胜感激,

谢谢

编辑: 在Wiki上读到,在我使用过的termios api中,有两种模式。典范和非典范。第一个将逐行处理,第二个将返回单个字符。但是在我的配置中,我确定使用以下语句停用了规范模式:

SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);

serial.h

#ifndef SERIAL_H
#define SERIAL_H

#include <cstdio>
#include <cstdlib>
#include <fcntl.h>                                                      // File control definitions
#include <stdexcept>
#include <string>
#include <sys/ioctl.h>                                                  // Serial Port IO Controls
#include <termios.h>                                                    // POSIX terminal control definitions
#include <unistd.h>                                                     // UNIX standard function definitions

using namespace std;

class Serial
{
    private:
        int fd;                                                         // file descriptor
        int configured;
    public:
        Serial(const char * device);

        ~Serial()
        {
            close(fd);
        };     

        void Begin();
        int Available();                                                // returns the number of bytes that's available for reading
};

#endif

serial.cpp

#include "serial.h"

Serial::Serial(const char * device)
{
    configured = 0;
    fd = open(device,O_RDWR | O_NOCTTY);                                // open serial port (read/write, no terminal control, blocking mode)
    if (fd < 0)
    {
        perror("failed to open serial port");
        exit(EXIT_FAILURE);
    }
}

void Serial::Begin()
{
    struct termios SerialPortSettings;                                  // structure for serial port settings

    tcgetattr(fd, &SerialPortSettings);                                 // paste file descriptor's current settings to structure

    cfsetispeed(&SerialPortSettings,B9600);                             // set input baud rate
    cfsetospeed(&SerialPortSettings,B9600);                             // set output baud rate

    SerialPortSettings.c_cflag &= ~PARENB;                              // disable parity

    SerialPortSettings.c_cflag &= ~CSTOPB;                              // set number of stop bits to 1

    SerialPortSettings.c_cflag &= ~CSIZE;                               // clear the bitmask
    SerialPortSettings.c_cflag |=  CS8;                                 // set the number of data bits to 8 (byte)

    SerialPortSettings.c_cflag |= CREAD | CLOCAL;                       // turn receiver on 
    SerialPortSettings.c_cc[VMIN]  = 10;                                // read 10 characters (8 data bits and a start and stop bit)
    SerialPortSettings.c_cc[VTIME] = 0;                                 // wait indefinitely

    SerialPortSettings.c_cflag &= ~CRTSCTS;                             // disable hardware based flow control
    SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY);              // disable software based flow control

    SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);      // set to non-cannonical operation mode

    int result = tcsetattr(fd,TCSANOW,&SerialPortSettings);             // set attribute changes

    if (result != 0)
    {
        close(fd);
        perror("failed to configure serial port");
        exit(EXIT_FAILURE);
    }
    configured = 1;
    Serial::Flush();                                                    // discard rx buffer
}

int Serial::Available()
{
    if (!configured)
    {
        return -1;
    }
    int bytes = 0;
    ioctl(fd, TIOCINQ, &bytes);
    return bytes;
}

main.cpp

#include <iostream>
#include "serial.h"

using namespace std;

int main()
{
    Serial serial = Serial("/dev/ttyUSB8");
    serial.Begin();
    while (true)
    {
        int available = serial.Available();
        cout << available << " bytes available" << endl;
    }
    return 1;
}

Arduino代码

void setup() {
  Serial.begin(9600);
}

void loop() {
  delay(2000);
  Serial.print("hello world");
}

0 个答案:

没有答案