Like Tree3Likes
  • 1 Post By Elkvis
  • 1 Post By stahta01
  • 1 Post By stahta01

Write to serial port

This is a discussion on Write to serial port within the C++ Programming forums, part of the General Programming Boards category; Hello, I am trying to write to device connected via a serial port. It uses 8 data bits, 1 stop ...

  1. #1
    Registered User
    Join Date
    Nov 2007
    Posts
    23

    Write to serial port

    Hello,

    I am trying to write to device connected via a serial port. It uses 8 data bits, 1 stop bit, even parity and a communication rate of 2400bps. I am developing in Linux.

    I need to send message 0x80007F23FF.

    But "it doesn't work" (I know that's vague, but I don't know how to check what's wrong - for example, what message was received (and if it was received). I just don't get the desired output (which would be to turn a light on on the device).

    Below is the relevant code I am using.

    Thanks in advance

    Code:
    int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
    fcntl(fd, F_SETFL, 0);
    
    // Set options for the serial port
    struct termios options;
    tcgetattr(fd, &options);
    
    // Set the baud rate to 2400
    cfsetispeed(&options, B2400);
    cfsetospeed(&options, B2400);
    
    // Set even parity checking
    options.c_cflag |= PARENB;
    options.c_cflag &= ~PARODD;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    options.c_iflag |= (INPCK | ISTRIP);
    
    // Enable the receiver and set local mode
    options.c_cflag |= (CLOCAL | CREAD);
    
    // Choose raw input
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | IEXTEN | ISIG);
    
    // Choose BRKINT and ICRNL options
    options.c_iflag &= ~(BRKINT | ICRNL | IMAXBEL);
    
    // Choose raw output
    options.c_oflag &= ~(OPOST | ONLCR);
    
    // Set the new options for the port
    tcsetattr(fd, TCSANOW, &options);
    
    // Try to send a message
    unsigned char msg[5] = {0x80, 0x00, 0x7F, 0x23, 0xFF};
    write(fd, &msg, 8);

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    2,402
    is it possible you're sending the bytes in reverse order?
    stahta01 likes this.

  3. #3
    Registered User
    Join Date
    May 2009
    Posts
    2,570
    Quote Originally Posted by Elkvis View Post
    is it possible you're sending the bytes in reverse order?
    I will agree with "Elkvis"; try sending one byte at a time. Note: I also wonder why you are telling the write function to send 3 bytes of garbage data.
    (8-5=3)

    Tim S.
    "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the Universe is winning." Rick Cook

  4. #4
    Registered User
    Join Date
    Nov 2007
    Posts
    23
    I got it, I hadn't set the c_cc[VTIME] and c_cc[VMIN] parameters correctly. I was sending the bytes in the correct order - and the 3 extra bytes was due to my distraction (I was sending a 8 bytes message before, and forgot to change that). Adding the following code solved it.

    Code:
    //Set the minimum number of characters to read
    options.c_cc[VMIN] = 60;
    //Set time to wait for data (tenths of seconds)
    options.c_cc[VTIME] = 1;
    However, now I have another problem. After I use the write call, I get the desired result (light turns on), but after that pretty much all read calls get wrong results. Occasionally it will read a correct parameter, but otherwise it will be wrong. I thought it might be because of the ECHO and ECHOE parameters, but I turned them off and that didn't solve it.
    Last edited by sombrancelha; 05-30-2012 at 12:14 PM.

  5. #5
    Registered User
    Join Date
    May 2010
    Posts
    2,752
    Post the code showing how you are trying to do multiple reads/writes.

    Jim

  6. #6
    Registered User
    Join Date
    May 2009
    Posts
    2,570
    What flow control is being used? (Hardware, XON/OFF or other)

    Tim S.
    "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the Universe is winning." Rick Cook

  7. #7
    Registered User
    Join Date
    Nov 2007
    Posts
    23
    I don't use any flow control.

    This is what I am doing:

    Code:
    char aux[8];
    unsigned char readRequest[5] = {0x80, 0x00, 0x7F, 0x6F, 0xFF};
    while (1) 
    {   
        write(fd, &readRequest, sizeof (readRequest));
        read(fd, aux, 8); 
        for (int i = 0; i < 8; i++)
            printf("%x ", aux[i]);
        printf("\n");
        sleep(2);
    }
    After I looked more carefully, I realized I'm not getting such weird results afterall. The result I am expecting is
    Code:
    80 00 22 60 00 0B 78 7F
    But I am getting
    Code:
    00 00 22 60 00 0B 78 7F
    Notice that the difference is in the most significant bit on the first and the last byte (it should be 1 and it is 0). By the device's design, only those bytes can have a MSB=1 (and it should always be 1).

  8. #8
    Registered User
    Join Date
    May 2009
    Posts
    2,570
    Read the meaning of ISTRIP

    Tim S.
    sombrancelha likes this.
    "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the Universe is winning." Rick Cook

  9. #9
    Registered User
    Join Date
    Nov 2007
    Posts
    23
    Thanks!

    I used CuteCom and saw that it got the communication working nicely, so I saw what options it used (with stty -a -F /dev/ttyS0) and set them accordingly. What I miss-setting were INPCK, ISTRIP and IXON.

    Just one more thing. I am using the same write/read/printf as before, and I am now getting this output:
    Code:
    ffffff80 0 22 60 0 b 71 ffffffff
    instead of
    Code:
    80 00 22 60 00 0b 71 ff
    Is that just a printing problem (wrong %x configuration) or am I still getting the wrong data?

  10. #10
    Registered User
    Join Date
    May 2009
    Posts
    2,570
    %0x will fix the 0 instead of 00.
    The ff might be XON/XOFF or something else.

    I have no idea what the XON/XOFF character is; the low level is supposed to stop it.
    But, till you tell me the flow control you are using, I can NOT say that is valid in your case.

    Tim S.
    "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the Universe is winning." Rick Cook

  11. #11
    Registered User
    Join Date
    Nov 2007
    Posts
    23
    %0x still outputted 0 instead of 00

    Regarding flow control: I don't use any hardware flow control, and I haven't set any software flow control either (maybe there's something - from the OS -, but I'm not aware of it and I don't know how to check). I tried different combinations of IXON and IXOFF, but it made no difference.

    EDIT: What I find weird is that aux[i] is a char, so byte-size - how can it print ffffff80?
    Last edited by sombrancelha; 05-31-2012 at 12:47 PM.

  12. #12
    Registered User
    Join Date
    May 2009
    Posts
    2,570
    Try "%hx " instead it should then only do 4 nibbles.
    Per printf - C++ Reference

    Might try "%02x" also.

    I am far from a printf/scanf expert.

    Tim S.
    Last edited by stahta01; 05-31-2012 at 01:18 PM.
    "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the Universe is winning." Rick Cook

  13. #13
    Registered User
    Join Date
    Nov 2007
    Posts
    23
    %02x did the trick for the 0, but I'm still intrigued on why 0x80 get's printed ffffff80 - is that just a printing problem or is there something deeper? If it's just printing I don't care, as I will perform some calculations on them and convert to decimal.

    Thanks for all the help!

  14. #14
    Registered User
    Join Date
    May 2009
    Posts
    2,570
    Guess: "char aux[8];" needs to be unsigned char instead of [signed] char.
    It is likely implicit cast to signed int from signed char.

    Tim S.
    sombrancelha likes this.
    "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the Universe is winning." Rick Cook

  15. #15
    Registered User
    Join Date
    Nov 2007
    Posts
    23
    It worked! Thanks a lot!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Serial port read/write problem
    By ojaro in forum C Programming
    Replies: 5
    Last Post: 06-25-2010, 08:26 AM
  2. Serial Port
    By samuelmoneill in forum Windows Programming
    Replies: 8
    Last Post: 04-14-2009, 03:53 PM
  3. Serial Port help
    By wiseasssed in forum C Programming
    Replies: 2
    Last Post: 03-17-2006, 01:44 AM
  4. read from and write to serial port
    By wazilian in forum Networking/Device Communication
    Replies: 3
    Last Post: 04-25-2004, 08:22 AM
  5. serial port??
    By SuperNewbie in forum Windows Programming
    Replies: 2
    Last Post: 12-11-2003, 10:09 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21