简体   繁体   English

使用C#和C语言进行USB到串行(往返)通信

[英]USB to Serial (to and fro) communication using C# and C language

This is the 1st time am posting my query. 这是我第一次发布查询。 I am in need of help. 我需要帮助。 Any help is appreciated. 任何帮助表示赞赏。

As i agree that i have given my prob as long story. 正如我所同意的,我已将自己的问题作为长篇大论。 But am sorry i am not getting how to make it short and my intention is give complete information regarding my prob. 但是很抱歉,我没有将其简化,我的目的是提供有关我的问题的完整信息。

Problem : I have to communicate between two laptops using USB-to-Serial adapter on windows platform. 问题:我必须使用Windows平台上的USB到串行适配器在两台笔记本电脑之间进行通信。 I have written 2 programs one for sending and another for receiving. 我写了2个程序,一个用于发送,另一个用于接收。 Programs were written in both C and C# programming languages. 程序使用C和C#编程语言编写。

Using C language : I am able to successfully communicate using C-Programs mentioned below. 使用C语言:我可以使用下面提到的C程序成功进行通信。 But the problem is speed. 但是问题是速度。 It takes around 1 hour(60min) for just to pass 150MB. 仅需150 MB,大约需要1个小时(60分钟)。 Anyone plz help me in improving the performance of this programs or you may suggest me other approaches which is robust and give high performance. 任何人都可以帮助我改善此程序的性能,或者您可以向我建议其他健壮并具有高性能的方法。 I also mention some comments along with programs for self understanding. 我还提到了一些注释以及用于自我理解的程序。

Sender File on laptop with serial port : 带串口的笔记本电脑上的发送者文件:

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

Receiving file on laptop with USB port : 通过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;
}

Sender file on laptop with USB port: 带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;
}

Receiver file on laptop with serial port : 带有串口的笔记本电脑上的接收器文件:

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

The above 4 programs behaves as, sender send a character and receives an ack for every character. 以上4个程序的行为如下:发送方发送一个字符并为每个字符接收一个确认。 I have followed this approach, bcoz other approaches were not working fine (in the sense the complete data is not sent, the amount of data sent is not judgeable, bcoz it will different every tym). 我遵循了这种方法,bcoz其他方法都无法正常工作(在某种意义上说,没有发送完整的数据,无法判断发送的数据量,bcoz的每个tym都会有所不同)。 when i used this approach it worked fine. 当我使用这种方法时,它工作正常。

Using C# language : Below two programs are written in C# using visual studio. 使用C#语言:下面两个程序是使用Visual Studio用C#编写的。 I have used SerilaPort class , its properties and methods for communication. 我使用了SerilaPort类,它的属性和通信方法。 Using this, am able to communicate text and xml files on both the sides successfully.Also image files with .jpg extention, can be transferred from USB to serial end withot any loss of data(successful transmission), but if i transfer from serial to usb end, am able receive image with some data loss, even with the data loss am able to see the image. 使用此功能,可以成功地在两侧传输文本和xml文件。扩展名为.jpg的图像文件也可以从USB传输到串行端,而不会丢失任何数据(成功传输),但是如果我从串行传输到在USB端,即使丢失了数据也能够看到图像,但仍然能够接收到图像。

Sender file on laptop with serial port : 带串口的笔记本电脑上的发送者文件:

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

        }
    }
}

Receiver file on laptop with USB port : 带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);
        }
   }
}

Please help me. 请帮我。

Thanks in advance. 提前致谢。

Transmission speed: 传输速度:

Serial ports are simple, not fast. 串行端口很简单,但速度不快。 I am assuming that you are using 230kbps which is already more than many hardware can handle. 我假设您使用的是230kbps,这已经超出了许多硬件的处理能力。 Compression is only thing that might help, but compressing already compressed data (like .mp3) won't help much. 压缩只是可能会有所帮助,但是压缩已压缩的数据(如.mp3)将无济于事。

Data loss: 数据丢失:

Serial ports are simple, not robust. 串行端口很简单,但不可靠。 Data loss is common, and only thing you can do about it is to have protocol to detect errors on incoming frames, and have ability to retry send if there is an error. 数据丢失很常见,您唯一能做的就是拥有协议来检测传入帧上的错误,并能够在发生错误时重试发送。

Conclusion: 结论:

Use TCP/IP instead. 请改用TCP / IP。

Way too long a question. 太长的问题。 I've found only one actual question, and that's the performance bit. 我只发现了一个实际问题,那就是性能。

Just use Ethernet or WiFi. 只需使用以太网或WiFi。 "Serial port" (you probably mean RS-232) speeds are low . “串行端口”(您可能指的是RS-232)速度很低 0.1 Mbit/second is considered fast by RS-232 standards. RS-232标准认为0.1 Mbit /秒很快 You clock 1200 Mbit/3600 seconds, which is 0.3 Mbit/second. 您的时钟为1200 Mbit / 3600秒,即0.3 Mbit /秒。 That is ultra-fast. 那太快了。 I'm in fact surprised that you achieve that, your C# program is explicitly setting the speed to 0.1 Mbit/second. 实际上,我为您实现这一目标感到惊讶,您的C#程序将速度显式设置为0.1 Mbit /秒。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM