#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2006
    Posts
    16
    Rep Power
    0

    RS232 Programming in C working on Windows (cygwin) but not on linux - suggestions?


    Hi,

    I am trying to communicate via RS232 to a modem using a C program that I wrote. I have originally developed the software in a Cygwin shell under Windows, and it is working perfectly. Now I have tried to port the software to a Linux machine (same gcc version, same USB-to-RS232 adapter) and it's not working anymore. The program will establish the connection, but it will return funny characters when trying to read anything. I have tried to match the port settings between the windows and the linux machine (using stty -F /dev/ttyUSB0 -a and comparing) but it didn't work. any help on this particular issue?

    Note: under Cygwin I was opening the port as /dev/com5 , whereas in Linux I am opening the port as /dev/ttyUSB0 . I guess that the first means passing through the Windows serial API, so this might be the issue. I am wondering how I can replicate these conditions and make the program working on Linux as well..

    Thanks!

    code follows:

    Code:
    #include <stdio.h> // standard input / output functions
    
    #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 definitionss
    
    #include <time.h>   // time calls
    
    #include <stdlib.h>
    
    #include <sys/time.h>
    
    #define FALSE 0
    
    #define TRUE 1
    
    volatile int STOP=FALSE;
    
    speed_t low_speed=B9600;
    
    speed_t medium_speed=B38400;
    
    speed_t high_speed=B115200;
    
    
    /*Function to open a serial port*/
    
    int open_port(void){
    
    	int fd; // file description for the serial port
    
    	fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NONBLOCK);
    
    	if(fd == -1) // if open is unsucessful
    
    	{
    
    	 	perror("open_port: Unable to open /dev/ttyS0 - ");
    
    	}
    
    	else
    
    	{   
    
    	 	fcntl(fd, F_SETFL, O_NONBLOCK);
    
    	}
    
    	return(fd);
    
    }
    
    
    
    /*Port configuration*/
    
    int configure_port(int fd , speed_t st)      {
    
    	struct termios port_settings;      // structure to store the port settings in
    
    	tcgetattr(fd, &port_settings);
    
    	cfsetispeed(&port_settings, st);    // set baud rates
    
    	cfsetospeed(&port_settings, st);
    
    	port_settings.c_cflag &= ~PARENB;    // set no parity, stop bits, data bits
    
    	port_settings.c_cflag &= ~CSTOPB;
    
    	port_settings.c_cflag &= ~CSIZE;
    
    	port_settings.c_cflag |= CS8;
    
    	//port_settings.c_cflag |= (CLOCAL | CREAD);
    
    	port_settings.c_lflag |= (ICANON | ECHO | ECHOE);
    
    	tcsetattr(fd, TCSANOW, &port_settings);    // apply the settings to the port
    
    	return(fd);
    
    }
    
    int main(void){
            int fd = open_port();
    
    	FILE *frate;
    
    	
    
    	int pack=0;
    
    	unsigned char check;
    
    	char rate_info[255];
    
    	frate=fopen("rate.txt","r");
    
    	if (frate==NULL) {
    
    			printf("Error in file opening ");
    
    			return(0);
    
    			}
    
    	fscanf(frate,"%s",&rate_info);
    
    	fclose(frate);
    
    	
    
    	int i=0;
    
    	int n=0;
    
    	int res;
    
    	int choice;
    
    	char buf[255];
    
    	printf("Now the modem is going into command mode\n");
    
    	sleep(1);
    
    	write(fd,"+++",3);
    
    	sleep(1);
    
    	STOP=FALSE;
    
    	n=0;
    
    	i=0;
    
    	for ( n=0;n<3;n++){
    
    		while (STOP==FALSE) {     /* loop until we have a terminating condition */
    
    		        
    
    			res = read(fd, buf+i, 1);
    
    			printf("%c", buf[i]);
    
    			if(buf[i] == '\n')
    
    				STOP = TRUE;
    
    		         }
    
    		STOP=FALSE;
    
    		i=0;
    
    	}
           write(fd,"ATA\r\n",5);
    
    	sleep(1);
    
    	STOP=FALSE;
    
    	i=0;
    
    	n=0;
    
    	for ( n=0;n<3;n++){
    
    		while (STOP==FALSE) {     /* loop until we have a terminating condition */
    
    		        
    
    			res = read(fd, buf+i, 1);
    
    			printf("%c", buf[i]);
    
    			if(buf[i] == '\n')
    
    				STOP = TRUE;
    
    		         }
    
    	STOP=FALSE;
    
    	i=0;
    
    	}
           close(fd);
    }
  2. #2
  3. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,638
    Rep Power
    4247
    Do you know if your read() succeeded. You're assigning the return value of read() to res, but you aren't checking it. That might be a good place to start off.

    Comments on this post

    • sizablegrin agrees : Despite rumors to the contrary, return values are mostly Good Thangs.
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2006
    Posts
    16
    Rep Power
    0
    hi,
    i am actually trying to find out how I can read multiple lines from the serial port. one of the main issues I have is that in minicom the read is ok, while with my read i have 1 blank line in the middle of each line, so i guess i am not doing the read process correctly.

    here is some check code i am doing to see if i can get the basics (it doesn't actually work). any thoughts?

    many thanks!

    Code:
    //LIBRARIES
    
    #include <stdio.h> // standard input / output functions
    
    #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 definitionss
    
    #include <time.h>   // time calls
    
    #include <stdlib.h>
    
    #include <sys/time.h>
    
    // SERIAL PORT CONFIGURATION
    
    /*Function for open a serial port*/
    
    int open_port(void){
    
    	int fd; // file description for the serial port
    
    	fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY );
    
    	if(fd == -1) // if open is unsucessful
    
    	{
    
    	 	perror("open_port: Unable to open /dev/ttyS0 - ");
    
    	}
    
    	else
    
    	{   
    
    	 	fcntl(fd, F_SETFL, 0);
    
    	}
    
    	return(fd);
    
    }
    
    /*Port configuration*/
    
    int configure_port(int fd , speed_t st)      {
    
    	struct termios port_settings;      // structure to store the port settings in
    
    	tcgetattr(fd, &port_settings);
    
    /*	cfsetispeed(&port_settings, st);    // set baud rates
    
    	cfsetospeed(&port_settings, st);
    
    	port_settings.c_cflag &= ~PARENB;    // set no parity, stop bits, data bits
    
    	port_settings.c_cflag &= ~CSTOPB;
    
    	port_settings.c_cflag &= ~CSIZE;
    	port_settings.c_cflag &= ~HUPCL;
    	port_settings.c_cflag &= ~CREAD;
    	//port_settings.c_cflag &= ~IGNPAR;
    	//port_settings.c_cflag &= ~CLOCAL;
    	//port_settings.c_cflag &= IGNPAR;
    	//port_settings.c_cflag &= ~PARMRK;
    	//port_settings.c_cflag &= ~INPCK;
    	//port_settings.c_cflag &= ~ISTRIP;
    	//port_settings.c_cflag &= ~INLCR;
    	//port_settings.c_cflag &= ~IGNCR;
    	port_settings.c_cflag &= ~ICRNL;
    	//port_settings.c_cflag &= ~IXON;
    	//port_settings.c_cflag &= ~IXOFF;
    	//port_settings.c_cflag &= ~IUCLC;
    	//port_settings.c_cflag &= ~IXANY;
    	//port_settings.c_cflag &= ~IMAXBEL;
    	//port_settings.c_cflag |= CS8;
    	port_settings.c_cc[VINTR] =(char)0;
    	port_settings.c_cc[VQUIT] =(char)0;
    	port_settings.c_cc[VKILL] =(char)0;
    	port_settings.c_cc[VERASE] =(char)0;
    	port_settings.c_cc[VEOF] =(char)0;
    	port_settings.c_cc[VEOL] =(char)0;
    	port_settings.c_cc[VEOL2] =(char)0;
    	port_settings.c_cc[VSWTC] =(char)0;
    	port_settings.c_cc[VSUSP] =(char)0;
    	port_settings.c_cc[VREPRINT] =(char)0;
    	port_settings.c_cc[VWERASE] =(char)0;
    	port_settings.c_cc[VMIN] =0;
    	port_settings.c_cc[VTIME] =0;
    	port_settings.c_cc[VLNEXT] =(char)0;
    */
    
    	//port_settings.c_cflag &= ICANON;	
    //port_settings.c_cflag |= (CLOCAL | CREAD);
    
    	//port_settings.c_lflag |= (ICANON | ECHO | ECHOE);
    
    	tcsetattr(fd, TCSANOW, &port_settings);    // apply the settings to the port
    
    	return(fd);
    
    }
    
    
    
    
    int main(void)
    
    {
    
    	int fd = open_port();
    
    	char buf[255];
    	char buf1[255];
    	char buf2[255];
    
    	configure_port(fd, 9600);
    	printf("Now the modem is going into command mode\n");
    
    	sleep(1);
    
    	write(fd,"+++",3);
    
    	sleep(1);
    int i=1;
    while ((buf[i]!='\r')&&(buf[i+1]!='\n')) {
    	read(fd,buf,1);	
    	printf(buf);
    i++;
    }
    	write(fd,"ATA\r\n",5);
    //	read(fd, buf, 255);
    
    //	printf(buf);
    	close(fd);
    }
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2006
    Posts
    16
    Rep Power
    0
    to make the point clear:

    if I read the output with minicom, it is:

    NO CARRIER
    OK

    if I read it with my program, it will read:

    <BLANK LINE HERE>
    <BLANK LINE HERE>
    NO CARRIER
    <BLANK LINE HERE>
    OK
    <BLANK LINE HERE>
  8. #5
  9. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,392
    Rep Power
    1871
    > int i=1;
    I think arrays start at 0, not 1

    > printf(buf);
    I think buff is full of garbage, did not have the first character written to. Where is the \0 to end the string?

    And I might add, an incredibly dumb way of using printf().
    http://en.wikipedia.org/wiki/Format_string_attack
    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
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2006
    Posts
    16
    Rep Power
    0
    Hi,
    i'm new to programming in general. unfortunately, the serial programming guides on the internet (everyone is pointing at 2) do not help me in solving the problem. the program works fine on cygwin under windows, but it doesn't really work on linux. even if i try to do a simple read (the latter code I attached) i can't. any help is greatly appreciated :)
  12. #7
  13. Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jun 2005
    Posts
    5,964
    Rep Power
    4852
    > int i=1;
    I think arrays start at 0, not 1
    Read your responses. He means he knows arrays start at 0, not 1.

    Your precise implementation will determine what happens at the output device when you have "\r\n" together.
    Write no code whose complexity leaves you wondering what the hell you did.
    Politically Incorrect DaWei on Pointers Grumpy on Exceptions
  14. #8
  15. Commie Mutant Traitor
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Jun 2004
    Location
    Alpharetta, GA
    Posts
    1,806
    Rep Power
    1570
    At the risk of arousing the ire of both the OP and the regulars here, I have take the trouble of re-arranging the code somewhat to eliminate redundancies a inconsistencies. I don't think that it has solved the actual problem, but it may make the whole somewhat easier to fix. as well as now compiling cleanly with the -Wall option set:
    C Code:
    #include <stdio.h>   // standard input / output functions
    #include <stdlib.h>  // general standard library functions
    #include <unistd.h>  // UNIX standard function definitions
    #include <fcntl.h>   // File control definitions
    #include <termios.h> // POSIX terminal control definitionss
     
    int open_port(void);
    int configure_port(int fd , speed_t st);
    int read_lines(int fd, char* buf, int lines);
     
    int main(int argc, char* argv[])
    {
       int fd = open_port();
       FILE *frate;
       char rate_info[255];
       int position;
     
       frate = fopen("rate.txt","r");
     
       if (frate == NULL)
       {
          printf("Error in file opening ");
          return(0);
       }
     
       fscanf(frate,"%s", rate_info);
       fclose(frate);
     
       char buf[255];
     
       printf("Now the modem is going into command mode\n");
     
       sleep(1);
       write(fd,"+++",3);
       sleep(1);
       position = read_lines(fd, buf, 3);   // read three lines of text from port
     
       if (0 >= position)
       {
          printf("\nPort closed unexpectedly after %d characters, exiting.\n",
                 -position);
          exit(-1);
       }
     
       write(fd,"ATA\r\n",5);
       sleep(1);
       position = read_lines(fd, buf + position, 3); // get next 3 lines
       if (0 >= position)
       {
          printf("\nPort closed unexpectedly after %d characters, exiting.\n",
                 -position);
          exit(-1);
       }
     
     
       close(fd);
     
       return 0;
    }
     
    /* read a set number of lines of text from the port */
    int read_lines(int fd, char* buf, int lines)
    {
       int count;
       int line, row = 0;
     
       for (line = 0; lines < lines; line++)
       {
          for (; buf[row] != '\n'; row++)
          {
             if (0 >= read(fd, (buf + row), 1))  // port closed for some reason
                return -count;
             else
             {
                putchar(buf[row]);
                count++;
             }
          }
       }
       return count;
    }
     
    /*Function to open a serial port*/
    int open_port(void)
    {
       int fd; // file description for the serial port
     
       fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NONBLOCK);
     
       if(fd == -1) // if open is unsucessful
       {
          perror("open_port: Unable to open /dev/ttyS0 - ");
       }
       else
       {
          fcntl(fd, F_SETFL, O_NONBLOCK);
       }
     
       return(fd);
    }
     
    /*Port configuration*/
    int configure_port(int fd , speed_t st)
    {
       struct termios port_settings;      // structure to store the port settings in
     
       tcgetattr(fd, &port_settings);
       cfsetispeed(&port_settings, st);    // set baud rates
       cfsetospeed(&port_settings, st);
     
       port_settings.c_cflag &= ~PARENB;    // set no parity, stop bits, data bits
       port_settings.c_cflag &= ~CSTOPB;
       port_settings.c_cflag &= ~CSIZE;
       port_settings.c_cflag |= CS8;
       //port_settings.c_cflag |= (CLOCAL | CREAD);
       port_settings.c_lflag |= (ICANON | ECHO | ECHOE);
     
       tcsetattr(fd, TCSANOW, &port_settings);    // apply the settings to the port
     
       return(fd);
    }
    Rev First Speaker Schol-R-LEA;2 JAM LCF ELF KoR KCO BiWM TGIF
    #define KINSEY (rand() % 7) λ Scheme is the Red Pill
    Scheme in Short Understanding the C/C++ Preprocessor
    Taming Python A Highly Opinionated Review of Programming Languages for the Novice, v1.1

    FOR SALE: One ShapeSystem 2300 CMD, extensively modified for human use. Includes s/w for anthro, transgender, sex-appeal enhance, & Gillian Anderson and Jason D. Poit clone forms. Some wear. $4500 obo. tverres@et.ins.gov
  16. #9
  17. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2010
    Posts
    1
    Rep Power
    0

    Question Serial C code working on Linux but not on Cygwin


    Well I have the opposite problem. My C code works fine in Linux (ubuntu) but it does not work under Cygwin. I looked under /dev/ and don't see any COM# at all. The same hardware (USB serial device + PC) works find under windows. Am I missing a driver for cygwin? Please help! Thanks!

IMN logo majestic logo threadwatch logo seochat tools logo