Solved

serial access in linux

Posted on 2002-07-17
9
297 Views
Last Modified: 2006-11-17
I've looked over previous quesitons regarding serial port access through linux, but didn't totally understand what was the best/easiest way to program on the ports.  I want to read in through COM1 and read/write through COM2.  I see open("/dev/ttyS0", O_RDWR).  I understand the first arguement, but I don't understand what the declared constansts are and through which library I'm supposed to include to access them.  Also, when I do have the read only port open, it will have to wait for data 24/7.  I don't know the best way to do that (is there a boolean that is changed on the event of buffer status change?) or even how to do that with the read() write() functions.  
0
Comment
Question by:Socr420
  • 2
  • 2
  • 2
  • +2
9 Comments
 
LVL 4

Expert Comment

by:Robson
ID: 7161671
Have a look at: http://www.tldp.org/HOWTO/Serial-Programming-HOWTO/index.html.
There's nothing wrong with waiting for data 24/7. The kernel puts your program to sleep so it doesn't consume CPU power until some datta arrives. If you want your program to do other things while waiting for data, you may use:

* multiple processes or multiple threads
* non-blocking read/write
* select or poll system calls

I suggest you to read some general UNIX programming book before to learn about all these techniques and decide which one is most suitable for you.

Robson.
0
 

Author Comment

by:Socr420
ID: 7161801
I've been to that site already.  I couldn't properly read in data and display it to screen.  Here is some code I'm trying to use to just display something caught from the serial port.
#include <stdio.h>


int main() {
        int fd;
        char inputString[20];
        char temp;
        int i;
        //inputString=(char *)malloc(sizeof(char)*120);
        inputString[19]='\0';
        printf("opening first comport\n");
        if((fd=open("/dev/ttyS0", 2))<0) exit(-1);
        read(fd, inputString, 19);
        printf("******\n");
        for(i=0; i<20; i++) {
                printf("%c", *(inputString+i));
        }
        printf("******\n");
        //how would I write to the port? write(fd, "a", 1)??
        printf("program was activated, and now closing");
        close(fd);
        return;
}
Sometimes I won't get anything, and at other times I'll get complete garbage.  I know what the data being sent in looks like, and it is nothing like what I receive. Hope you can help.  Thanks
0
 
LVL 4

Accepted Solution

by:
Robson earned 100 total points
ID: 7162615
I think you should have a closer look at your serial port settings: parity, speed, flow control and suchlike. Manual for 'stty' command will tell you more. What is this device that you read from? What serial parameters does it operate at? AND DON'T FORGET TO CHECK ALL SYSTEM CALLS RESULTS! The garbage you mentioned could be random data from inptutString, when read failed, but you won't know that unless you check read() result.

0
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 

Expert Comment

by:kugan
ID: 7163942
Try This code , O_RDWR is basically a no defined in the header file, using a no 2 as you have done is not a good practice, because even if the no is wrong the compiler want give any error , but you will get run time error which is hard to debug

#include <stdio.h>
#include <fcntl.h>
int
main ()
{
  int fd;
  char *inputString;
  char temp;
  int i, error;

  inputString = (char *) malloc (sizeof (char) * 120);

  printf ("opening first comport\n");

  if ((fd = open ("/dev/ttyS0", O_RDWR)) < 0)
    {
      perror ("Opening");
      exit (-1);
    }

  if ((error = read (fd, inputString, 19)) < 0)
    {
      perror ("Reading ");
      exit (-2);
    }

  printf ("******\n");
  for (i = 0; i < 20; i++)
    {
      printf ("%c", *(inputString + i));
    }

  printf ("******\n");
  //how would I write to the port? write(fd, "a", 1)??
  if ((error = read (fd, inputString, 19) < 0))
    {
      perror ("Reading");
      exit (-3);
    }

  printf ("program was activated, and now closing");
  close (fd);

  return 1;
}
0
 

Author Comment

by:Socr420
ID: 7165537
I tried that code, but I seem to get locked up at the reading part.  It just sits there, and doesn't give any error.  I know there's input coming in because I connected a Tripmate GPS antenna to it.  I know every second the word "ASTRAL" is sent in at 4800 baud.  If I send the word "ASTRAL" back to it, it'll start sending all sorts of other data as well.  But I don't think I'm even sending correctly.  Is the cread option supposed to be on?  When I type "stty -F /dev/ttyS0" I see -cread is on, along with the other two defaults.
0
 

Expert Comment

by:kugan
ID: 7166121
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>

#define USE_NO_FLOW 0
#define USE_FLOW_CTRL 1


void
fd_setup (int fd, int speed, int flow)
{
  struct termios t;


  if (fd < 0)
    {
      perror ("fd_setup");
      exit (-1);
    }

  if (tcgetattr (fd, &t) < 0)
    {
      perror ("tcgetattr");
      exit (-1);
    }

  cfmakeraw (&t);

  t.c_cflag &= ~CBAUD;
  t.c_cflag |= speed| CS8 | CLOCAL;
  t.c_oflag = 0;                /* turn off output processing */
  t.c_lflag = 0;                /* no local modes */

  if (flow)
    t.c_cflag |= CRTSCTS;
  else
    t.c_cflag &= ~CRTSCTS;

  if (tcsetattr (fd, TCSANOW, &t) < 0)
    {
      perror ("fd_setup : tcsetattr");
      exit (1);
    }
  return 1;
}

int
main ()
{
  int fd;
  char *inputString;
  char temp;
  int i, error;

  inputString = (char *) malloc (sizeof (char) * 120);

  printf ("opening first comport\n");

  if ((fd = open ("/dev/ttyS0", O_RDWR)) < 0)
    {
      perror ("Opening");
      exit (-1);
    }

  fd_setup(fd,B4800,USE_FLOW_CTRL);

  if ((error = read (fd, inputString, 19)) < 0)
    {
      perror ("Reading ");
      exit (-2);
    }

  printf ("******\n");
  for (i = 0; i < 20; i++)
    {
      printf ("%c", *(inputString + i));
    }



  printf ("program was activated, and now closing");
  close (fd);

  return 1;
}

by default if you open the /dev/ttyS0 the data will not be read until the input stream not terminated as far as i remember. and default baud is 9600 baud.

you first try " cat /dev/ttyS0" to see if you are getting the data and then set the termios structure properly and try, check baudtrate ,folwcontrol etc

I dont have a serial cable :-) to test it here

0
 

Expert Comment

by:RonaldMundell
ID: 7167518
Hi

If you look under X you would see a section for documentation. Under there you would find 2 doc's containing how to write serial comms. this explains excactly what you need to do, where to select what Comms Port, etc... If this does not help, then EMAIL me and I will forward you the POSIX Serial Porgramming Manuel (an electronic copy). If I could upload it now, I would.

Ronald
0
 
LVL 20

Expert Comment

by:jmcg
ID: 9925610
No comment has been added lately, so it's time to clean up this TA.
I will leave the following recommendation for this question in the Cleanup topic area:

Accept: Robson {http:#7162615}

Please leave any comments here within the next seven days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

jmcg
EE Cleanup Volunteer
0

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Have you ever been frustrated by having to click seven times in order to retrieve a small bit of information from the web, always the same seven clicks, scrolling down and down until you reach your target? When you know the benefits of the command l…
The purpose of this article is to fix the unknown display problem in Linux Mint operating system. After installing the OS if you see Display monitor is not recognized then we can install "MESA" utilities to fix this problem or we can install additio…
This Micro Tutorial hows how you can integrate  Mac OSX to a Windows Active Directory Domain. Apple has made it easy to allow users to bind their macs to a windows domain with relative ease. The following video show how to bind OSX Mavericks to …
This tutorial gives a high-level tour of the interface of Marketo (a marketing automation tool to help businesses track and engage prospective customers and drive them to purchase). You will see the main areas including Marketing Activities, Design …

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question