views:

799

answers:

3

Hi,

In my program I read from the serial device (Linux, 8N1) without any problem. But in the case I want to write a single bit, I get nothing out on the interface. I assume that my serial output settings are wrong. But there aren't that many ways how to set c_oflag...

My code:

#define TTYDEVICE "/dev/ttyS0"
#define BAUDRATE B9600

int openSerialDevice(const char* devTTY, struct termios oldTio) {
//----< Open serial device >----------------------------------
int fileDescriptor;
// fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY);
//fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY /*| OPOST*/);
if (fileDescriptor == -1) {
 perror("Error while opening serial interface occurred!");
 return -99;
}

// set new parameters to the serial device
struct termios newtio;
bzero(&newtio, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

// set to 8N1
newtio.c_cflag &= ~PARENB;
newtio.c_cflag &= ~CSTOPB;
newtio.c_cflag &= ~CSIZE;
newtio.c_cflag |= CS8;

newtio.c_iflag = IGNPAR;

// output mode to
//newtio.c_oflag = 0;
newtio.c_oflag |= OPOST;

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

newtio.c_cc[VTIME] = 10; /* inter-character timer 1 sec */
newtio.c_cc[VMIN] = 0; /* blocking read disabled  */

tcflush(fileDescriptor, TCIFLUSH);
if (tcsetattr(fileDescriptor, TCSANOW, &newtio)) {
 perror("could not set the serial settings!");
 return -99;
}

//----< / Open serial device >----------------------------------
return fileDescriptor;
}

int ACK[1] = { 6 };

int main() {
// old termios to restablish
struct termios oldTIO;
// filedescriptor
int fd;

fd = openSerialDevice(TTYDEVICE, oldTIO);

if ((fd == -1) | (fd == -99)) {
 perror("Could not open TTY-Device. Exit on failure!");
 return EXIT_FAILURE;
}

write(fd, ACK, 1);  // Problem !! 


     return 0:
}

Now, if I use

screen /dev/ttyS1 9600 8n1

to verify what's coming out on /dev/ttyS0. I can't see anything. Same if I sniff with Docklight 1.8.

Any suggestions? thanks

+1  A: 

How do you verify nothing is coming out ?

You can try to drop the RTSCTS, and try again. Infact, if you want minimal interference from the tty layer, you should set your terminal to raw, using this :

cfmakeraw(&newtio);
shodanex
agreed. RTSCTS means hardware handshake, which is normally not used for 9600n81. This only works if the lines are also triggered by the counter part. Connecting RTS and CTS in hardware should also make the same program work, or connect it with a proper (null-modem) cable to another pc, and remember to configure RTS/CTS handshake there too.
Adriaan
+1  A: 

You're giving write() the data argument of ACK, which is a pointer to int. This is probably not what you mean. Depending on the endianness of the computer you're on, this means write() will "see" a buffer containing the chars { 6, 0, 0, 0 } (little-endian) or { 0, 0, 0, 6 } (big-endian). This assumes that sizeof (int) == 4 is true, adjust for other sizes as needed, the problem remains.

You should very probably make the buffer unsigned char instead. Also, if you had made the call like this:

int wrote = write(fd, ACK, sizeof ACK);
printf("Wrote %d bytes\n", wrote);

You would have gotten direct feedback. You should test something like this, to see that the write actually succeeds.

unwind
A: 

The activated Hardware-Flow-Control (CRTSCTS) was the reason why write() blocked and finally nothing has appeared on the serial output.

thanks!

Code snap which works:

int openSerialDevice(const char* devTTY, struct termios oldTio) {

    //----< Open serial device >----------------------------------
    int fileDescriptor;
    // fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
    fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY);
    //fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY /*| OPOST*/);
    if (fileDescriptor == -1) {
     perror("Error while opening serial interface occurred!");
     return -99;
    }

    // set new parameters to the serial device
    struct termios newtio;

    fcntl(fileDescriptor, F_SETFL, 0);
    // set everything to 0
    bzero(&newtio, sizeof(newtio));

    // again set everything to 0
    bzero(&newtio, sizeof(newtio));

    newtio.c_cflag |= BAUDRATE; // Set Baudrate first time
    newtio.c_cflag |= CLOCAL; // Local line - do not change "owner" of port
    newtio.c_cflag |= CREAD; // Enable receiver

    newtio.c_cflag &= ~ECHO; // Disable echoing of input characters
    newtio.c_cflag &= ~ECHOE;

    // set to 8N1
    newtio.c_cflag &= ~PARENB; // no parentybyte
    newtio.c_cflag &= ~CSTOPB; // 1 stop bit
    newtio.c_cflag &= ~CSIZE; // Mask the character size bits
    newtio.c_cflag |= CS8; // 8 data bits

    // output mode to
    newtio.c_oflag = 0;
    //newtio.c_oflag |= OPOST;


    // Set teh baudrate for sure
    cfsetispeed(&newtio, BAUDRATE);
    cfsetospeed(&newtio, BAUDRATE);

    newtio.c_cc[VTIME] = 10; /* inter-character timer  */
    newtio.c_cc[VMIN] = 0; /* blocking read until  */

    tcflush(fileDescriptor, TCIFLUSH); // flush pending data

    // set the new defined settings
    if (tcsetattr(fileDescriptor, TCSANOW, &newtio)) {
     perror("could not set the serial settings!");
     return -99;
    }

    //----< / Open serial device >----------------------------------
    return fileDescriptor;
}
Maus