Linux C串行程序冻结

时间:2013-09-30 12:06:41

标签: c linux serial-port arduino beagleboard

我正在一台小型Linux服务器(在Beagleboard xM ARM计算机上运行的Ubuntu Server 13.04)上工作,它将在笔记本电脑之间进行无线通信和Arduino通信。我似乎遇到的问题是关于Arduino和Beagleboard之间的通信。该程序将运行一段时间,大约30秒左右,然后它将停止。该程序将继续运行,但该端口显然已冻结。

我正在运行的程序目前只是一个扫描伺服超过一定范围的测试程序。找到了用于设置端口的函数的代码here

我的程序代码如下,但在单独的线程中找到的代码除外:

    #include <errno.h>
    #include <termios.h>
    #include <stdio.h>
    #include <string.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <iostream>

    using namespace std;

   ...

   int main (int argc, const char* argv[]) {
        cout << "TestIO running...\n";
        char* portname = "/dev/ttyACM0";
        // Open serial port
        int fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);

        // Return error if port cannot be opened
        if (fd < 0)
        {
                cout << "error " << errno << " opening " <<  portname << ": " << strerror (errno) << "\n";
                return -1;
        }

        set_interface_attribs (fd, B9600, 0);   // set speed to 9600 bps, 8n1 (no parity)
        set_blocking (fd, 0);                   // set no blocking

        // Read from serial port
        //char inputBuffer[64];
        //int inputLength = read(fd, inputBuffer, sizeof inputBuffer);

        double output = 575;
        char outputString[255];
        char outputLength;
        int incrimentor = 1;
        char inChar;
        for(;;) {
                if (output >= 675 )
                        incrimentor = -1;
                else if (output <= 375)
                        incrimentor = 1;
                output += incrimentor;

                // Sweep wheels on car, set drive motor to 0
                outputLength = sprintf(outputString, "%0.2f", output);
                write(fd, outputString, outputLength);
                write(fd, ",", 1);
                write(fd, "0", 1);
                write(fd, "\n", 1);

                cout << outputString << "\n";

                // Sleep thread for 5000 uS (5 ms)
                usleep(5000);
        }
        close(fd);
        return 0;
}

稍微不同的说明,当程序冻结时,我必须强制它退出代码以关闭端口永远不会到达,因此我无法再次运行程序来测试它。我很好奇是否有人知道如何通过终端中运行的Linux命令关闭串口。

谢谢!

1 个答案:

答案 0 :(得分:0)

参考关于如何退出挂起程序的第二个问题:

将返回值的测试添加到所有系统调用通常是一个好主意!

请注意,read() / write()不一定会读取/写出与被告知的数据一样多的数据。

如果进程收到信号,read() / write()也会返回。

这里特别添加测试结果到可能阻止(write())的调用:

ssize_t writen(int fd, char * buffer, size_t size)
{
  ssize_t written_total = 0;
  ssize_t written = 0;

  while  (outputLength > written_total)
  {
    written = write(fd, buffer + written_total, size - written_total);
    if (-1 == written)
    {
      if (EINTR == errno)
      {
        /* interupted by signal -> break and leave */
        break;
      }
      elseif ((EAGAIN == errno) || (EWOULDBLOCK == errno))
      {
        continue; /* try again */
      }

      /* another error occured -> log, break and leave */

      break;
    }

    written_total += written;
  }

  if (outputLength > written_total)
  {
    if (-1 = written)
    {
      /* handle error */
    }
    else
    {
      /* notify of interruption */
    }
  }
  else
  {
    /* log succesfully transmission of all data */
  }

  return written_total;
}

int main()
{
  ...

  do
  {
    if (outputLength != writen(fd, outputString, outputLength))
    {
      fprintf(stderr, "writen(fd, outputString, outputLength) failed");
      break;
    }

    if (1 != writen(fd, ",", 1))
    {
      fprintf(stderr, "writen(fd, ",", 1)) failed");
      break;
    }

    if (1 != writen(fd, "0", 1))
    {
      fprintf(stderr, "writen(fd, "0", 1)) failed");
      break;
    }

    if (1 != writen(fd, "\n", 1))
    {
      fprintf(stderr, "writen(fd, "\n", 1)) failed");
      break;
    }
  } while (0);

  if (-1 == close(fd))
  {
    perror("close() failed");
  }

  ...
}

请注意,该程序还需要注册一个信号处理程序(例如SIGUSR1),它什么都不做,但“吃掉”信号。

然后从命令行中,您可以通过执行以下操作轻松取消阻止程序:

$ kill <program-pid> -SIGUSR1