3

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

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

串行输出.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);
}

序列号

#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);
}

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

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

4

2 回答 2

5

如果要传输文件,则应将文件分成块,并在每个块上使用校验和;然后在您重新加入另一侧的块时验证校验和。

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

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

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

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

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

于 2012-07-23T20:21:20.330 回答
4

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

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

上面提到的传输协议仅添加层以确保整个文件被发送并且它没有损坏,但是您可以在第一个实例上将它们关闭以理解这个概念。

于 2012-07-23T21:36:06.180 回答