LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 01-10-2006, 03:17 PM   #1
myrmidon
Member
 
Registered: May 2005
Distribution: redhat 9 , fedora 5,6,7,DSL,Debian 3, mandrake 9.2 , knoppix 3.8, red hat 7.3
Posts: 38

Rep: Reputation: 15
Serial Port


Hello everyone, i'm writing a small c program, but i have stucked .

I have connected a small device on serial port, when i send a "9G" command to a device he's respond is "9G12,22;".
This perfectly works in minicom.
Parameters:
9600
8N1
NO HARDWARE FLOW CONTROL
NO SOFTWARE FLOW CONTROL

/dev/ttyS0


/dev/ttS0 is accessible,
because i did
chmod a+rw /dev/ttyS0

The same response i'm trying to achieve with my code, but i got no response I think there is an error in serial port parameters settings in code. Please HEEELP:


Code:

 #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 */


#include <stdio.h>


int open_port(void)
 {

  int fd=open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
   if(fd<0)
    {
      printf("Unable to open port\n");
    }

   return fd;


 }


/* ************************************* Setting parameters for serial port **************************************/



void set_parameters(int fd)
{


  struct termios options;

   fcntl(fd, F_SETFL, FNDELAY);             /* Configure port reading */


   tcgetattr(fd, &options);        /* Get the current options for the port */
   cfsetispeed(&options, B9600);                 /* Set the baud rates to 9600 */
   cfsetospeed(&options, B9600);

                                     /* Enable the receiver and set local mode */
    options.c_cflag |= (CLOCAL | CREAD);



    options.c_cflag &= ~PARENB;  /* Mask character size to 8 bits, no parity */
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |=  CS8;


    options.c_cflag &= ~CRTSCTS;          /* Disable hardware flow control */


    options.c_lflag &= ~(ICANON | ECHO | ISIG); /* RAW mode */




					/* Set the new options for the port */
    tcsetattr(fd, TCSANOW, &options);







}


/********************************* main **********************************************************************************/

int main(void)
{


   int fd,n;
   char buf[8];

   fd=open_port();


   set_parameters(fd);

   n=write(fd,"9G",3);

   if(n!=3)
    printf("Write to port failed!\n");


   read(fd,buf,8) ;

   printf("Read from serial:%s",buf);



   close(fd) ;



  return 0;

}
 
Old 01-12-2006, 12:36 AM   #2
Wim Sturkenboom
Senior Member
 
Registered: Jan 2005
Location: Roodepoort, South Africa
Distribution: Slackware 10.1/10.2/12, Ubuntu 12.04, Crunchbang Statler
Posts: 3,786

Rep: Reputation: 282Reputation: 282Reputation: 282
// something went wrong during the posting

Last edited by Wim Sturkenboom; 01-12-2006 at 01:04 AM.
 
Old 01-12-2006, 01:02 AM   #3
Wim Sturkenboom
Senior Member
 
Registered: Jan 2005
Location: Roodepoort, South Africa
Distribution: Slackware 10.1/10.2/12, Ubuntu 12.04, Crunchbang Statler
Posts: 3,786

Rep: Reputation: 282Reputation: 282Reputation: 282
First thing I notice is that what you send in minicom is not the same as what you send in your program.
In minicom, you only send 2 characters (or 3 or 4 including a CR and/or LF). In your program however you send 2 and a string terminator. I think that your device needs a CR and/or LF to see the end of the command, so I would change
Code:
n=write(fd,"9G",3);
to one of the following
Code:
n=write(fd,"9G\n",3);
n=write(fd,"9G\r",3);
n=write(fd,"9G\r\n",4);
n=write(fd,"9G\n\r",4);
Further some advice for debugging:
If your PC has 2 serial ports, you can connect them, run minicom on the one and your program on the other.
If you don't have 2 serial ports, you can use pseudo terminals. Start minicom as below and change /dev/ttyS0 in your program to /dev/ttyp0.
minicom -o -p /dev/ptyp0

Both allow you to check in minicom what you're sending and send replies back and check what your program is reading.

Info about pseudo terminals can be found on http://www.tldp.org/HOWTO/Text-Terminal-HOWTO-6.html

Below my code for a serial port setup. It also check if some of the parameters are set after a tcsetattr.
Code:
#define RS232PARAM (ird->comms.rs232)
/******************************************************************
 * NAME:      open_rs232
 * FUNCTION:  open a comm-port
 *
 * IN:        pointer to irdinfo
 * OUT:       none
 * RETURN:    file descriptor on success
 *            RC_IRD_xxx      on error
 *
 * Note:      only bails out on error
 *            calling routine must handle the errors
******************************************************************/
int open_rs232(sIRD *ird)
{

// com-port setup variables
struct termios newtio,vertio;

  // open the comport
//  ird->fd=open(RS232PARAM.port,O_RDWR|O_NOCTTY);
  ird->fd=open(RS232PARAM.port,O_RDWR);
  if(ird->fd<0)
    return RC_IRD_OPEN;

  memset(&newtio,0,sizeof(newtio));
  cfmakeraw(&newtio);

  newtio.c_cflag&=~CSIZE;
  newtio.c_cflag|=(RS232PARAM.br|
                   RS232PARAM.dbits|
                   RS232PARAM.sbits|
                   RS232PARAM.par|
                   CLOCAL|CREAD);
  newtio.c_iflag|=INPCK;
//  newtio.c_oflag=0;

//  newtio.c_lflag=0;
  newtio.c_cc[VTIME]=0;
  newtio.c_cc[VMIN]=1;     // trigger after 1 char

  tcflush(ird->fd,TCIFLUSH);
  tcsetattr(ird->fd,TCSANOW,&newtio);

  // verify
  tcgetattr(ird->fd,&vertio);
//  if(memcmp(&newtio,&vertio,sizeof(struct termios)))
  if(newtio.c_cflag!=vertio.c_cflag ||
     newtio.c_iflag!=vertio.c_iflag ||
     newtio.c_oflag!=vertio.c_oflag ||
     newtio.c_lflag!=vertio.c_lflag ||
     newtio.c_cc[VTIME]!=vertio.c_cc[VTIME] ||
     newtio.c_cc[VMIN]!=vertio.c_cc[VMIN])
  {
    close(ird->fd);
    ird->fd=-1;
    return RC_IRD_VERIFY;
  }


  return ird->fd;
}
And last, just in case you need it, serial programming howto

Last edited by Wim Sturkenboom; 01-12-2006 at 01:05 AM.
 
  


Reply

Tags
programming, rs232, serial port, tty


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
linux serial port to router console port connection? frankie_fix Linux - General 3 02-26-2007 10:32 PM
Using serial port card(PCMCIA) with IPAQ running Linux, can't find ttyS0 port d2army Linux - Laptop and Netbook 0 11-12-2005 09:07 PM
Using an USB port as a standard DB9 Serial Port Lsteele Linux - Newbie 1 10-22-2005 10:48 AM
serial port vasanthraghavan Linux - Hardware 2 02-05-2005 12:55 PM
Where's my serial port??? bad_andy Mandriva 4 01-01-2005 09:18 PM


All times are GMT -5. The time now is 10:45 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration