Problem to read and write on a serial port

C

collinm

hi

i send a command to a led display, the led display is suppose to return
me some character

i write a string on a serial port

void ledDisplayExist()
{
char msg[]={'\0', '\0', '\0', '\0', '\0', '\1', 'Z', '0', '0',
'\2', 'H', 'B', '\4' };
int length = sizeof(msg);
writeopen(msg, length);
readopen();
}

int writeopen(char msg[], int size)
{
printf("write\n");
int fd1;
int wr;
fd1 = open(ledisplay, O_RDWR | O_NOCTTY | O_NDELAY );
if (fd1 == -1)
{
fprintf(stderr, " %s open_port: Unable to open %s\n",
strerror(errno), ledisplay);
}
else
{
fcntl(fd1, F_SETFL, 0);

wr=write(fd1, msg, size);
if (wr < 0)
fputs("write() of n bytes failed!\n", stderr);
close(fd1);
}
return (fd1);
}

after i read on the serial port:

int readopen()
{
printf("read\n");
int fd1;
int rd;
char *buff=NULL;
fd1 = open(ledisplay, O_RDONLY | O_NOCTTY | O_NDELAY );
if (fd1 == -1)
{
fprintf(stderr, "%s open_port: Unable to open %s\n",
strerror(errno), ledisplay);
}
else
{
fcntl(fd1, F_SETFL, 0);
printf(" Port 1 has been sucessfully opened and %d is the file
descriptor\n",fd1);
rd=read(fd1, buff, 30);
printf(" Bytes recieved are %d \n",rd);
close(fd1);
}
return (fd1);
}

the string returned by the led display is suppose to be something like:
<nul><nul><nul><nul><nul><soh>"000"<stx>"G234.3432"<etx>"0237<eot>

the lenght of the returned string is under 30 character...

when i run the prog, the prog display

port série utilisé: /dev/ttyS2
connection au led display
write
read
Port 1 has been sucessfully opened and 3 is the file descriptor

i wait a few second and nothing more is display.... i kill the program

any idea why i don't read correctly on the serial port?
 
W

Walter Roberson

i write a string on a serial port

Anything to do with serial ports is implimentation specific; you
could likely get better and faster advice in a newsgroup such as
comp.programming.embedded .

int writeopen(char msg[], int size)
{
return (fd1);

Note that by that point fd1 is either not been opened properly, or
has already been closed. fd1 is thus only of academic interest and should
not be treated as being anything particularily meaningful .
after i read on the serial port:
int readopen()
{
printf("read\n");
int fd1;
int rd;
char *buff=NULL;
fd1 = open(ledisplay, O_RDONLY | O_NOCTTY | O_NDELAY );

The behaviour of open() is not part of the C standard. If you are
using some other standard, then you should at least say which standards
we should interpret the code under.

For example, your description indicates you are opening /dev/ttyS2 .
That appears to be a serial port. On some systems, the fact that you
opened the port as ttyS<something> would have a different result
than if you opened it as (say) ttyd<something>. You have not said which
OS you are using, so we cannot research to find out what, if any,
special properties might be associated with opening the serial port
through that version of its name.
fcntl(fd1, F_SETFL, 0);

fcntl() is not part of the C standard either. If you are using the
POSIX.1-1990 fcntl() then using the F_SETFL open with a value of 0
clears all the flags associated with the file descriptor -- including
the O_NDELAY flag that you carefully specified in the open() statement.
The read() statement is thus (assuming POSIX.1 once more) going to become
a blocking read. We don't know how that serial port or leddisplay operate
so we don't have information on the expected behaviour upon opening.

In one of your earlier code iterations in this newsgroup, your code did
not close the device between the write() and the read(). That might or might
not be crucial to the behaviour.
printf(" Port 1 has been sucessfully opened and %d is the file
descriptor\n",fd1);
rd=read(fd1, buff, 30);

You could add debugging there such as using a select() with a timeout,
or you could loop reading 1 character at a time and seeing how many
characters you actually get.

any idea why i don't read correctly on the serial port?

As I indicated in an earlier posting, one thing that is missing
from your code is any code to set the port to a known good state,
such as by specifying the serial port speed, number of stop bits,
whether the I/O is "raw" or "cooked". For example, it could be
(hypothetically) that the problem you are having is that the <stx>
in the input stream is being interpreted as indicating that one
or more characters in the input buffer should be flushed, which
would leave you with less than 30 characters in the buffer but you
always wait for exactly 30. Then too there is the issue that the
default behaviour on most serial ports that are not specifically
set to "raw" mode is to ignore NUL bytes, which again would lead
to a short input count.
 
J

Jens.Toerring

collinm said:
i send a command to a led display, the led display is suppose to return
me some character
after i read on the serial port:
int readopen()
{
printf("read\n");
int fd1;
int rd;
char *buff=NULL;
fd1 = open(ledisplay, O_RDONLY | O_NOCTTY | O_NDELAY );
if (fd1 == -1)
{
fprintf(stderr, "%s open_port: Unable to open %s\n",
strerror(errno), ledisplay);
}
else
{
fcntl(fd1, F_SETFL, 0);
printf(" Port 1 has been sucessfully opened and %d is the file
descriptor\n",fd1);
rd=read(fd1, buff, 30);

Assuming that read() is meant to read a certain number of characters
into the memory pointed to by 'buff' (which I can't say for sure since
there's no read() function in standard C) then you make a mistake here,
'buff' is a pointer initialized to NULL and thus pointing to memory you
are never allowed to use (if it exists at all). You need to make 'buff'
an array of at least as many characters as you want to read or assign a
pointer to 'buff' that points to enough space (e.g. by using malloc()).
printf(" Bytes recieved are %d \n",rd);
close(fd1);
}
return (fd1);
}

From what you are writing it looks as if you might be on some kind of
UNIX system. Most of your questions then might be answered better in
a group that deals with programming under UNIX - lots of your code
uses non-standard extensions to C (all the functions open(), read(),
write(), close(), fcntl() are not part of C). If that is the case
you might benefit quite a lot by asking your questions in e.g.
comp.unix.programmer instead of here. There are several people who
have been dealing with serial port issues under UNIX for quite some
time, but they won't answer you're question here since it would be
off-topic (if they read comp.lang.c at all). And there are quite a
few problems involved with using the UNIX read() function correctly
(and especially when used for serial ports), but you won't find out
about it here but only in a group where read() has a well-defined
meaning.
Regards, Jens
 
C

collinm

Walter Roberson wrote:
Anything to do with serial ports is implimentation specific; you
could likely get better and faster advice in a newsgroup such as
comp.programming.embedded .

i begining a tread to this newsgroup

The behaviour of open() is not part of the C standard. If you are
using some other standard, then you should at least say which standards
we should interpret the code under.

For example, your description indicates you are opening /dev/ttyS2 .
That appears to be a serial port. On some systems, the fact that you
opened the port as ttyS<something> would have a different result
than if you opened it as (say) ttyd<something>. You have not said which
OS you are using, so we cannot research to find out what, if any,
special properties might be associated with opening the serial port
through that version of its name.

we use a sixnet Mini-VersaTRAK mIPm
http://www.sixnetio.com/html_f iles/products_and_groups/mipm_ vt.htm

this system use linux
fcntl() is not part of the C standard either. If you are using the
POSIX.1-1990 fcntl() then using the F_SETFL open with a value of 0
clears all the flags associated with the file descriptor -- including
the O_NDELAY flag that you carefully specified in the open() statement.
The read() statement is thus (assuming POSIX.1 once more) going to become
a blocking read. We don't know how that serial port or leddisplay operate
so we don't have information on the expected behaviour upon opening.

In one of your earlier code iterations in this newsgroup, your code did
not close the device between the write() and the read(). That might or might
not be crucial to the behaviour.


You could add debugging there such as using a select() with a timeout,
or you could loop reading 1 character at a time and seeing how many
characters you actually get.



As I indicated in an earlier posting, one thing that is missing
from your code is any code to set the port to a known good state,
such as by specifying the serial port speed, number of stop bits,
whether the I/O is "raw" or "cooked".

under bash:
~ # stty -a </dev/ttyS2
speed 9600 baud; rows 0; columns 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; start = ^Q; stop = ^S; susp = ^Z;
rprnt = ^R; werase = ^W; lnext = ^V; flush = ^U; min = 1; time = 0;
-parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl
ixon
-ixoff -iuclc -ixany -imaxbel
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0
bs0
vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop
-echoprt echoctl echoke

For example, it could be
(hypothetically) that the problem you are having is that the <stx>
in the input stream is being interpreted as indicating that one
or more characters in the input buffer should be flushed, which
would leave you with less than 30 characters in the buffer but you
always wait for exactly 30. Then too there is the issue that the
default behaviour on most serial ports that are not specifically
set to "raw" mode is to ignore NUL bytes, which again would lead
to a short input count.

with:

int readopen()
{
printf("read\n");
int fd1;
int rd;
char buff[255];
fd1 = open(ledisplay, O_RDWR | O_NOCTTY | FNDELAY );
if (fd1 == -1)
fprintf(stderr, "%s open_port: Unable to open %s\n",
strerror(errno), ledisplay);
else
{
fcntl(fd1, F_SETFL, FNDELAY);
rd=read(fd1, buff, 20);
printf(" Bytes recieved are %d \n",rd);
close(fd1);
}
return (fd1);
}

that return always return me: Bytes recieved are -1
 

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

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top