write() to /dev/ttyS0 has no effect

View: New views
3 Messages — Rating Filter:   Alert me  

write() to /dev/ttyS0 has no effect

by Borge :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

I'm writing some C code to control an external MCU over UART.
Everything works like a charm using TeraTerm or cat >>/dev/ttyS0. gcc
is 3.4.4. In a different program (not inserted), I am able to use
read() to get information from the MCU. Cygwin is "CYGWIN_NT-5.1
1.5.25(0.156/4/2) 2008-06-12 19:34".

However, it seems like no information is sent when I call write(). Are
there any known bugs with Cygwin when it comes to this?

I have inserted my code below. Thanks for any help!

"f" is a valid command to the MCU. The MCU will disregard any \r or
\n. I have tried hitting the enter button, not just 'a' on the
keyboard.


Borge


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <string.h>
       
#define BAUDRATE B115200
#define MODEMDEVICE "/dev/ttyS0"
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0
#define TRUE 1
       

FILE *keyboard;
int status;

main()
{
        int fd,c, res;
        struct termios oldtio,newtio;

        keyboard = fopen("/dev/tty", "r");      //open the terminal keyboard
        if (!keyboard)
        {
                fprintf(stderr, "Unable to open /dev/tty\n");
                exit(1);
        }

        fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
        if (fd <0) {perror(MODEMDEVICE); exit(-1); }

        fcntl(fd, F_SETFL, 0); // Needed???
       
        tcgetattr(fd,&oldtio); // Save current port settings

        // Non-canonical init.
        bzero(&newtio, sizeof(newtio));
        newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
        newtio.c_iflag = IGNPAR;
        newtio.c_oflag = 0;
        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)
        {
                status = getc(stdin);
                if (status == 'a') {
                        char outbuf[] = "f";
                        printf("%s", outbuf); // This printout is ok
                        write(fd, outbuf, 1); // This doesn't seem to get sent down the uart!
                }

        }
        tcsetattr(fd,TCSANOW,&oldtio); // Restore port settings
}

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


Re: write() to /dev/ttyS0 has no effect

by Bugzilla from matthias.andree@gmx.de :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Børge Strand-Bergesen schrieb:

> I'm writing some C code to control an external MCU over UART.
> Everything works like a charm using TeraTerm or cat >>/dev/ttyS0. gcc
> is 3.4.4. In a different program (not inserted), I am able to use
> read() to get information from the MCU. Cygwin is "CYGWIN_NT-5.1
> 1.5.25(0.156/4/2) 2008-06-12 19:34".
>
> However, it seems like no information is sent when I call write(). Are
> there any known bugs with Cygwin when it comes to this?

"Works for me", albeit with MSP430 behind a FTDI USB/serial converter and
without CRTSCTS and lower bit rate (57600).

> I have inserted my code below. Thanks for any help!
>
> "f" is a valid command to the MCU. The MCU will disregard any \r or
> \n. I have tried hitting the enter button, not just 'a' on the
> keyboard.
>
>
> Borge
>
>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <termios.h>
> #include <stdio.h>
> #include <string.h>
>
> #define BAUDRATE B115200
> #define MODEMDEVICE "/dev/ttyS0"
> #define _POSIX_SOURCE 1 /* POSIX compliant source */

This must be before the first #include.

> #define FALSE 0
> #define TRUE 1
>
>
> FILE *keyboard;
> int status;
>
> main()
> {
> int fd,c, res;
> struct termios oldtio,newtio;
>
> keyboard = fopen("/dev/tty", "r");      //open the terminal keyboard

What's that good for? You're not using that.

> if (!keyboard)
> {
> fprintf(stderr, "Unable to open /dev/tty\n");
> exit(1);
> }
>
> fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
> if (fd <0) {perror(MODEMDEVICE); exit(-1); }
>
> fcntl(fd, F_SETFL, 0); // Needed???

Not needed.

>
> tcgetattr(fd,&oldtio); // Save current port settings
>
> // Non-canonical init.
> bzero(&newtio, sizeof(newtio));

bzero() isn't standard. Use memset(), sample below.

> newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

Does the µC support CRTSCTS? If not, that's why it fails.

Also, BAUDRATE may not fit into speed_t according to /usr/include/sys/termios.h,
so you're losing the "extended baud rate" flag and are actually programming 75
Baud instead of 115200. Use cfsetXspeed (X is i or o) to manipulate newtio
instead, example (in C++):

                struct termios newtio;
                /* configure serial interface to 57600 8N1 no-canonical */
                memset(&newtio, 0, sizeof(newtio));
                newtio.c_cflag = CS8 | CLOCAL | CREAD;
                newtio.c_iflag = 0;
                newtio.c_oflag = 0;
                newtio.c_lflag = 0;
                newtio.c_cc[VTIME] = 0;
                newtio.c_cc[VMIN] = 1;  /* at least 1 characters */
                if (cfsetispeed(&newtio, B57600)) throw("cfsetispeed");
                if (cfsetospeed(&newtio, B57600)) throw("cfsetospeed");
                if (tcflush(fd, TCIFLUSH)) throw("tcflush");
                if (tcsetattr(fd, TCSANOW, &newtio)) throw("tcsetattr");


> newtio.c_iflag = IGNPAR;
> newtio.c_oflag = 0;
> 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)
> {
> status = getc(stdin);
> if (status == 'a') {
> char outbuf[] = "f";
> printf("%s", outbuf); // This printout is ok
> write(fd, outbuf, 1); // This doesn't seem to get sent down the uart!
> }
>
> }

You're apparently not reading from the serial line. Is that intentional?

> tcsetattr(fd,TCSANOW,&oldtio); // Restore port settings

This is unreached (dead) code.

> }

HTH

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


Re: write() to /dev/ttyS0 has no effect

by Borge :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Matthias,

vielen Dank!

It works now. Your questions were mostly about unrelated code that
somehow survived as I stripped things down to make the example.
Removing CRTSCTS did the trick.

I see that you are using non-canonical reads. Do you know if canonical
works on Cygwin? In my finished program I will indeed be reading input
from the UART. But "res = read(fd,inbuf,255);" returns on several
occations when it contents are not terminated by \n, \r or 0. As you
probably see from my code, I have copied the Serial HOWTO code.


Børge


On Thu, Oct 29, 2009 at 10:59, Matthias Andree <matthias.andree@...> wrote:

> Børge Strand-Bergesen schrieb:
>
>> I'm writing some C code to control an external MCU over UART.
>> Everything works like a charm using TeraTerm or cat >>/dev/ttyS0. gcc
>> is 3.4.4. In a different program (not inserted), I am able to use
>> read() to get information from the MCU. Cygwin is "CYGWIN_NT-5.1
>> 1.5.25(0.156/4/2) 2008-06-12 19:34".
>>
>> However, it seems like no information is sent when I call write(). Are
>> there any known bugs with Cygwin when it comes to this?
>
> "Works for me", albeit with MSP430 behind a FTDI USB/serial converter and
> without CRTSCTS and lower bit rate (57600).
>
>> I have inserted my code below. Thanks for any help!
>>
>> "f" is a valid command to the MCU. The MCU will disregard any \r or
>> \n. I have tried hitting the enter button, not just 'a' on the
>> keyboard.
>>
>>
>> Borge
>>
>>
>> #include <sys/types.h>
>> #include <sys/stat.h>
>> #include <fcntl.h>
>> #include <termios.h>
>> #include <stdio.h>
>> #include <string.h>
>>
>> #define BAUDRATE B115200
>> #define MODEMDEVICE "/dev/ttyS0"
>> #define _POSIX_SOURCE 1 /* POSIX compliant source */
>
> This must be before the first #include.
>
>> #define FALSE 0
>> #define TRUE 1
>>
>>
>> FILE *keyboard;
>> int status;
>>
>> main()
>> {
>>       int fd,c, res;
>>       struct termios oldtio,newtio;
>>
>>       keyboard = fopen("/dev/tty", "r");      //open the terminal keyboard
>
> What's that good for? You're not using that.
>
>>       if (!keyboard)
>>       {
>>               fprintf(stderr, "Unable to open /dev/tty\n");
>>               exit(1);
>>       }
>>
>>       fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
>>       if (fd <0) {perror(MODEMDEVICE); exit(-1); }
>>
>>       fcntl(fd, F_SETFL, 0); // Needed???
>
> Not needed.
>
>>
>>       tcgetattr(fd,&oldtio);                                  // Save current port settings
>>
>>       // Non-canonical init.
>>       bzero(&newtio, sizeof(newtio));
>
> bzero() isn't standard. Use memset(), sample below.
>
>>       newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
>
> Does the µC support CRTSCTS? If not, that's why it fails.
>
> Also, BAUDRATE may not fit into speed_t according to /usr/include/sys/termios.h,
> so you're losing the "extended baud rate" flag and are actually programming 75
> Baud instead of 115200. Use cfsetXspeed (X is i or o) to manipulate newtio
> instead, example (in C++):
>
>                struct termios newtio;
>                /* configure serial interface to 57600 8N1 no-canonical */
>                memset(&newtio, 0, sizeof(newtio));
>                newtio.c_cflag = CS8 | CLOCAL | CREAD;
>                newtio.c_iflag = 0;
>                newtio.c_oflag = 0;
>                newtio.c_lflag = 0;
>                newtio.c_cc[VTIME] = 0;
>                newtio.c_cc[VMIN] = 1;  /* at least 1 characters */
>                if (cfsetispeed(&newtio, B57600)) throw("cfsetispeed");
>                if (cfsetospeed(&newtio, B57600)) throw("cfsetospeed");
>                if (tcflush(fd, TCIFLUSH)) throw("tcflush");
>                if (tcsetattr(fd, TCSANOW, &newtio)) throw("tcsetattr");
>
>
>>       newtio.c_iflag = IGNPAR;
>>       newtio.c_oflag = 0;
>>       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)
>>       {
>>               status = getc(stdin);
>>               if (status == 'a') {
>>                       char outbuf[] = "f";
>>                       printf("%s", outbuf);                   // This printout is ok
>>                       write(fd, outbuf, 1);                   // This doesn't seem to get sent down the uart!
>>               }
>>
>>       }
>
> You're apparently not reading from the serial line. Is that intentional?
>
>>       tcsetattr(fd,TCSANOW,&oldtio);                  // Restore port settings
>
> This is unreached (dead) code.
>
>> }
>
> HTH
>
> --
> Problem reports:       http://cygwin.com/problems.html
> FAQ:                   http://cygwin.com/faq/
> Documentation:         http://cygwin.com/docs.html
> Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
>
>

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple