0

I'm trying to write some bytes to a serial port:

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <stdint.h>

int main()
{
    // Open serial port
    port_fd = open("/dev/ttyUSB0", O_RDWR);
    if (port_fd < 0)
    {
        printf("Error %i while opening serial port: %s\n", errno, strerror(errno));
    }
    
    // Get serial port configuration
    struct termios tty;
    if (tcgetattr(port_fd, &tty) != 0)
    {
        printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
    }

    // Edit serial port configuration
    tty.c_cflag &= ~PARENB;
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag |= CS8;
    tty.c_cflag &= ~CRTSCTS;
    tty.c_cflag |= CREAD | CLOCAL;
    tty.c_lflag &= ~ICANON;
    tty.c_lflag &= ~ECHO;
    tty.c_lflag &= ~ECHOE;
    tty.c_lflag &= ~ECHONL;
    tty.c_lflag &= ~ISIG;
    tty.c_iflag &= ~(IXON | IXOFF | IXANY);
    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);
    tty.c_oflag &= ~OPOST;
    tty.c_oflag &= ~ONLCR;
    tty.c_cc[VTIME] = 10;
    tty.c_cc[VMIN] = 0;
    cfsetispeed(&tty, B115200);
    cfsetospeed(&tty, B115200);

    // Set serial port configuration
    if (tcsetattr(port_fd, TCSANOW, &tty) != 0)
    {
        printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
    }

    uint8_t testMsg[] = {0xAA, 0xBB, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x77};
    write(port_fd, testMsg, sizeof(testMsg));
    
    return EXIT_SUCCESS;
}

In this case, the serial device that I am writing to detects the bytes "0xAA" and "0xBB" as the start of a message frame. It then detects the byte "0x77" as the end of a message frame.

For some reason, when I call write() using sizeof(testMsg), the serial device does not respond.

write(port_fd, testMsg, sizeof(testMsg));

However, when I increment the size_t value of the write() call, the serial device responds correctly:

write(port_fd, testMsg, sizeof(testMsg)+1)

Why is this happening? Is there a better way to fix this?


for(int i = 0; i < 100; i++)
{
    write(port_fd, testMsg, sizeof(testMsg));
    sleep(10);
}

Actually, when writing the bytes without iterating, the serial device will respond to every other message. Still unsure what is happening though.


For reference, the serial device has the following configuration:
Baud Rate: 115200
Data Bits: 8
Parity Bits: None
Stop Bits: 1

ewaddicor
  • 29
  • 2
  • 1
    What is CSB? Should that be CS8? – stark Aug 05 '23 at 02:37
  • 2
    Why are you not checking the return code from **write()** like the other syscalls in your program? – sawdust Aug 05 '23 at 03:04
  • Yes, it should be CS8. I edited it. – ewaddicor Aug 05 '23 at 03:10
  • When I check the return code from write() it returns the number of bytes that it wrote successfully. It writes 9 bytes for sizeof(testMsg) and 10 bytes for sizeof(testMsg) + 1 – ewaddicor Aug 05 '23 at 03:11
  • 2
    Sounds more like a problem with protocol decoding at the other end:( – Martin James Aug 05 '23 at 05:01
  • 3
    It just reeks of the rx state'machine failing to reset to 'expect start byte' immediately after handling the end byte, resulting in the start byte of the second message being ignored/discarded as a protocol error in itself and only then resetting the state to 'expect start byte'. That would cause every other message to be rejected and explain how sending an extra byte allows all messages to be recognised. – Martin James Aug 05 '23 at 05:07

0 Answers0