I am working on a project where I have PIC devices on a RS485 half duplex (2 wire) network with a master slave protocol, where the master is a PC connected to an external RS232/485 converter. Data direction for the converter is controlled with the DTR signal on the PC com port.
I have made a DOS program handling this master/slave protocol without any problems (mainly because I am using a self-developed interrupt driver for the serial port).
I am now converting this program to Windows and since I haven't got the time (or the knowledge yet) to redevelop a serial port interface for Windows, I purchased the Commx Active X component from Green leaf software.
However, I can't get the half duplex RS485 communication to work properly. The main problem is that Commx has an event for TX buffer empty, but not for TX shift register empty in the UART. It seems that the event for the TX buffer empty is fired after the last Transmit Register (FIFO) Empty Interrupt from the UART when Commx hasn't got anything more to write to the TX FIFO (when the FIFO is ready to receive new data but the last byte is still in the TX shift register). Thus, using this event for controlling data direction of the RS232/485 converter switches the converter from transmitter to receiver a couple of bits into the last character of the TX string which means that it isn't read properly by my receiving devices on the network. I have used the technique to append a dummy character (0xff) after my last significant character to make sure the last significant character is seen by my network devices and got the communication to work. But since the information about when the TX shift register is empty is available in the PC UART (a bit in the line status register I think) I would prefer to use this by waiting for this bit to get set before I drop DTR to the converter when I get a TX buffer empty event.
Has anybody successfully got this to work? Are there anybody else using CommX with Visual C++?
The doc (helpfile) says that the port handle, accessible through CommX, is the very same handle returned from the CreateFile() Windows API function call used inside the PortCtl object. Can this handle be used to access registers from the UART directly?
Some things never change. This is exactly the problem that came up on
PICLIST last week, but from the other end of the link (the PIC).
One solution I know of is to use an RS485 board that supports automatic
turnaround. These boards watch the TX line. When it goes idle for a short
time they turn the line around.
Writing directly to the Windows COMM API isn't all that difficult.
Unfortunately, I'm afraid you'll run into very much the same problem at that
level.
And no, you _cannot_ access the UART directly. In fact the Win32 COMM API is
designed for device independence and can support many different UART
chips/intelligent multiport cards with appropriate drivers.
You _could_ write your own COMM driver, but this wouldn't be pretty.
Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
software)
> I am working on a project where I have PIC devices on a RS485 half duplex
(2
> wire) network with a master slave protocol, where the master is a PC
> connected to an external RS232/485 converter. Data direction for the
> converter is controlled with the DTR signal on the PC com port.
>
> I have made a DOS program handling this master/slave protocol without any
> problems (mainly because I am using a self-developed interrupt driver for
> the serial port).
>
> I am now converting this program to Windows and since I haven't got the
time
> (or the knowledge yet) to redevelop a serial port interface for Windows, I
> purchased the Commx Active X component from Green leaf software.
>
> However, I can't get the half duplex RS485 communication to work properly.
> The main problem is that Commx has an event for TX buffer empty, but not
for
> TX shift register empty in the UART.
This is a common problem with standard UART drivers on PCs. I don't see
what the Commx library is buying you here. You would get the same treatment
from the native Win32 calls, which is probably what the Commx library
accesses. Unfortunately, the transmitter empty information is not surfaced
to the Win32 layer either. You therefore have to customize the existing
device driver, or create a new that only does the things you need. This can
be done, but messing with OS internals is not something the average
programmer should try at home. There may be folks out there that provide
"enhanced" device drivers that include this feature, but I don't know of any
off hand. I have seen commercial products for other COMM devices, like the
paralell port, so it might be worth looking around bit. Sorry for the
unwelcome news.
This may not help you much, but I did something almost like this once. The
only difference is that the PC was embedded and not running any form of
Windows. This allowed direct access to the UART from assembler, which does
at least provide a bit indicating transmission is complete. Could the PC be
embedded where you can control the HW directly.
Another thought is to have the PC talk to a PIC via RS-232, then the PIC
drive the RS-485 on behalf of the PC. You could still use DTR to signal
that transmission from the PC will be over after the next pause, then have
the PIC do the actual turn around sequencing and timing.
For what it's worth I believe a lot depends on what the bus turnaround time
is. Some microcontroller to microcontroller apps use near instant turnaround
but sometimes delays of 100ms or more are added between recieving and
replying to give the host time to turn the port round. In our case it was
9ms. Easy for DOS but not Windows. Personally I strongly doubt it is
possible to switch the port reliably at application level as your program
might not even be active the instant the data goes out. When confronted with
this problem I specified:
1. A 'magic' interface for testing which senses the data going out and sets
the direction accordingly. Significantly the time delay before release was
less than a bit, so it was necessary to bias the bus to a '1' state to
prevent corruption. This oddity makes me wary of this method in finished
installations.
2. A standard interface requiring soft direction control, but with a device
driver supporting RS485 direction control. The one we used from Amplicon
supported both internal 485 and an external converter, the difference being
the different lines used to enable transmission.
I use a circuit I found in circuit cellar to do this for me. It requires
a max232, 555 timer and a RS485 chip. The circuit automatically puts the
RS485 chip into TX when a byte is being sent and then puts it into RX
when its finished, It makes comms under windows alot easier. I can scan
the circuit and email it to you if you like.
Regards
Stuart O'Reilly
>
> Hello,
>
> I am working on a project where I have PIC devices on a RS485 half duplex (2 wire) network with a master slave protocol, where the master is a PC connected to an external RS232/485 converter. Data direction for the converter is controlled with the DTR signal on the PC com port.
>
> I have made a DOS program handling this master/slave protocol without any problems (mainly because I am using a self-developed interrupt driver for the serial port).
>
> I am now converting this program to Windows and since I haven't got the time (or the knowledge yet) to redevelop a serial port interface for Windows, I purchased the Commx Active X component from Green leaf software.
>
> However, I can't get the half duplex RS485 communication to work properly. The main problem is that Commx has an event for TX buffer empty, but not for TX shift register empty in the UART. It seems that the event for the TX buffer empty is fired after the last Transmit Register (FIFO) Empty Interrupt from the UART when Commx hasn't got anything more to write to the TX FIFO (when the FIFO is ready to receive new data but the last byte is still in the TX shift register). Thus, using this event for controlling data direction of the RS232/485 converter switches the converter from transmitter to receiver a couple of bits into the last character of the TX string which means that it isn't read properly by my receiving devices on the network. I have used the technique to append a dummy character (0xff) after my last significant character to make sure the last significant character is seen by my network devices and got the communication to work. But since the information about when the TX
> shift register is empty is available in the PC UART (a bit in the line status register I think) I would prefer to use this by waiting for this bit to get set before I drop DTR to the converter when I get a TX buffer empty event.
>
> Has anybody successfully got this to work? Are there anybody else using CommX with Visual C++?
>
> The doc (helpfile) says that the port handle, accessible through CommX, is the very same handle returned from the CreateFile() Windows API function call used inside the PortCtl object. Can this handle be used to access registers from the UART directly?
>
> --
> http://www.piclist.com hint: The PICList is archived three different
> ways. See http://www.piclist.com/#archives for details.
> For what it's worth I believe a lot depends on what the bus turnaround
> time is. Some microcontroller to microcontroller apps use near instant
> turnaround but sometimes delays of 100ms or more are added between
> recieving and replying to give the host time to turn the port round.
> In our case it was 9ms. Easy for DOS but not Windows. Personally I
> strongly doubt it is possible to switch the port reliably at
> application level as your program might not even be active the instant
> the data goes out. When confronted with this problem I specified:
>
Right now I have about 10ms turnaround time, but I think I will
increase this time, reviewing the answers I have got so far.
> 1. A 'magic' interface for testing which senses the data going out and
> sets the direction accordingly. Significantly the time delay before
> release was less than a bit, so it was necessary to bias the bus to a
> '1' state to prevent corruption. This oddity makes me wary of this
> method in finished installations.
>
> 2. A standard interface requiring soft direction control, but with a
> device driver supporting RS485 direction control. The one we used from
> Amplicon supported both internal 485 and an external converter, the
> difference being the different lines used to enable transmission.
>
Interesting, I will look into this Amplicon device driver, thanks.
==============================
Ruben Jvnsson
AB Liros Elektronik
Box 9124, 200 39 Malmv, Sweden
TEL INT +46 40142078
FAX INT +46 40947388 rubenKILLspampp.sbbs.se
==============================
Thanks for Your replies and suggestions on this topic. I now know at
least two things I didn't before.
1. My problems hasn't got to do with using CommX from Greenleaf, I
would most likely get the same problem with other software drivers. I
have asked Greenleaf about this several times, but has not yet got a
meaningful reply.
2. I now understand why a lot of RS485 devices with master/slave
protocol uses full duplex.
==============================
Ruben Jvnsson
AB Liros Elektronik
Box 9124, 200 39 Malmv, Sweden
TEL INT +46 40142078
FAX INT +46 40947388 EraseMErubenspam_OUTTakeThisOuTpp.sbbs.se
==============================
Tony Kübek, Flintab AB
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
E-mail: @spam@tony.kubekKILLspamflintab.com
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
You can leave the rs-485 converter open both ways (don't turn off the receiver
when you send). Your program will receive the data it is sending on the
network, and you can test for the last byte sent. Once you've received it, you
know the tx register is empty. But since you're leaving both tx and rx open on
the line all the time anyway, it's not important to worry about switching it.
>
> Hello,
>
> I am working on a project where I have PIC devices on a RS485 half duplex (2 wire) network with a master slave protocol, where the master is a PC connected to an external RS232/485 converter. Data direction for the converter is controlled with the DTR signal on the PC com port.
>
> I have made a DOS program handling this master/slave protocol without any problems (mainly because I am using a self-developed interrupt driver for the serial port).
>
> I am now converting this program to Windows and since I haven't got the time (or the knowledge yet) to redevelop a serial port interface for Windows, I purchased the Commx Active X component from Green leaf software.
>
> However, I can't get the half duplex RS485 communication to work properly. The main problem is that Commx has an event for TX buffer empty, but not for TX shift register empty in the UART. It seems that the event for the TX buffer empty is fired after the last Transmit Register (FIFO) Empty Interrupt from the UART when Commx hasn't got anything more to write to the TX FIFO (when the FIFO is ready to receive new data but the last byte is still in the TX shift register). Thus, using this event for controlling data direction of the RS232/485 converter switches the converter from transmitter to receiver a couple of bits into the last character of the TX string which means that it isn't read properly by my receiving devices on the network. I have used the technique to append a dummy character (0xff) after my last significant character to make sure the last significant character is seen by my network devices and got the communication to work. But since the information about when the TX
> shift register is empty is a
>
> Has anybody successfully got this to work? Are there anybody else using CommX with Visual C++?
>
> The doc (helpfile) says that the port handle, accessible through CommX, is the very same handle returned from the CreateFile() Windows API function call used inside the PortCtl object. Can this handle be used to access registers from the UART directly?
>
> --
> http://www.piclist.com hint: The PICList is archived three different
> ways. See http://www.piclist.com/#archives for details.
>Yeah, but you still have to turn off your transmitter when you receive.
>That's the whole point off the 2-wire half-duplex link.
but after you receive the last character you know you transmitted, you know you
can turn off the transmitter. It gives you a one character turn around delay
maybe. It saves having to know when to turn on the receiver
Your turn around delay is 1 character, plus whatever delays are introduced
by the most-certainly-nowhere-like-realtime Windoze before dispatching your
program.
Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
software)
You are correct, of course. You shouldn't be using a non-realtime OS (windows,
in this case) to control a realtime system.
Ideally you would use a realtime controller to go between the windows computer
and the network to handle those issues. ie, a realtime <---> non-realtime
interface.
-Adam
Bob Ammerman wrote:
>
> Your turn around delay is 1 character, plus whatever delays are introduced
> by the most-certainly-nowhere-like-realtime Windoze before dispatching your
> program.
>
> Bob Ammerman
> RAm Systems
> (contract development of high performance, high function, low-level
> software)
>
> {Original Message removed}
perhaps try to find out if your protocol allows you to manipulate the tx
fifo (esp. turn it off). If yes, then do so. Now the TEMT signal will tell
you that there is at most one more byte to be sent, and you can be sure to
switch at the 'right' time if the last byte is an insignificant 0xFF.
Delay in software by 1 bit time or more after TEMT to allow the start
bit to go out w/o glitch. This is a hack, but it is a hack that worked for
me.
Well, now don't get me wrong. You _can_ use Windo(ws/ze) in a real time
environment. You just have to define your real-time requirements reasonably,
with an acceptable fallback when the timing isn't met.
For example, in the current case where we have to turn around and RS485 line
to pick up the reception the cost of a real-time failure will most likely be
a retransmit (and a collision on the RS485 bus). If that is acceptable (in
fact when N consecutive retries are acceptable) then you could use
Windo(ws/ze) in this environment.
You just have to know your limitations and consequences.
Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
software)
It doesn't seem to be necessary to turn off the fifo since it seems
that I get my TX buffer empty event fired, not when the last byte is
written to the fifo but when I get the last TEMP interrupt from the
UART after the last byte is written to the TX fifo, which means that
the fifo is already empty and the last byte is in the TX shift
register. I have come to this conclusion by looking at the signals on
a scope and saw that my switch signal is mostly released a couple of
bits into the last byte (never before, sometimes after).
I think I can ignore the fact that I can get a glitch in the start
bit of the last 0xff dummy byte, since my network devices also
ignores this. When it sees the carriage return, it ignores all
receiving characters until an initial delay (for guaranteed minimum
turnaround time) has been done and the received string has been
interpreted and executed.
I initially used only the TX buffer empty event to switch the
converter, but I noticed that sometimes the RX trigger event that got
fired from my echoed command string on TX came before the TX buffer
empty event, so now I use whichever comes first. I don't want to
relay on the RX trigger event only, since I want to use the software
for both half and full duplex RS485, and for standard RS232 also.
I also retry every unsuccessfull command at least 3 times before I
report a failure. This seems to be working pretty well on my machine
(550 MHz PIII), I am a bit concerned on how it will work on slower
machines though. I think that I must increase my minimum turnaround
time to perhaps 50ms, instead of the 10ms I have now.
> Hi,
>
> perhaps try to find out if your protocol allows you to manipulate the
> tx fifo (esp. turn it off). If yes, then do so. Now the TEMT signal
> will tell you that there is at most one more byte to be sent, and you
> can be sure to switch at the 'right' time if the last byte is an
> insignificant 0xFF. Delay in software by 1 bit time or more after TEMT
> to allow the start bit to go out w/o glitch. This is a hack, but it is
> a hack that worked for me.
>
> Peter
>
> --
> http://www.piclist.com hint: To leave the PICList
> piclist-unsubscribe-requestEraseME.....mitvma.mit.edu
==============================
Ruben Jvnsson
AB Liros Elektronik
Box 9124, 200 39 Malmv, Sweden
TEL INT +46 40142078
FAX INT +46 40947388 EraseMErubenpp.sbbs.se
==============================
-- http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]: PIC only [EE]: engineering [OT]: off topic [AD]: advertisements
> You are correct, of course. You shouldn't be using a non-realtime OS
(windows,
> in this case) to control a realtime system.
>
> Ideally you would use a realtime controller to go between the windows
computer
> and the network to handle those issues. ie, a realtime <---> non-realtime
> interface.
>
> -Adam
>
I've just completed a project were I wrote a PPI driver for a Siemes PLC (a
226).
My software worked on Win98 using the APIs and an external RS232-RS485
converter with predefined turn around delay of 1ms.
With this setup I had no communication problem (usually the PLC had delays
of 15ms, minimum).
The adventures I had with turn-around RS485 taught me to use strict packet
discipline on that kind of network. In other words I have large gaps (for
turning interfaces), even 100ms sometimes, I start all packets with two or
more SYN characters (or 0x5A5A or other such magic), where the receiver
always ignores these, I send a packet (Pascal string style, length first,
checksum at end), and pad it with a variable number of 0xFF.
I have never used this on a Pentium 500MHz, but it worked on PIC, all
Intel PC systems (not Windows) from 33MHz to 100MHz and on some old Z80
and 8051 hardware, including with non-standard RS485 drivers.
The most important feature I have added imho is the ping feature which
makes life so much easier for me. All the programs I wrote for this have a
mode where the remote interface becomes a repeater and sends the control
string back. By sending a cunning control string and having the ping
feature you can tune your timing. Since the receiver will return what it
sees as a packet (ignoring length and crc) if you send a packet containing
successive numbers in each byte, the receiver will return one that starts
with the first bvyte it saw 'good'. Thus you know which way to tune your
delay/turnaround/whatever. F.ex. if you send:
SYN SYN 0 1 2 3 4 5 6 7 ... 255 0xFF 0xFF
and get:
3 4 5 6 7 ... 254
then you can already draw conclusions about which end is lagging and
approximately how much (in this example the receiver is about 10
characters 'slow' turning and the Tx cuts it short by about 4 characters).
NOTE that you must send the characters with pacing in this mode so the
effective delays are larger than shown. Pacing means that in this test
mode you send one character, then wait 10 bit times, then send another ...
You can automate this process if you have access to the firmware at both
ends (I had, but I hard-wired the timing values into the code when I was
finished).
I have never tried to mix software for RS485 and RS232. Besides UART setup
they are worlds apart imho (ok, I borrow setup code from one for the
other etc).