Thread: USB to Serial (to and fro) communication using C language

  1. #1
    Registered User
    Join Date
    Dec 2013
    Posts
    3

    Unhappy USB to Serial (to and fro) communication using C language

    Hi eveybuddy,
    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 to give complete information regarding my prob.


    Problem :
    I have to communicate between two laptops using USB-to-Serial adapter. I have written 2 programs one for sending and another for receiving. Programs were written in both C and C# programming languages.


    Using C language :
    I am able to successfully communicate using C-Programs mentioned below. But the problem is speed. It takes around 1 hour(60min) for just to pass 150MB. 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 :

    Code:
    #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 :

    Code:
    #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:

    Code:
    #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 :

    Code:
    #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. 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). when i used this approach it worked fine.



    Please help me.


    Thanks in advance.
    [/code]
    Last edited by chetanraj; 12-18-2013 at 03:56 AM.

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Please write in normal English, not some crappy "SMS speak" or whatever you're using. Bcoz is not a word. Neither is tym. This is important, because not everybody (note the spelling, it's not "eveybuddy") on this forum is a native speaker and capable of deciphering what you wrote.

    By serial, do you mean RS-232? Or some other serial protocol. RS-232 only supports up to 115,200 bits/sec (~115k baud). 150MB is 150*1024*1024 = 157286400 bytes. Divide that by the transfer rate, gives 157286400 / 115200 = 1365.33333333 seconds, or ~22.75 minutes. You simply can't get faster than that with RS-232.

    Why do you have to use a USB to serial port? Is this a requirement for some homework assignment? Can you use just USB or ethernet (or wifi) to connect the two laptops?

    Why are you using conio.h and dos.h. Those are very outdated headers. They (along with other stuff in your code) suggest you're using Turbo C, which is also a very non-standard, outdated compiler. Consider upgrading if possible. There are lots of free alternatives.

    Assuming that you really have to use serial communication:

    I looked up the bioscom documentation (link). It looks like it only supports a maximum rate of 9600 buad. That means your 150MB file would take close to 4 hours to complete. Find a library that supports faster rates, if your devices support it.

    Learn to check for errors. All the file functions (fopen, fgetc, fputc) return error codes. Also, bioscom returns an error code every time, perhaps this will allow you to better detect problems with the serial communication. You should also consider using a parity bit as that will help detect errors in the packet. Sending a checksum or CRC every N bytes would also be good. That way, if you detect an error, you only have to repeat the last N bytes instead of the whole file. I would pick a small-ish N, no more than a few hundred.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Dec 2013
    Posts
    3
    Hi Anduril462,

    First of all i would like to apologize for using colloquial language in my post. Also I am glad and appreciate you for giving feedback and suggestions regarding my post.

    1. Yes I mean RS-232 itself. I agree that RS-232 supports up to 115200 bits/sec, but I have to write the program only in Turbo C which supports only 9600 baud rate. In my program, I have defined a constant i.e. SETTING, where 0xE0 indicates the 9600 baud rate.

    2. Yes, its a requirement that I must use USB-to-Serial adopter, as a communication media.

    3. Am using CONIO.H and DOS.H, is just because, the program that is written for communication must be compatible to DOS environment. It is a prime requisite that, the programs will be run in the DOS environment.

    4. I have checked with status codes and error codes returned by BIOSCOM function, from which i have concluded that, it needs to send ACK for every byte. If I wont do that, I would have resulted in receiving random sized data at the receiver, even if the sender sends complete data.This is how the BIOSCOM function behaves.

    I tried to search other libraries and function, but I am not succeeded in searching. Could any one please suggest some libraries or functions that works in DOS environment and uses Serial port(RS-232) as a basic communication interface for transmitting and receiving data.

    Thanks In advance.

    Regards,
    Chetanraj

  5. #5
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,787
    3. Am using CONIO.H and DOS.H, is just because, the program that is written for communication must be compatible to DOS environment. It is a prime requisite that, the programs will be run in the DOS environment.
    Well, unfortunately CONIO.H is not even portable for programs meant to run in the DOS environment. It was popular (although never standard, ever) about 25 years ago. I suppose that if you enjoy playing with ancient artefacts that no person with a modern compiler can hope to compile, without silly tricks, then it's ok.

    Let me put this bluntly: Turbo C is crap; Pelles C is crap. There really is no reason whatsoever for this program you're writing to use this incompatible, non-portable stuff. I'm sorry for appearing angry but quite frankly I'm sick of seeing this stuff perpetuated.

  6. #6
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    Quote Originally Posted by chetanraj View Post
    3. Am using CONIO.H and DOS.H, is just because, the program that is written for communication must be compatible to DOS environment. It is a prime requisite that, the programs will be run in the DOS environment.

    I tried to search other libraries and function, but I am not succeeded in searching. Could any one please suggest some libraries or functions that works in DOS environment and uses Serial port(RS-232) as a basic communication interface for transmitting and receiving data.
    You could try DJGPP, which is basically like MinGW for DOS. It is old, but probably newer than whatever DOS stuff you are trying now. DJGPP has support for termios.h which lets you use similar methods as Linux to access the serial port

    Documentation of DJGPP termios

    DJGPP C Library Reference

    Example of using termios

    linux - how to open, read, and write from serial port in C - Stack Overflow

    Obviously you'll have to make adjustments for the environment, for example in DJGPP I doubt the serial port is called /dev/ttyUSB1

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    I agree with Hodor, though am a little less angry about it . And c99tutorial gave you some good advice. I suspect, however, that this is a school assignment, and you may be required to use Turbo C -- if so, I'm sorry. Your education system is doing you a disservice. I recommend you familiarize yourself with modern tools as well, so as to be prepared for the real world when you're done.

    Quote Originally Posted by chetanraj View Post
    1. Yes I mean RS-232 itself. I agree that RS-232 supports up to 115200 bits/sec, but I have to write the program only in Turbo C which supports only 9600 baud rate. In my program, I have defined a constant i.e. SETTING, where 0xE0 indicates the 9600 baud rate.
    Then something is wrong, your 150MB file can not transfer in 1 hour. At best is roughly 4 hours, if you don't send ACKs. However, if you send a 1 byte ACK for each byte of data you send, then you cut that in half, roughly 8 hours for a 150MB file.
    Quote Originally Posted by chetanraj View Post
    4. I have checked with status codes and error codes returned by BIOSCOM function, from which i have concluded that, it needs to send ACK for every byte. If I wont do that, I would have resulted in receiving random sized data at the receiver, even if the sender sends complete data.This is how the BIOSCOM function behaves.
    I see you check the modem status in a few places, and you store (but never) use the return value in a few other places. That is different than checking whether the bioscom function actually encountered an error. You need to check for all error conditions every time you call it. You need to read the bioscom documentation carefully, and pay attention to the return values. It returns 16 bits. Thus, for example, your shiftcount variables potentially contain more than just the 8 data bits, which could cause problems when you use them to build count.

    Also: I don't think "that is how the bioscom function behaves". Nobody would use the library if it read or wrote random sized data all the time.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. serial communication
    By cbrandy in forum C Programming
    Replies: 2
    Last Post: 02-24-2012, 07:50 AM
  2. Serial Communication in C++
    By NewGuy100 in forum C++ Programming
    Replies: 8
    Last Post: 04-24-2006, 01:56 PM
  3. Serial Communication
    By Korn1699 in forum C# Programming
    Replies: 0
    Last Post: 11-29-2005, 12:50 PM
  4. C Serial Communication BCD
    By ZoomCities in forum C Programming
    Replies: 1
    Last Post: 10-13-2005, 07:00 PM
  5. serial communication
    By hick.hack in forum C++ Programming
    Replies: 1
    Last Post: 02-13-2003, 12:18 PM

Tags for this Thread