EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

RS485 enable and TCP/IP

Started by dpalu2 September 14, 2005
Hello,

I am using a RCM3000 and it is connected to six RS485 serial ports.
The RCM3000 is basically a router. It gets packets on TCP/IP and
sends them out the appropriate RS485 port and if it gets a response
it sends it back up using TCP/IP. So far everything is working great,
now I am trying to speed things up. I would like to eliminate the
below Dynamic C statements

if (serXwrUsed() < byte_count) //byte_count is some number I have been
// playing with to increase throughput
{
while((!(!serXwrUsed() && !BitRdPortI(SXSR, 2)))); //spin til all
// bytes transmitted
portXenableRX();
}

I would like to get rid of the while loop so that the program can do
other stuff, but I also want to immediately enable the receiver on
the RS485 port so I dont miss any incoming bytes. I will never
receiver any bytes on the RS485 side of things until I have
completely transmitted a packet out the RS485.

I have six sockets, one for each serial port. tcp_tick() is called at
the beginning of the 'superloop'. The 'byte_count' variable in the if
statement above is depending a lot on how long the call to tcp_tick()
takes.

In summary, I would like to minimize the time spent spinning waiting
for the RS485 to finish transmitting so that I can enable the
receiver, but I also need to handle TCP/IP in case there are requests
on other sockets or I need to send responses up from other RS485
ports. Am I missing something? Is there an easy way to do this? Will
I have to hack the RS232.LIB?

TIA

Draper



On Sep 14, 2005, at 12:42 PM, dpalu2 wrote:
> In summary, I would like to minimize the time spent spinning waiting
> for the RS485 to finish transmitting so that I can enable the
> receiver, but I also need to handle TCP/IP in case there are requests
> on other sockets or I need to send responses up from other RS485
> ports. Am I missing something? Is there an easy way to do this? Will
> I have to hack the RS232.LIB?

Automatically switching between transmit and receive mode on the RS485
bus would be very handy to me as well.

I just took a look at the Tx/Rx ISRs and RS232.LIB, and it looks like
it might actually be easy to accomplish. I'm using port D, and it
would appear that I can simply modify the dDisable and dEnable assembly
routines to turn the RS485 driver off and on accordingly.

Unfortunately, I don't have the hardware set up to try this. Draper,
perhaps you could give it a try and report back to the group with the
results.

--
Tom Collins - tom@tom@...
Certified Rabbit Semiconductor Consultant based in Napa, California
Info on the Sniffter, a rechargeable, hand-held Network Tester
powered by the RCM2210: http://sniffter.com/


Tom Collins wrote:
> On Sep 14, 2005, at 12:42 PM, dpalu2 wrote:
>> In summary, I would like to minimize the time spent spinning waiting
>> for the RS485 to finish transmitting so that I can enable the
>> receiver, but I also need to handle TCP/IP in case there are requests
>> on other sockets or I need to send responses up from other RS485
>> ports. Am I missing something? Is there an easy way to do this? Will
>> I have to hack the RS232.LIB?
>
> Automatically switching between transmit and receive mode on the
> RS485 bus would be very handy to me as well.
>
> I just took a look at the Tx/Rx ISRs and RS232.LIB, and it looks like
> it might actually be easy to accomplish. I'm using port D, and it
> would appear that I can simply modify the dDisable and dEnable
> assembly routines to turn the RS485 driver off and on accordingly.
>
> Unfortunately, I don't have the hardware set up to try this. Draper,
> perhaps you could give it a try and report back to the group with the
> results.

FYI to you guys, I have had some problems in the past with turning the line
around too quickly after the last bit gets shifted out. Terminating,
biasing, line length, etc. You guys have probably been around long enough
to know that, but just in case...


Is this a 2-wire or 4-wire configuration? If this is
4-wire, and there is only one master on each pair, its
relatively easy to do what you want.

--- dpalu2 <dpalu2@dpal...> wrote:

> Hello,
>
> I am using a RCM3000 and it is connected to six
> RS485 serial ports.
> The RCM3000 is basically a router. It gets packets
> on TCP/IP and
> sends them out the appropriate RS485 port and if it
> gets a response
> it sends it back up using TCP/IP. So far everything
> is working great,
> now I am trying to speed things up. I would like to
> eliminate the
> below Dynamic C statements
>
> if (serXwrUsed() < byte_count) //byte_count is some
> number I have been
> // playing with to
> increase throughput
> {
> while((!(!serXwrUsed() && !BitRdPortI(SXSR,
> 2)))); //spin til all
> //
> bytes transmitted
> portXenableRX();
> }
>
> I would like to get rid of the while loop so that
> the program can do
> other stuff, but I also want to immediately enable
> the receiver on
> the RS485 port so I dont miss any incoming bytes. I
> will never
> receiver any bytes on the RS485 side of things until
> I have
> completely transmitted a packet out the RS485.
>
> I have six sockets, one for each serial port.
> tcp_tick() is called at
> the beginning of the 'superloop'. The 'byte_count'
> variable in the if
> statement above is depending a lot on how long the
> call to tcp_tick()
> takes.
>
> In summary, I would like to minimize the time spent
> spinning waiting
> for the RS485 to finish transmitting so that I can
> enable the
> receiver, but I also need to handle TCP/IP in case
> there are requests
> on other sockets or I need to send responses up from
> other RS485
> ports. Am I missing something? Is there an easy way
> to do this? Will
> I have to hack the RS232.LIB?
>
> TIA
>
> Draper >
>





Hi guys.

I made a simple change in RS232.lib to handle the tx-enable pin of a 2-wire RS485 connection. You will have to enable the pin manually, but it is turned off automtically in the standard RS232 library. No need for while loops.

So far we have used it in a single module but that one has been working since February. I would still be happy if someone could check the code and see if anything could go wrong.

Since the changes are done directly in RS232.lib, you will have to redo them everytime that you change version of Dynamic C but it is a quick change, as you will see. You will need to add four lines of code for every port that will have the tx-enable. The example below is for port C but port A to F are identical. Just search for spa_isr::, spb_isr:: etc instead of spc_isr:: in RS232.lib.

I posted my sollution on the Bulletin Board of Rabbit ("RS485 tx-enable using RS232.lib") before I found out about this mailing list. Here's a copy of what I wrote back in February. Hope it helps you.
---------

I need to set an output pin to control the tx-enable pin of a half-duplex RS485 circuit. I can enable the tx just before sending the data, but I don't want to wait in a busy loop to reset it when the transfer is done. Thus, I need to use interrupts, which is terrifyingly new to me.

I added these four lines (stolen from pktDemo.C) to spc_isr:: in RS232.lib. They reset pin G4, which I happen to use as tx-enable.

spc_txidle:
ld a, (PGDRShadow)
res 4, a ; Bit G4 is the tx-enable of my com C.
ioi ld (PGDR), a
ld (PGDRShadow), a

In my main program, I set the tx-enable pin just before I call any of the com-functions:

BitWrPortI(PGDR,&PGDRShadow,1,4);
wfd cof_serCputs("Surprise!.\n\r");

I was actually very surprised to see it work. I've done some tests and I can transmit and receive on the port perfectly. I monitored the signal with an oscilloscope and the interrupt turns off the rx-enable pin at the perfect time.

My question is this:
Can anyone see a problem with the code? Is there any situation when the interrupt will fail to reset the tx-enable pin?

Thanks for any help
/Bjn On 2005-09-15 Dave Moore wrote: >Tom Collins wrote:
>> On Sep 14, 2005, at 12:42 PM, dpalu2 wrote:
>>> In summary, I would like to minimize the time spent spinning waiting
>>> for the RS485 to finish transmitting so that I can enable the
>>> receiver, but I also need to handle TCP/IP in case there are requests
>>> on other sockets or I need to send responses up from other RS485
>>> ports. Am I missing something? Is there an easy way to do this? Will
>>> I have to hack the RS232.LIB?
>>
>> Automatically switching between transmit and receive mode on the
>> RS485 bus would be very handy to me as well.
>>
>> I just took a look at the Tx/Rx ISRs and RS232.LIB, and it looks like
>> it might actually be easy to accomplish. I'm using port D, and it
>> would appear that I can simply modify the dDisable and dEnable
>> assembly routines to turn the RS485 driver off and on accordingly.
>>
>> Unfortunately, I don't have the hardware set up to try this. Draper,
>> perhaps you could give it a try and report back to the group with the
>> results.
>
>FYI to you guys, I have had some problems in the past with turning the line
>around too quickly after the last bit gets shifted out. Terminating,
>biasing, line length, etc. You guys have probably been around long enough
>to know that, but just in case... >
> SPONSORED LINKS >
>
> Embedded module > Microcontrollers > Z-world >
>
> Pic microcontrollers > 8051 microprocessor >
>
> YAHOO! GROUPS LINKS >
> >


Have you looked at the packet driver? It is basically "set and
forget".

--- In rabbit-semi@rabb..., "dpalu2" <dpalu2@u...> wrote:
> Hello,
>
> I am using a RCM3000 and it is connected to six RS485 serial
ports.
> The RCM3000 is basically a router. It gets packets on TCP/IP and
> sends them out the appropriate RS485 port and if it gets a
response
> it sends it back up using TCP/IP. So far everything is working
great,
> now I am trying to speed things up. I would like to eliminate the
> below Dynamic C statements
>
> if (serXwrUsed() < byte_count) //byte_count is some number I have
been
> // playing with to increase throughput
> {
> while((!(!serXwrUsed() && !BitRdPortI(SXSR, 2)))); //spin til
all
> // bytes
transmitted
> portXenableRX();
> }
>
> I would like to get rid of the while loop so that the program can
do
> other stuff, but I also want to immediately enable the receiver on
> the RS485 port so I dont miss any incoming bytes. I will never
> receiver any bytes on the RS485 side of things until I have
> completely transmitted a packet out the RS485.
>
> I have six sockets, one for each serial port. tcp_tick() is called
at
> the beginning of the 'superloop'. The 'byte_count' variable in the
if
> statement above is depending a lot on how long the call to tcp_tick
()
> takes.
>
> In summary, I would like to minimize the time spent spinning
waiting
> for the RS485 to finish transmitting so that I can enable the
> receiver, but I also need to handle TCP/IP in case there are
requests
> on other sockets or I need to send responses up from other RS485
> ports. Am I missing something? Is there an easy way to do this?
Will
> I have to hack the RS232.LIB?
>
> TIA
>
> Draper



> My question is this:
> Can anyone see a problem with the code?

Isn't there code already in the libs somewhere to handle rs-485?
packet.lib??

Anyhow, regarding your code below,

> spc_txidle:
> ld a, (PGDRShadow)
> res 4, a ; Bit G4 is the tx-enable of my com C.
> ioi ld (PGDR), a
> ld (PGDRShadow), a

The issue of shutting the tx-enable off prior to the bits going all the way
is a concern. I've not used the rabbit to do rs-485, so can't comment about
exactly when the txidle occurs. Suffice to say make sure your bits have
been received by your endpoints when you shut off the transmitter. (style
comment: and maybe you should make that "4" a macro or something.)

> BitWrPortI(PGDR,&PGDRShadow,1,4);
> wfd cof_serCputs("Surprise!.\n\r");

Seems like there could be some significant time between the txenable and the
actual outgoing data on the wire. Since you were in the libs, why not move
that bit set in front of the transmit routine (must be some sort of tx_start
in there?)

> Is there any situation when the interrupt will fail to reset the tx-enable
pin?

If you don't get the interrupt. ;-) You could get really paranoid and set
a timer after you start a packet or after you send out the last byte...but
then what if you don't get that timer interrupt? I've had to do that before
on serial hardware that doesn't give you a good tx_complete interrupt. A
stuck-on transmitter is a very bad thing in a network. You could also stick
an extra byte on the end as long as your receivers can tolerate that. That
fixes the above "shut the tx enable off too early" problem, but is a bit of
a hack. Sometimes ya just gotta trust the hardware.

-- Dave

bjorn@bjor... wrote:
> Hi guys.
>
> I made a simple change in RS232.lib to handle the tx-enable pin of a
> 2-wire RS485 connection. You will have to enable the pin manually,
> but it is turned off automtically in the standard RS232 library. No
> need for while loops.
>
> So far we have used it in a single module but that one has been
> working since February. I would still be happy if someone could check
> the code and see if anything could go wrong.
>
> Since the changes are done directly in RS232.lib, you will have to
> redo them everytime that you change version of Dynamic C but it is a
> quick change, as you will see. You will need to add four lines of
> code for every port that will have the tx-enable. The example below
> is for port C but port A to F are identical. Just search for
> spa_isr::, spb_isr:: etc instead of spc_isr:: in RS232.lib.
>
> I posted my sollution on the Bulletin Board of Rabbit ("RS485
> tx-enable using RS232.lib") before I found out about this mailing
> list. Here's a copy of what I wrote back in February. Hope it helps
> you. ---------
>
> I need to set an output pin to control the tx-enable pin of a
> half-duplex RS485 circuit. I can enable the tx just before sending
> the data, but I don't want to wait in a busy loop to reset it when
> the transfer is done. Thus, I need to use interrupts, which is
> terrifyingly new to me.
>
> I added these four lines (stolen from pktDemo.C) to spc_isr:: in
> RS232.lib. They reset pin G4, which I happen to use as tx-enable.
>
> spc_txidle:
> ld a, (PGDRShadow)
> res 4, a ; Bit G4 is the tx-enable of my com C.
> ioi ld (PGDR), a
> ld (PGDRShadow), a
>
> In my main program, I set the tx-enable pin just before I call any of
> the com-functions:
>
> BitWrPortI(PGDR,&PGDRShadow,1,4);
> wfd cof_serCputs("Surprise!.\n\r");
>
> I was actually very surprised to see it work. I've done some tests
> and I can transmit and receive on the port perfectly. I monitored the
> signal with an oscilloscope and the interrupt turns off the rx-enable
> pin at the perfect time.
>
> My question is this:
> Can anyone see a problem with the code? Is there any situation when
> the interrupt will fail to reset the tx-enable pin?
>
> Thanks for any help
> /Bjn > On 2005-09-15 Dave Moore wrote: >>
>>
>>
>> Tom Collins wrote:
>>> On Sep 14, 2005, at 12:42 PM, dpalu2 wrote:
>>>> In summary, I would like to minimize the time spent spinning
>>>> waiting for the RS485 to finish transmitting so that I can enable
>>>> the receiver, but I also need to handle TCP/IP in case there are
>>>> requests on other sockets or I need to send responses up from
>>>> other RS485 ports. Am I missing something? Is there an easy way to
>>>> do this? Will I have to hack the RS232.LIB?
>>>
>>> Automatically switching between transmit and receive mode on the
>>> RS485 bus would be very handy to me as well.
>>>
>>> I just took a look at the Tx/Rx ISRs and RS232.LIB, and it looks
>>> like it might actually be easy to accomplish. I'm using port D,
>>> and it would appear that I can simply modify the dDisable and
>>> dEnable assembly routines to turn the RS485 driver off and on
>>> accordingly.
>>>
>>> Unfortunately, I don't have the hardware set up to try this.
>>> Draper, perhaps you could give it a try and report back to the
>>> group with the results.
>>
>> FYI to you guys, I have had some problems in the past with turning
>> the line
>> around too quickly after the last bit gets shifted out. Terminating,
>> biasing, line length, etc. You guys have probably been around long
>> enough
>> to know that, but just in case...
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> SPONSORED LINKS
>>
>>
>>
>>
>> Embedded module
>>
>>
>> Microcontrollers
>>
>>
>> Z-world
>>
>>
>>
>>
>> Pic microcontrollers
>>
>>
>> 8051 microprocessor
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> YAHOO! GROUPS LINKS
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
> >
>
> ------------------------ Yahoo! Groups Sponsor
> --------------------~-->
> Fair play? Video games influencing politics. Click and talk back!
> http://us.click.yahoo.com/T8sf5C/tzNLAA/TtwFAA/dN_tlB/TM
> --------------------------------~- > Yahoo! Groups Links >




Thanks for the suggestion. It appears it would be that easy but I had
troubles and after getting the O-scope out and mucking in assembly,
still have not found a solution.

Here is a code snippit, works fine if i manually switch ON/OFF RS485:

char dummy[100];
strcpy(dummy, "this is only a test, test");
for (i = 0; i < strlen(dummy); i++)
{
serFputc(dummy[i]);
}

while((!(!serFwrUsed() && !BitRdPortI(SFSR, 2))));
Here is the assembly I modified to automagically switch ON/OFF RS485

fDisable::
; disable RS485 TX, DE line pulled low
ld a,(PFDRShadow) ;
and 0feh ;
ld (PFDRShadow),a ;
ioi ld (PFDR),a ;

ld a,(PGDRShadow)
set FDRIVE_TXD,a ;make sure Tx is high(idle)
ld (PGDRShadow),a
ioi ld (PGDR),a
ld a,(PGFRShadow)
res FDRIVE_TXD,a
ld (PGFRShadow),a
ioi ld (PGFR),a
ret fEnable::
; enable RS485 TX, DE line pulled high
ld a,(PFDRShadow) ;
or 01h ;
ld (PFDRShadow),a ;
ioi ld (PFDR),a ;

ld a,(PGFRShadow)
set FDRIVE_TXD,a
ld (PGFRShadow),a
ioi ld (PGFR),a
ret Looking at the scope the behavior is that the DE for RS485 is high
initially, then goes low after about 8 bytes are transmitted and then
goes back high forever. Still trying to figure out why. Its probably
something dumb I am doing.

Thanks --- In rabbit-semi@rabb..., Tom Collins <tom@t...> wrote:
> On Sep 14, 2005, at 12:42 PM, dpalu2 wrote:
> > In summary, I would like to minimize the time spent spinning
waiting
> > for the RS485 to finish transmitting so that I can enable the
> > receiver, but I also need to handle TCP/IP in case there are
requests
> > on other sockets or I need to send responses up from other RS485
> > ports. Am I missing something? Is there an easy way to do this?
Will
> > I have to hack the RS232.LIB?
>
> Automatically switching between transmit and receive mode on the
RS485
> bus would be very handy to me as well.
>
> I just took a look at the Tx/Rx ISRs and RS232.LIB, and it looks
like
> it might actually be easy to accomplish. I'm using port D, and it
> would appear that I can simply modify the dDisable and dEnable
assembly
> routines to turn the RS485 driver off and on accordingly.
>
> Unfortunately, I don't have the hardware set up to try this.
Draper,
> perhaps you could give it a try and report back to the group with
the
> results.
>
> --
> Tom Collins - tom@t...
> Certified Rabbit Semiconductor Consultant based in Napa, California
> Info on the Sniffter, a rechargeable, hand-held Network Tester
> powered by the RCM2210: http://sniffter.com/



The 2024 Embedded Online Conference