RS485 interface

Hi I want to set the digi-me up to have a RS485 coms port, which I want to run modbus over. I can’t see in the netos7 how to define what gpio is used to control the direction of the RS485 chip. Are there any examples on how to do this. Searching the NetOS7 it looks as though RS485 is supported but for different platforms.

NETOS 7 uses a termios-like serial driver (see API reference device drivers->serial) so I would think you’d use the RTS pin and maybe the CRTSTOGGLE mode. Not sure how you’d set the turnaround timing delays though, never done RS-485 with an ME. Post back if you find a solution.

For those of you who may be interested in RS485.

I’m using netos72 with the DIGI connect ME.

The way I implemented RS485 is as follows


serialParameter_t serial_parameters[] =

int gpio_port = 0;
open (“/com/0”, serial_parameters[0].mode);

NAconfigureGPIOpin(gpio_port, NA_GPIO_OUTPUT_STATE, 0);

NAsetGPIOpin(gpio_port, 0); // set RS485 control low
write(com0, test_str, sizeof(test_str) ); // tx data
ioctl(com0, TCDRAIN, (char *)&ioctl_data ); // wait till all data is drained from buffer and registers
NAsetGPIOpin(gpio_port, 1); // set RS485 control hi

serialParameter is taken out of the serial example provided with the newos projects.

The above code has a 0.5ms-1.5ms delay from end of serial transmission to changing the logic level. Which is ok for what I’m doing.

i changed the stdio to “/udpdb/0” so I could use the com port.

It seems to be working fine.

If there are any other ways of implementing this I would be interested to know.

In some cases I’ve used the RTS_TOGGLE serial option to enable the transmit buffer, which is fine if you never want to permanently enable it as a run-time configuration option.

So I adopted this useful tip - but found that at 9600 baud the tcdrain() function sometimes disabled RTS about 1-2msec prematurely, truncating the end of my message. I put in a tx_thread_relinquish(); after the call to tcdrain(), which seemed to sort it, albeit giving a wide variation in time to transmitter disable - 2 to 10msec (just about OK for my application).

I’m using Net+OS 7.1 - has anyone else had this problem with tcdrain()?

Incidentally, the ‘official’ RTS pin is all over the place during power up - suspect the bootloader needs a mod, but haven’t investigated yet.

Thank you all for the information that you posted here.

Chris Prause: I tried to implement the RS485 communication following your instructions that seemed very clear to me, but I get an error: ‘TCDRAIN’ undeclared.

I cannot find where that macro is defined. I cannot find any information about ioctl() function serial device specific commands.

Maybe the problem is that I am using NET+OS 7.3. Can anyone help me find some information about ioctl serial device request codes?

Thank you

I solved my problem using tcdrain() function, like steved, instead of ioctl() function. I find the same issue, that the function returns too early. I think the problem is that tcdrain() returns as soon as the last byte is put in the transmitting buffer and does not wait until it is transmitted. So the time between tcdrain() returns and the last byte is transmitted depends on transmission speed.

I solved it using a delay, but I would need to be sure that the thread is not preempted at this point or I have the risk of holding the control line in transmission state for too long and “not listen” to the start of the answer. Any suggestions?

With the ME9210, there’s now a hardware function that will properly encapsulate the Tx Data, with up to 2 bit times of setup and hold. However the standard driver doesn’t fully support this - I modified an equate in camry_serl.h to set the maximum time values.

So if you set CRTSTOGGLE, the transmitter disable via RTS is very predictable and quite fast.

The other problem is that a subsequent tcsetattr() call doesn’t fully cancel CRTSTOGGLE mode once set - you have to explicitly set the RTS pin as a simple output (assuming that you need RTS to be permanently in one state, as I did)