【问题标题】:USB to Serial (to and fro) communication using C# and C language使用 C# 和 C 语言进行 USB 到串行(来回)通信
【发布时间】:2013-12-18 08:57:24
【问题描述】:

这是我第一次发布我的查询。我需要帮助。任何帮助表示赞赏。

我同意我已经把我的概率说得很长了。但很抱歉,我不知道如何缩短它,我的目的是提供有关我的问题的完整信息。

问题: 我必须在 Windows 平台上使用 USB 转串口适配器在两台笔记本电脑之间进行通信。我写了两个程序,一个用于发送,另一个用于接收。程序是用 C 和 C# 两种编程语言编写的。

使用 C 语言: 我能够使用下面提到的 C 程序成功地进行通信。但问题是速度。通过 150MB 大约需要 1 小时(60 分钟)。任何人请帮助我提高该程序的性能,或者您可以向我建议其他强大且性能高的方法。我还提到了一些 cmets 以及用于自我理解的程序。

带串口的笔记本电脑上的发送文件:

#include <stdio.h>
#include <bios.h>
#include <conio.h>
#define COM1       0
#define DATA_READY 0x100
#define TRUE       1
#define FALSE      0
#define SETTINGS ( 0xE0 | 0x03 | 0x00 | 0x00)

int main(void)
{
   int in, out, status, DONE = FALSE,i=0;
   char c;
   FILE *fp,*fp1;
   unsigned long count = 0,shiftcount = 0;

   clrscr();

   fp = fopen("C:/TC/pic.jpg","rb"); //opened for reading actual content
   fp1 = fopen("C:/TC/pic.jpg","rb"); //opened for reading the size of file

   fseek(fp1,0L,2);
   count = ftell(fp1) + 1; // file size

   bioscom(0, SETTINGS, COM1); // initializing the port

   printf("No. of Characters = %lu\n",count);

// since bioscom function can send or receive only 8bits at a time, am sending file size in
    4 rounds so that we can send at max of 4GB file.

   bioscom(1,count,COM1); // sneding 1st lower 8bits 

   bioscom(1,count>>8,COM1); // sending 2nd set of lower 8bits

   bioscom(1,count>>16,COM1); // sending 3rd set of lower 8bits

   bioscom(1,count>>24,COM1); // sending upper 8 bits

   cprintf("... BIOSCOM [ESC] to exit ...\n");
   while (!DONE)
   {
      status = bioscom(3, 0, COM1);// get the status of port
      //printf("%d",status);
      if (status & DATA_READY) //checks if data is ready
      {
        out = bioscom(2, 0, COM1); // receives the ack
        if(!feof(fp))
        {
            c = fgetc(fp); //read character by character from file
            bioscom(1,c,COM1);//send character to receiver
            putch(c);//display
        }
     }

//to interrupt
     if (kbhit())
     {
        if ((in = getch()) == '\x1B')
           DONE = TRUE;
     }
   }
   fclose(fp);
   return 0;
}

通过 USB 端口在笔记本电脑上接收文件:

#include <stdio.h>
#include <bios.h>
#include <conio.h>

#define COM4       3
#define DATA_READY 0x100
#define TRUE       1
#define FALSE      0

#define SETTINGS ( 0xE0 | 0x03 | 0x00 | 0x00)

int main(void)
{
   int in, out, status;
   char c;
   FILE *fp;
   unsigned long shiftcount1=0,shiftcount2=0,shiftcount3=0,shiftcount4=0;
   unsigned long count = 0, DONE = 1;

   clrscr();

   fp = fopen("C:/TC/pic1.jpg","wb");// file opened for writing

   bioscom(0, SETTINGS, COM4);//initialize tyhe port
   cprintf("... BIOSCOM [ESC] to exit ...\n");
//receives all the 32 bits of file size sent from sender
   shiftcount1 = bioscom(2,0,COM4);
   shiftcount2 = bioscom(2,0,COM4);
   shiftcount3 = bioscom(2,0,COM4);
   shiftcount4 = bioscom(2,0,COM4);

//send an ack
   bioscom(1,'x',COM4);

   count = shiftcount1 | (shiftcount2<<8) | (shiftcount3<<16) | (shiftcount4<<24);

   printf("shift4 = %lu\tshift3 = %lu\tshift2 = %lu\tshift1 = %lu\n",shiftcount4,shiftcount3,shiftcount2,shiftcount1);
   printf("File Size = %lu\n",count);

//loop till the size of the file
   while (DONE < count)
   {
      status = bioscom(3, 0, COM4);// check the status
     // printf("%d",status);
      if (status & DATA_READY)//check for data ready at the port
      {
        out = bioscom(2, 0, COM4);//receive the data
        DONE++;
        fputc(out,fp);
        putch(out);
        bioscom(1,'x',COM4);//send an ack
      }


     if (kbhit())
     {
        if ((in = getch()) == '\x1B')
        break;
     }
   }
   fclose(fp);
   return 0;
}

在带有 USB 端口的笔记本电脑上发送文件:

#include <stdio.h>
#include <bios.h>
#include <conio.h>
#include<dos.h>
#include<stdlib.h>
#include<time.h>

#define RTS 0x02
#define COM1       0
#define COM4       3
#define CURRCOM   COM4
#define DATA_READY 0x100
#define TRUE       1
#define FALSE      0

#define SETTINGS ( 0xE0 | 0x03 | 0x00 | 0x00)

int main(void)
{
   int in, out, status, DONE = FALSE,nextfile = 1;
   char c;
   FILE *fp,*fp1;
   unsigned long count = 0,shiftcount = 0;
   clock_t start,end;

   start = clock();

   clrscr();

   fp = fopen("C:/TC/pic.jpg","rb");
   fp1 = fopen("C:/TC/pic.jpg","rb");

   fseek(fp1,0L,2);
   count = ftell(fp1) + 1;

   bioscom(0, SETTINGS, CURRCOM);

  /*  while(!feof(fp1))
    {
    c = fgetc(fp1);
    count++;
    } */


   printf("No. of Cheracters = %lu\n",count);


    bioscom(1,count,CURRCOM);

    bioscom(1,count>>8,CURRCOM);

    bioscom(1,count>>16,CURRCOM);

    bioscom(1,count>>24,CURRCOM);

   cprintf("\n... BIOSCOM [ESC] to exit ...\n");
   while (!DONE)
   {
      status = bioscom(3, 0, CURRCOM);
      if (status & DATA_READY)
      {
        out = bioscom(2,0,CURRCOM);

        if(!feof(fp))
        {
            c = fgetc(fp);
            bioscom(1,c,CURRCOM);
            putch(c);
        }
      }

     if (kbhit())
     {
        if ((in = getch()) == '\x1B')
           DONE = TRUE;
     }
   }
   fclose(fp);

   end = clock();
   printf("\nTotal time = %d\n",(end - start)/CLK_TCK);

   return 0;
}

带串口的笔记本电脑上的接收文件:

#include <stdio.h>
#include <bios.h>
#include <conio.h>
#include<time.h>

#define COM1       0
#define DATA_READY 0x100
#define TRUE       1
#define FALSE      0

#define SETTINGS ( 0xE0 | 0x03 | 0x00 | 0x00)

int main(void)
{
   int in, out, status;
   char c;
   FILE *fp;
   int y = 0,esc;
   unsigned long count=0,shiftcount1 = 0,shiftcount2 = 0,shiftcount3 = 0,shiftcount4 = 0, DONE = 1;

   clock_t start,end;

   start = clock();

   clrscr();

   fp = fopen("C:/TC/pic1.jpg","wb");

   bioscom(0, SETTINGS, COM1);
   cprintf("... BIOSCOM [ESC] to exit ...\n");

   shiftcount1 = bioscom(2,0,COM1);
   shiftcount2 = bioscom(2,0,COM1);
   shiftcount3 = bioscom(2,0,COM1);
   shiftcount4 = bioscom(2,0,COM1);

   bioscom(1,'x',COM1);

   count = shiftcount1 | (shiftcount2<<8) | (shiftcount3<<16) | (shiftcount4<<24);

   printf("shift4 = %lu\tshift3 = %lu\tshift2 = %lu\t shift1 = %lu\n",shiftcount4,shiftcount3,shiftcount2,shiftcount1);
   printf("file size = %lu\n",count);

   while (DONE < count)
   {
      status = bioscom(3, 0, COM1);
      //printf("%d",status);
      if (status & DATA_READY)
      {
        out = bioscom(2, 0, COM1);
        DONE++;
        fputc(out,fp);
        putch(out);
        bioscom(1,'x',COM1);
      }


     if (kbhit())
     {
        if ((in = getch()) == '\x1B')
           break;
     }
   }
   fclose(fp);

   end = clock();
   printf("\nTotal time = %f\n",(end - start)/CLK_TCK);

   return 0;
}

上述 4 个程序的行为是,发送者发送一个字符,并为每个字符接收一个 ack。我采用了这种方法,但其他方法无法正常工作(从某种意义上说,没有发送完整的数据,发送的数据量是不可判断的,因为它会因时间而异)。当我使用这种方法时效果很好。

使用 C# 语言: 下面两个程序是使用 Visual Studio 用 C# 编写的。我使用了 SerilaPort 类,它的属性和通信方法。使用它,我能够成功地在双方通信文本和xml文件。还有.jpg扩展名的图像文件,可以从USB传输到串口而不会丢失任何数据(成功传输),但是如果我从串口传输到usb端,能接收到有一些数据丢失的图像,即使数据丢失也能看到图像。

带串口的笔记本电脑上的发送文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.IO;
using System.Threading;

namespace Communication
{
    class Program
    {
        static void Main(string[] args)
        {

            string name;
            string message;
            StringComparer stringComparer = StringComparer.OrdinalIgnoreCase;
            //Thread readThread = new Thread(Read);


            FileStream fs = new FileStream("C:/text.xml", FileMode.Open);

            //StreamReader sr = new StreamReader(fs);

            BinaryReader br = new BinaryReader(fs);

            // Create a new SerialPort object with default settings.
            SerialPort _serialPort = new SerialPort();

            // Allow the user to set the appropriate properties.
            _serialPort.PortName = "COM1";
            _serialPort.BaudRate = 115200;
            _serialPort.Parity = Parity.None;
            _serialPort.DataBits = 8;
            _serialPort.StopBits = StopBits.One;
            _serialPort.Handshake = Handshake.None;

            // Set the read/write timeouts
            _serialPort.ReadTimeout = 500;
            _serialPort.WriteTimeout = 500;

            _serialPort.Open(); 
            bool _continue = true;
            //readThread.Start();

            int len = (int)fs.Length;
            char[] data = new char[len+1];

            br.Read(data, 0, len);

            for (int i = 0; i < len+1; i++)
            {
                _serialPort.Write(data, i, 1);
                //Console.Write(data,i,1);
            }

            br.Close();
            fs.Close();
            _serialPort.Close();

        }
    }
}

带 USB 端口的笔记本电脑上的接收器文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.IO;
using System.Threading;
using System.Collections;

namespace Communication
{
    class Program
    {
        static void Main(string[] args)
        {
            SerialComm comm = new SerialComm();
            comm.Init();
            comm.ReadSerial();
            comm.WriteToFile();
            comm.ResClose();
            Console.ReadKey();
        }
    }


    class SerialComm
    {
        FileStream fs = null;
        BinaryWriter file = null;
        ArrayList al = null;

        public Boolean Init()
        {
            if (fs == null)
            {
                fs = new FileStream("C:/text1.txt", FileMode.OpenOrCreate);
            }

            if (file == null)
            {
                file = new BinaryWriter(fs);
            }
            if (al == null)
            {
                al = new ArrayList();
            }

            return true;
        }

        public void ResClose()
        {
            file.Close();
            fs.Close();
        }


        public Boolean ReadSerial()
        {
            SerialPort port;
            StreamWriter sw;
            ConsoleKeyInfo ck;

            port = new SerialPort();

            port.PortName = "COM4";
            port.BaudRate = 115200;
            port.DataBits = 8;
            port.Parity = Parity.None;
            port.StopBits = StopBits.One;
            port.Handshake = Handshake.None;

            port.Open();

            port.BaseStream.Flush();
            port.DiscardInBuffer();
            int c = 1;
            while (c != 0)
            {
                c = port.ReadByte();
                al.Add((byte)c);
            }
            return true;
        }

        public void WriteToFile()
        {
            int i = 0;
            byte[] message = al.ToArray(typeof(byte)) as byte[];
            file.Write(message, 0, message.Length - 1);
        }
   }
}

请帮助我。

提前致谢。

【问题讨论】:

  • 是的,我同意....但是第一个 4 个程序包括 2 个发送者和 2 个接收者,它们非常相似,只有端口号不同。我发布只是为了不混淆,如果有人真的在寻找交流,他们会使用它。
  • 所以在 115200 波特,当您等待每个字符回显时。你考虑过前向纠错吗?循环冗余校验?也许看看 Kermit 协议?
  • @MarkU:平均速度显然是 150 Mbyte/60 分钟,所以 2.5 Mbyte/分钟而不是秒。显然你不能以 115.200 波特率发送 20.000.000 位/秒。
  • 对问题格式的建议:从问题开始,不要为成为新用户而道歉。当我们的读者将鼠标悬停在托盘中的主主题行上时,第一段是人们在决定是否深入到实际消息之前看到的内容。
  • 投票结束。无法在软件中修复不适当的硬件选择。

标签: c# c


【解决方案1】:

传输速度:

串行端口很简单,但速度不快。我假设您使用的是 230kbps,这已经超过了许多硬件可以处理的速度。压缩只是可能有帮助的东西,但压缩已经压缩的数据(如 .mp3)不会有太大帮助。

数据丢失:

串行端口很简单,但不可靠。数据丢失很常见,您唯一能做的就是让协议检测传入帧的错误,并在出现错误时重试发送。

结论:

改用 TCP/IP。

【讨论】:

  • 串口既简单又健壮,(只要它们不被滥用,与任何接口相同)。
  • @MartinJames 是的,你可以让它变得健壮。但在实践中,您不能只通过 RS-232 发送所有内容并期望它始终通过。这是一个模拟世界,会有传输错误。迟早。
  • user694733 感谢您的回复。如果 TCP/IP 是解决方案,那么您能否建议任何方法,以便它应该使用串行端口并且编程仅在 Turbo C 中完成。
  • @user3114042 我的意思是使用 TCP/IP,因为以太网硬件的功能远不止串行端口。但是由于从您的问题评论中看到这是不可能的,也许您应该使用一些现有的流量协议(如 Modbus/RTU)。您仍然不会获得高传输速度,但至少会有一些错误检测。
【解决方案2】:

Way 问题太长了。我只发现了一个实际问题,那就是性能问题。

只需使用以太网或 WiFi。 “串行端口”(您可能是指 RS-232)速度。 RS-232 标准认为 0.1 Mbit/秒快速。您的时钟为 1200 Mbit/3600 秒,即 0.3 Mbit/秒。那是超快的。事实上,我很惊讶你能做到这一点,你的 C# 程序明确地将速度设置为 0.1 Mbit/秒。

【讨论】:

  • 他的 16 位 C 程序正在初始化端口以 9600 波特率运行 :) 假设他没有使用真正的串行端口是很安全的。
  • @MSalters,感谢您的回复。性能问题与 C 程序有关。顺便说一句,C# 实现的速度相当不错,即在一个半分钟内可以传输大约 1MB 的数据。我认为它的速度非常快。
  • @user3114042:8 Mbit/90 秒是 0.088 Mbit/秒,这对于 0.115 MBaud 是有意义的。但如果这很好,那么有什么问题?!
猜你喜欢
  • 1970-01-01
  • 2013-12-22
  • 1970-01-01
  • 1970-01-01
  • 2014-10-01
  • 2013-11-02
  • 1970-01-01
  • 1970-01-01
  • 2014-03-23
相关资源
最近更新 更多