Cast problem / serial interface

M

MVennebusch

Hi,

I want to read/parse the binary output of a GPS receiver written to
the serial interface. The data packages start with a "$@".

The following program does read from the serial interface, but it does
not find the beginning of a data block. (I am very sure that the
binary data sent from the GPS receiver does contain the "$@"!). So
there must be an error in the if-statement. Do I have to cast either
"buf[0]" or the '$'-sign? What else could be wrong?

Thanks for your help!
Markus


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>

#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS0"
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0
#define TRUE 1

#define BLOCKSIZE 1

int main()
{
int fd;
struct termios oldtio,newtio;
char buf[BLOCKSIZE];

ssize_t res;

fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
if (fd <0) { printf("ERROR while opening MODEMDEVICE \n");
perror(MODEMDEVICE); return 0; }

tcgetattr(fd,&oldtio); /* save current port settings */

bzero(&newtio, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;

/* set input mode (non-canonical, no echo,...) */
newtio.c_lflag = 0;

newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
newtio.c_cc[VMIN] = 5; /* blocking read until 5 chars received
*/

tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);

while (1) {

res = read(fd, &buf, BLOCKSIZE);
buf[1]='\0';

printf("%c\n", buf[0]);
// Why does the following not work???
if (buf[0] == '$') { printf("Possible beginning of data!\n");
sleep(1); }
// read next byte and check for "@"...

}

tcsetattr(fd,TCSANOW,&oldtio);

return 0;

}
 
R

Richard Heathfield

(e-mail address removed) said:

#define BLOCKSIZE 1

1. Right, okay so far.
int main()
{
int fd;
struct termios oldtio,newtio;
char buf[BLOCKSIZE];

i.e. char buf[1], i.e. an array of 1 byte, whose index is 0.

buf[1]='\0';

Writing to buf[0] is legal, but writing to buf[1] is not, because buf[1]
doesn't exist.

I'm not saying that's your only problem, but it's definitely *a* problem.
 
V

vippstar

Hi,

I want to read/parse the binary output of a GPS receiver written to
the serial interface. The data packages start with a "$@".

The following program does read from the serial interface, but it does
not find the beginning of a data block. (I am very sure that the
binary data sent from the GPS receiver does contain the "$@"!). So
there must be an error in the if-statement. Do I have to cast either
"buf[0]" or the '$'-sign? What else could be wrong?
As the snippet that follows uses POSIX headers and functions, your
question(s) belong in another newsgroup, namely comp.unix.programmer.
comp.lang.c discusses ISO C and ISO C only.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>

#define BAUDRATE B38400
This doesn't seem valid..
#define MODEMDEVICE "/dev/ttyS0"
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0
#define TRUE 1 Rather annoying macros IMHO.
#define BLOCKSIZE 1
Since you won't change this (or else, your whole code would change as
seen bellow)
why not write a readbyte(sock, buf) function instead? (or just use
read with 1 as size)
int main()
{
int fd;
struct termios oldtio,newtio;
char buf[BLOCKSIZE];

ssize_t res;

fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
if (fd <0) { printf("ERROR while opening MODEMDEVICE \n");
perror(MODEMDEVICE); return 0; }

tcgetattr(fd,&oldtio); /* save current port settings */

bzero(&newtio, sizeof(newtio));
bzero marked as a legacy function from the open group base spec issue
6.
(available online at <http://www.opengroup.org/onlinepubs/009695399/>)
Use memset(&newtio, 0, sizeof newtio); instead, or the macro suggested
by open group.
#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
You have defined BAUDRATE as B38400, that would probably be a syntax
error.
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;

/* set input mode (non-canonical, no echo,...) */
newtio.c_lflag = 0;

newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
newtio.c_cc[VMIN] = 5; /* blocking read until 5 chars received
*/

tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);

while (1) {

res = read(fd, &buf, BLOCKSIZE);
Why don't you check the return value of read?
buf[1]='\0';
Why set it every time you run the loop?
printf("%c\n", buf[0]);
// Why does the following not work???
if (buf[0] == '$') { printf("Possible beginning of data!\n");
Possibly? that is not reliable at all. Have a size_t object that
counts the data that has been read.
if(buf[0] == '$' && count == 0) /* possibly beginning of data */
sleep(1); }
// read next byte and check for "@"...
Do you really want to sleep there?
It is very likely that you have not posted the code that doesn't
"work".
 
M

MVennebusch

Thanks a lot for your quick answers!
It was (as always) a stupid mistake: The baud rate was wrong, indeed.
Now everything works fine!

But thank you for the useful comments!

Markus
 
C

CBFalconer

I want to read/parse the binary output of a GPS receiver written
to the serial interface. The data packages start with a "$@".
Take a look at the thread "search a string in file handling in c"
and my answer of last Thursday, Feb. 14th.
 
K

Keith Thompson

I want to read/parse the binary output of a GPS receiver written to
the serial interface. The data packages start with a "$@".

The following program does read from the serial interface, but it does
not find the beginning of a data block. (I am very sure that the
binary data sent from the GPS receiver does contain the "$@"!). So
there must be an error in the if-statement. Do I have to cast either
"buf[0]" or the '$'-sign? What else could be wrong?
As the snippet that follows uses POSIX headers and functions, your
question(s) belong in another newsgroup, namely comp.unix.programmer.
comp.lang.c discusses ISO C and ISO C only.
Yup.

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>

#define BAUDRATE B38400
This doesn't seem valid..
[...]

I think B38400 is a macro defined in one of the POSIX-specific headers.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top