LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Serial Port (https://www.linuxquestions.org/questions/programming-9/serial-port-401713/)

myrmidon 01-10-2006 02:17 PM

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;

}


Wim Sturkenboom 01-11-2006 11:36 PM

// something went wrong during the posting :(

Wim Sturkenboom 01-12-2006 12:02 AM

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


All times are GMT -5. The time now is 04:15 PM.