Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8577801
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 11, 20262026-06-11T20:14:28+00:00 2026-06-11T20:14:28+00:00

I have been tasked with the implementation of the ModBus protocol over a RS485

  • 0

I have been tasked with the implementation of the ModBus protocol over a RS485 2-wire system. (Actually it’s three wires, A/B and GND).
ModBus is not the point though, but the step before that…simple I/O over the interface.

I am using the FTDI USB-RS485 converter to connect a Linux host (not interchangeable) to a Windows host (interchangeable with another Linux host, though I’d like to avoid that)

The encoding is supposed to be 19200, 8, n, 1.
But it just doesn’t seem to work.

I don’t have the exact code handy, but on Linux I am doing this:

 int fd = open("/dev/ttyS3", O_RDWR | O_CTTY);
 if(fd == -1) return "Error while opening the port";

Next, I configure the port.

struct termios tty;

tcgetattr(fd, &tty);

cfsetispeed(&tty, B19200);
cfsetospeed(&tty, B19200);

tty.c_cflag  = CS8;              //Empties the cflags and sets the character width.
tty.c_cflag |= (CLOCAL | CREAD); //Sets 'recommended' options.

tty.c_lflag  = 0;
tty.c_iflag  = 0;
tty.c_oflag  = 0;

tcgetattr(fd, TCSANOW, &tty);

Parity and Flow Control are currently not planned, since the final result will connect to a low level board, where I need to take care of the signals myself. Furthermore there aren’t any wires, which would allow ‘unfettered communication’. (After all I don’t want an XON/XOFF character to limit the byte range I can transmit)

All of these function go through properly and the data is set.

On Windows, I open the serial port like this:

DCB SP;
HANDLE hSerial = CreateFile("COM6", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if(hSerial == INVALID_HANDLE_VALUE) return "Error while opening the port";
GetCommState(hSerial, &SP);

Parity is disabled, as well as flow control. Byte size is set to 8.

Edit:
Since it has been asked, here is my code for the baudrate on Windows (from memory)
SP.DCBlength= sizeof(SP);
SP.BaudRate = 19200;
SP.Parity = NOPARITY;
SP.StopBits = ONESTOPBIT;
SetCommState(hSerial, &SP);

Again, all of these functions run flawlessly.

Now, for the test case that’s giving me a major headache.

On the Linux host, I create a byte buffer of 256 bytes size.
This buffer is filled with the character values from 0-255…and then sent over the wire with write.
At the same time, the other side is waiting with ‘ReadFile’ for data to arrive.

With this configuration, for both the ‘other Linux host’, as well as for the Windows host, 256 Bytes arrive…however it’s NOT the numbers from 0-255, but something 00 06 etc.

I can get the Linuxhost to work, when I’m setting all members of the termios structure to 0 before setting the options I actually want. I’m guessing, it’s because of the control characters…however if I do that, the Windows host either receives only 4 of 256 bytes.

As I said, unfortunately I don’t have the code handy. If anyone has any idea from what point I could tackle this, I’d be very grateful. I will post more code, once I have access to it again.

How I’m implementing the read operation:

DWORD nBytes = 0;
char Buffer[256], *ptr = Buffer;
int Rem = 256;

while(Rem) {
    ReadFile(hSerial, ptr, Rem, &nBytes, 0);
    Rem -= nBytes;
    ptr += nBytes;
}

//Evaluate Buffer

To be noted, I did set the timeouts, but can’t remember the exact values.

Edit: Since I now have access to my work place again, here’s the actual (current) code.

const char *InitCOM(const char *TTY) {
    struct termios tty;
    hSerial = open(TTY, O_RDWR | O_NOCTTY | O_NDELAY);
    if(hSerial == -1) return "Opening of the port failed";
    fcntl(hSerial, F_SETFL, 0);
    if(tcgetattr(hSerial, &tty) != 0) return "Getting the parameters failed.";
    if(cfsetispeed(&tty, B19200) != 0 || cfsetospeed(&tty, B19200) != 0) return "Setting the baud rate failed.";


    //CFlags
    //Note: I am full aware, that there's an '=', and that it makes the '&=' obsolete, but they're in there for the sake of completeness.
    tty.c_cflag  = (tty.c_cflag & ~CSIZE) | CS8;    //8-bit characters
    tty.c_cflag |= (CLOCAL | CREAD);und erlaubt 'Lesen'.
    tty.c_cflag &= ~(PARENB | PARODD);          
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CRTSCTS;                    

    //Input Flags
    tty.c_iflag     &= ~IGNBRK;             
    tty.c_iflag &= ~(IXON | IXOFF | IXANY);         

    //Local Flags
    tty.c_lflag  = 0;                   

    //Output Flags
    tty.c_oflag  = 0;

    //Control-Characters
    tty.c_cc[VMIN]   = 0;
    tty.c_cc[VTIME]  = 5;
    if(tcsetattr(hSerial, TCSAFLUSH, &tty) != 0) return "Setting the new parameters failed";
return NULL;

}

As for the actual sending/receiving code:

int main(int argc, char* argv[]) {
    #if defined FOR_PC
        const char *err = InitCOM("/dev/ttyUSB0");
    #else
        const char *err = InitCOM("/dev/ttyS3");
    #endif

    if(err) printf("Error while initalizing: %s ErrNum: %d\n", err, errno);
    else {
    /*unsigned char C[256];    //Original code with the array
    int nBytes;
    #ifdef FOR_PC
        int Rem = 256, ReqCount = 0;
        unsigned char *ptr = C;
        while(Rem > 0) {    
            fd_set fds;
            FD_ZERO(&fds);
            FD_SET(hSerial, &fds);
            select(hSerial+1, &fds, NULL, NULL, NULL);
            nBytes = read(hSerial, ptr, Rem);
            if(nBytes > 0) {
                Rem -= nBytes;
                ptr += nBytes;
                ++ReqCount;
            }
        }
        printf("Number of received Bytes: %d in %d sends.\n\n", 256 - Rem, ReqCount);
        for(int i = 0; i < 256; ++i) {
            printf("%02X ", C[i]);
            if((i%32) == 31) printf("\n");
        }
    #else
        for(int i = 0; i < 256; ++i) C[i] = i;
        nBytes = write(hSerial, C, 256);
        printf("\nWritten Bytes: %d\n", nBytes);
    #endif*/

    //Single-Byte Code
    unsigned char C = 0x55;
    #ifdef FOR_PC
        while(true) {   //Keeps listening
            fd_set fds;
            FD_ZERO(&fds);
            FD_SET(hSerial, &fds);
            select(hSerial+1, &fds, NULL, NULL, NULL);
            read(hSerial, &C, 1);
            printf("Received value 0x%02X\n", C);
        }
    #else
        write(hSerial, &C, 1);  //Sends one byte
    #endif
    close(hSerial);
}
return 0;

}

As for the Oscilloscope: I’ve tested both directions with sending. Both did their job quite admirably.

The signal of 0x55 is a constant Up/Down at the length of 50 microseconds (as it should, so setting the baud rate is no problem either).

So is there anything in my ‘receive’ code I’m doing wrong? Is the ‘select’ wrong?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-11T20:14:29+00:00Added an answer on June 11, 2026 at 8:14 pm
    1. Are you also setting the proper baud rate on the Windows side?
    2. Use an oscilloscope to check the actual data present on the wire(s). Debugging serial communications is what oscilloscopes were invented for. Almost. 🙂
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have been tasked with maintaining a legacy unmanaged c++ system. I do not
I have been tasked with coming up with a solution where I am not
I have been tasked with researching and implementing data warehousing for our ERP system
I have been tasked with building a new system that models a virtual filesystem.
I have been tasked with updating a old project that I did not write.
I have been tasked with creating a binary search over a list of words,
I have been tasked with converting some scripts referencing an Informix database to be
I have been tasked with porting a large Java codebase to the Android platform.
I have been tasked with refactoring some components that used xmlbeans to now make
I have been tasked to develop an interactive website using java & mysql: using

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.