簡體   English   中英

通過串口發送文件

[英]Sending files over serial port

我需要一些通過串行連接發送文件的幫助。 我有兩條RS232轉USB電纜,我用一個發送數據測試我的代碼,另一個用來接收它。 我讓它們彼此物理連接。

所以我寫了一些改編自幾個來源的代碼,我可以成功轉移一系列字符。 一個程序接收數據,另一個程序發送數據。 我將這兩個在兩個獨立的終端中打開。 找到下面的兩個代碼塊:

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

所以我想做的是發送文件。 例如,一個jpeg文件。 有沒有辦法將其轉換為字節碼並將其重組為jpeg? 我已經四處搜索但很遺憾找不到相關信息 - 也許我正在搜索錯誤的條款。

更好的方法是在壓縮后發送文件。 最后,我使用gzip壓縮jpeg文件,然后通過串行連接發送它們。 感謝大家!

如果要傳輸文件,則應將文件分成塊,並對每個塊使用校驗和; 然后在重新加入另一側的塊時驗證校驗和。

這不是一個新問題。 其他人已經為你解決了。 您應該獲得一個現有的可靠文件傳輸程序並通過串行鏈接運行它。

最好的選擇是rsync。 這是GPL,因此如果您正在進行專有工作,許可證可能會阻止您使用它。

另一個不錯的選擇是XMODEM(或YMODEM或ZMODEM)。 我找到了帶有BSD許可證的XMODEM的C實現,所以你可以肯定地使用它。 這比rsync更小更簡單。

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

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

我還打算建議Z-Modem或X-Modem進行文件傳輸。 但你必須明白的是文件並沒有什么特別之處。 就轉移計算機和接收終端而言,正在發送的文件只是二進制數據流,無論它是jpeg圖像,壓縮文件還是文本文件。

您所要做的就是將傳入的流寫入文件,確保它具有正確的擴展名,以便正確處理。

上面提到的傳輸協議只添加層以確保發送整個文件並且它沒有被破壞,但您可以在第一個實例上解除它們以理解該概念。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM