Linux 通过串口发送文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11619664/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 13:53:15  来源:igfitidea点击:

Sending files over serial port

clinuxfileserial-port

提问by capcom

I need some help sending a file over a serial connection. I have two RS232 to USB cables, and I am testing out my code by using one to send data, and the other to receive it. I have them both physically connected to each other.

我需要一些帮助通过串行连接发送文件。我有两根 RS232 到 USB 电缆,我正在测试我的代码,使用一根发送数据,另一根接收数据。我让它们彼此物理连接。

So I wrote some code adapted from a few sources, and I can successfully transfer a series of characters. One program receives the data, the other sends it. I have these two open in two separate terminals. Find the two blocks of code below:

所以我写了一些从几个来源改编的代码,我可以成功地传输一系列字符。一个程序接收数据,另一个程序发送数据。我在两个单独的终端中打开了这两个。找到下面的两个代码块:

serialout.c

串行输出文件

#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

int main()
    {
            //writing
            int writeport = open_port("/dev/ttyUSB0");

            char str[] = "hello how are you?";
            int n = write(writeport, str, strlen(str));
            if (n < 0)
                    fputs("write() of bytes failed!\n", stderr);

            //closing ports
            close(writeport);
    }

    int open_port(char str[])
{
    int fd = open(str, O_RDWR | O_NOCTTY | O_NONBLOCK); // ?? NDELAY or NONBLOCK?

  if (fd == -1)
  {
                    perror("open_port: Unable to open /dev/ttyS0 - ");
  }
  else
                    fcntl(fd, F_SETFL, 0);

      struct termios options;
      tcgetattr(fd, &options); //this gets the current options set for the port

      // setting the options

      cfsetispeed(&options, B9600); //input baudrate
      cfsetospeed(&options, B9600); // output baudrate
      options.c_cflag |= (CLOCAL | CREAD); // ?? enable receicer and set local mode
      //options.c_cflag &= ~CSIZE; /* mask the character size bits */
      options.c_cflag |= CS8;    /* select 8 data bits */
      options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // choosing raw input
      options.c_iflag &= ~INPCK; // disable parity check
      options.c_iflag &= ~(IXON | IXOFF | IXANY); // disable software flow control
      options.c_oflag |= OPOST; // ?? choosing processed output
      options.c_cc[VMIN] = 0; // Wait until x bytes read (blocks!)
      options.c_cc[VTIME] = 0; // Wait x * 0.1s for input (unblocks!)

      // settings for no parity bit
      options.c_cflag &= ~PARENB;
      options.c_cflag &= ~CSTOPB;
      options.c_cflag &= ~CSIZE;
      options.c_cflag |= CS8;

      tcsetattr(fd, TCSANOW, &options); //set the new options ... TCSANOW specifies all option changes to occur immediately

  return (fd);
}

serialin.c

序列号

#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

int main()
{
    //reading   
    int readport = open_port("/dev/ttyUSB1");

    //trying to read one character at a time
    char buff;
    int n = 1;

   while (n > 0)
   {
    n = read(readport, &buff, 1);
    printf("%c", buff, buff);
   }

    printf("\n");

    //closing ports
    close(readport);
}

int open_port(char str[])
{
    int fd = open(str, O_RDWR | O_NOCTTY | O_NONBLOCK); // ?? NDELAY or NONBLOCK?

  if (fd == -1)
  {
        perror("open_port: Unable to open /dev/ttyS0 - ");
  }
  else
        fcntl(fd, F_SETFL, 0);

  struct termios options;
  tcgetattr(fd, &options); //this gets the current options set for the port

  // setting the options

  cfsetispeed(&options, B9600); //input baudrate
  cfsetospeed(&options, B9600); // output baudrate
  options.c_cflag |= (CLOCAL | CREAD); // ?? enable receicer and set local mode
  //options.c_cflag &= ~CSIZE; /* mask the character size bits */
  options.c_cflag |= CS8;    /* select 8 data bits */
  options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // choosing raw input
  options.c_iflag &= ~INPCK; // disable parity check
  options.c_iflag &= ~(IXON | IXOFF | IXANY); // disable software flow control
  options.c_oflag |= OPOST; // ?? choosing processed output
  options.c_cc[VMIN] = 0; // Wait until x bytes read (blocks!)
  options.c_cc[VTIME] = 0; // Wait x * 0.1s for input (unblocks!)

  // settings for no parity bit
  options.c_cflag &= ~PARENB;
  options.c_cflag &= ~CSTOPB;
  options.c_cflag &= ~CSIZE;
  options.c_cflag |= CS8;

  tcsetattr(fd, TCSANOW, &options); //set the new options ... TCSANOW specifies all option changes to occur immediately

  return (fd);
}

So what I'd like to do is send a file. For example, a jpeg file. Is there some way to convert it to bytecode and reassemble it as a jpeg? I have searched around but have found little relevant information unfortunately - maybe I'm searching the wrong terms.

所以我想做的是发送一个文件。例如,一个 jpeg 文件。有什么方法可以将其转换为字节码并将其重新组合为 jpeg 吗?我四处搜索,但不幸的是几乎没有找到相关信息 - 也许我正在搜索错误的术语。

Even better would be to send the files after they are zipped. Ultimately, I am using gzip to zip jpeg files, then send them over the serial connection. Thanks everyone!

更好的是在压缩后发送文件。最终,我使用 gzip 来压缩 jpeg 文件,然后通过串行连接发送它们。谢谢大家!

采纳答案by steveha

If you want to transfer files, you should break the file up into chunks, and use a checksum on each chunk; then verify the checksums as you rejoin the chunks on the other side.

如果你想传输文件,你应该把文件分成块,并对每个块使用校验和;然后在您重新加入另一侧的块时验证校验和。

This is not a new problem. Others have solved it for you. You should get an existing reliable file-transfer program and run it over the serial link.

这不是一个新问题。别人已经为你解决了。您应该获得一个现有的可靠文件传输程序并通过串行链接运行它。

The top choice would be rsync. That is GPL, so the license may keep you from using it if you are doing proprietary work.

首选是 rsync。那是 GPL,因此如果您从事专有工作,许可证可能会阻止您使用它。

Another good choice would be XMODEM (or YMODEM or ZMODEM). I found a C implementation of XMODEM with a BSD license, so you can use this for sure. This is also smaller and simpler than rsync.

另一个不错的选择是 XMODEM(或 YMODEM 或 ZMODEM)。我找到了一个带有 BSD 许可证的 XMODEM 的 C 实现,所以你可以肯定地使用它。这也比 rsync 更小更简单。

http://www.menie.org/georges/embedded/#xmodem

http://www.menie.org/georges/embedded/#xmodem

http://en.wikipedia.org/wiki/XMODEM

http://en.wikipedia.org/wiki/XMODEM

回答by Rafael Dazcal

I was also going to suggest Z-Modem or X-Modem for file transferring. But what you've got to understand is that there's nothing special about files. As far as the transferring computer and receiving terminal are concerned, the file being sent is just a stream of binary data, no matter if it's a jpeg image, a compressed file or just a text file.

我还打算建议使用 Z-Modem 或 X-Modem 进行文件传输。但是您必须了解的是,文件并没有什么特别之处。就传输计算机和接收端而言,发送的文件只是一个二进制数据流,无论是jpeg图像、压缩文件还是文本文件。

All you've got to do is write the incoming stream into a file an make sure it has the right extension so it can be properly handled.

您所要做的就是将传入的流写入文件并确保它具有正确的扩展名,以便可以正确处理。

The transfer protocols mentioned above only add layers to ensure the whole file is being sent and that it is not corrupted, but you can dismiss them on a first instance to understand the concept.

上面提到的传输协议只添加了层以确保整个文件被发送并且它没有被损坏,但是您可以在第一时间忽略它们以理解这个概念。