Re: RS485/COM2 Error in SBC84500 documentation
From: Frencia (jean.pierre.frencia_at_wanadoo.fr)
Date: 06/21/05
- Next message: Himanshu: "Re: Embedded Platform"
- Previous message: Floog: "re:Motorola MX.l DMA controller problem"
- In reply to: Floyd L. Davidson: "Re: RS485/COM2 Error in SBC84500 documentation"
- Next in thread: Grant Edwards: "Re: RS485/COM2 Error in SBC84500 documentation"
- Reply: Grant Edwards: "Re: RS485/COM2 Error in SBC84500 documentation"
- Reply: Floyd L. Davidson: "Re: RS485/COM2 Error in SBC84500 documentation"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Tue, 21 Jun 2005 20:33:49 +0200
Hi
Thanks for your comments a bit pedantic ;) but useful to learn. I think
there is a lack of material on serial port programming for newbies. Here is
the 2 useful link I have found:
- http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single
Serial-Programming-HOWTO.html
- http://www.easysw.com/~mike/serial/serial.html
It would be fine if you could post some others
J.P. Frencia
Floyd L. Davidson wrote:
> Frencia <jean.pierre.frencia@wanadoo.fr> wrote:
>>Hi
>>
>>There is an error in the SBC84500 documentation concerning RS485/COM2 pins
>>assignment.
>>The signal is between pin 1 (DATA-) and pin 2 (DATA+) instead of pin 1 and
>>pin 3 as stated page 29 of the documentation.
>>
>>I also have removed CRTSCTS flag when tuning the termios.
>>
>>Here is my OpenDevice routine (if it could be helpful for somebody else).
>
> Here's a *very* pedantic (but also very useful) commentary on your
> code.
>
>>int OpenDevice (char* device)
>>{
>> int fd;
>>
>> fd = open(device, O_RDWR | O_NOCTTY );
>> if(fd<=0) {
>
> That should be "if (fd < 0) {", because 0 is a valid fd.
>
>> fprintf(stderr, "Error opening %s\n", device);
>> exit(-1);
>
> The argument for exit() is an int, but its value is taken as an
> unsigned character. Hence, -1 is not -1, but 255.
>
> Useful arguments are in the range 0 to 255.
>
>> }
>> tcgetattr(fd,&oldtio); /* save current port settings */
>> tcgetattr(fd,&newtio); /* get current port settings */
>
> You could just as well save the second function call, and
> do
>
> newtio = oldtio;
>
> But at that point there is another problem. POSIX says that the
> above is the one and only correct way to initialize a termios
> structure. (Which rules out using something like memset() to
> clear it entirely.) But, that also means you *must* set each
> and every element of the structure to an appropriate value for
> your application, because whatever just happens to be in "oldtio"
> might not be compatible with your app. That sounds easy, but
> POSIX doesn't specify _everything_ that might be there! It says
> certain things must exist, but each implementation is allowed to
> add non-POSIX specified members to termios. So, for a portable
> program, it is *impossible* to know how to initialize termios!
>
> It happens that Linux has such an addition to termios, the
> c_line member, which is not POSIX, does not exist in any other
> OS, and if set to the wrong value will cause a port to appear
> to be dead.
>
> So you are left with, in my opinion, two options. One is to
> use something like this:
>
> #if __linux__
> #include <sys/ioctl.h> /* defines N_TTY */
> newtio.c_line = NTTY; /* or skip the header, and set it to 0 */
> #endif
>
> *and* make sure that you set each and every POSIX member of
> the termios structure.
>
> The other way, which is not POSIXly correct, is easier and
> more likely to always be right!
>
> memset(&newtio, 0, sizeof newtio);
>
>> newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
>> // BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD does NOT work
>
> You probably shouldn't put the BAUDRATE there either; and
> regardless of whether it is there or not, you should use
> cfsetispeed() and cfsetospeed() to set the bitrate.
>
>> newtio.c_cflag &= ~PARENB; /* no generation of parity bit */
>> newtio.c_cflag &= ~CSTOPB; /* 1 Stop bit */
>
> The above are unnecessary. You properly *set* (using '=') only
> some of the bits above, and all others are cleared. Clearing
> them again won't make the twice as cleared, eh? :-)
>
>> newtio.c_iflag &= ~INPCK; /* no input parity check */
>> newtio.c_iflag = IGNPAR;
>
> That doesn't make sense either. Just do the second line, and it
> will also do the first at the same time. I'm not sure what is
> implemented in the driver you are using, but commonly for the
> c_iflag on RS-232 ports one would also set IGNBRK.
>
>> newtio.c_oflag = 0;
>>
>> /* set input mode (non-canonical, no echo,...) */
>> newtio.c_lflag = 0;
>>
>> newtio.c_cc[VTIME] = 10;
>> newtio.c_cc[VMIN]= 0;
>
> Wow, that's a pretty hefty wait interval!
>
>> tcflush(fd, TCIFLUSH);
>
> You might want to change that to TCIOFLUSH, so that both input
> and output are flushed before continuing.
>
>> tcsetattr(fd,TCSANOW,&newtio);
>
> You should check this for an error. But also note that if it
> returns -1, that means *nothing* worked. And if anything at all
> was set as requested, it will return 0. That means most of it
> might be other than what you expect, and the error return won't
> indicate it. (The only way to know for sure, is obnoxious...
> you'd have to use tcgetattr() again, and compare what you get
> to the newtio struct, and even that isn't easy because the bitrate
> bits won't be the same and have to be compared separately from
> the rest of the struct.)
>
>> return(fd);
>
> There is no need to put parens around fd in the return
> statement, though it doesn't hurt anything. (I said it was a
> pedantic commentary... :-)
>
> return fd;
>
>>}
>
- Next message: Himanshu: "Re: Embedded Platform"
- Previous message: Floog: "re:Motorola MX.l DMA controller problem"
- In reply to: Floyd L. Davidson: "Re: RS485/COM2 Error in SBC84500 documentation"
- Next in thread: Grant Edwards: "Re: RS485/COM2 Error in SBC84500 documentation"
- Reply: Grant Edwards: "Re: RS485/COM2 Error in SBC84500 documentation"
- Reply: Floyd L. Davidson: "Re: RS485/COM2 Error in SBC84500 documentation"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]