Searching \ for '[PIC]: Sending the last byte in a 2 wire RS485 tra' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/ios.htm?key=rs485
Search entire site for: 'Sending the last byte in a 2 wire RS485 tra'.

Exact match. Not showing close matches.
PICList Thread
'[PIC]: Sending the last byte in a 2 wire RS485 tra'
2000\08\10@125646 by Simon Nield

flavicon
face
Background:
I have a 16f877 running at 20MHz communicating with a PC using 2 wire RS485 at 115200 baud.
In other words it's half-duplex. The PC sends out a request and the PIC then responds with a load of
data.
The transmission from the PIC is all dealt with via interrupts and the hardware USART.

Problem:
When the last byte is moved from the TXREG into the TSR for shifting out, the TXIF interrupt goes
off...
 If I disable the 485 output buffer now then I will truncate the last byte.
 If I send a dummy byte now and disable when _that_ is moved into the TSR then I send an extra byte
of garbage... also this does not seem to work reliably
 If I sit polling (TXSTA, TRMT) until the transmission is done then I waste almost 400 instruction
cycles.

Question:
Have any of you run in to this problem before and found an elegant solution ?


Thanks,
Simon

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]: PIC only [EE]: engineering [OT]: off topic [AD]: advertisements

2000\08\10@131507 by Bob Ammerman

picon face
Many of us have run into this.  It is a common problem with many UARTS in
many environments.

Your extra byte idea is a good one, but you are probably still turning off
the 485 buffer in the middle of the character and thus confusing the poor
PC.

My best suggestion is to find something useful to do doing the 400
instructions that you have to wait for TRMT.

Bob Ammerman
RAm Systems
(contract developement of high performance, high function, low-level
software)

{Original Message removed}

2000\08\10@131512 by Andrew Kunz

flavicon
face
>  If I sit polling (TXSTA, TRMT) until the transmission is done then I waste
almost 400 instruction
>cycles.
>
>Question:
>Have any of you run in to this problem before and found an elegant solution ?

Been there, done that.

It's a WHOLE lot easier to just send a dummy character that is ignored by your
protocol (in my case, the LF after a CR), and to not start transmission until
the USART receiver says it's OK to do so (put a flag in your ISR that will
enable the transmission only after it has received that terminator character, or
a long time (several character times) have expired.

Andy

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]: PIC only [EE]: engineering [OT]: off topic [AD]: advertisements

2000\08\10@131516 by M. Adam Davis

flavicon
face
So, what exactly is the problem?

Are you saying you don't want the TXIF interrupt to be set off when you send the
last byte?  You can turn it off for the last byte.

I assume you have a routine that starts the transmission of your packet of
data.  In this routine clear the TXIF bit, and enable the TXIF interrupt.  In
your TXIF interrupt routine you should be able to tell when your packet buffer
is empty.  Immediately before placing the last byte into txreg, disable the TXIF
interrupt.  This will make it so that interrupt occurs ONLY when you have data
to send, and the txreg is available.

I would avoid workarounds like truncating bytes and such, it makes code reuse
and maintenance a pain in the neck.

-Adam

Simon Nield wrote:
{Quote hidden}

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]: PIC only [EE]: engineering [OT]: off topic [AD]: advertisements

2000\08\10@134029 by Andrew Kunz
flavicon
face
No, what he's looking to do is keep it from actually turning off the
transmission (ie, drop into receive mode) immediately after the last useful
byte.  The if TRMT bit generated an interrupt (somebody in Arizona listening?)
then it would be a no-brainer.  As it is, you have to wait for TXIF and TRMT to
both be true, and the 400 instructions is how long that takes after sticking the
last char into TXREG.

Andy









"M. Adam Davis" <spam_OUTadavisTakeThisOuTspamUBASICS.COM> on 08/10/2000 01:14:52 PM

Please respond to pic microcontroller discussion list <.....PICLISTKILLspamspam@spam@MITVMA.MIT.EDU>








To:      PICLISTspamKILLspamMITVMA.MIT.EDU

cc:      (bcc: Andrew Kunz/TDI_NOTES)



Subject: Re: [PIC]: Sending the last byte in a 2 wire RS485
         transmission








So, what exactly is the problem?

Are you saying you don't want the TXIF interrupt to be set off when you send the
last byte?  You can turn it off for the last byte.

I assume you have a routine that starts the transmission of your packet of
data.  In this routine clear the TXIF bit, and enable the TXIF interrupt.  In
your TXIF interrupt routine you should be able to tell when your packet buffer
is empty.  Immediately before placing the last byte into txreg, disable the TXIF
interrupt.  This will make it so that interrupt occurs ONLY when you have data
to send, and the txreg is available.

I would avoid workarounds like truncating bytes and such, it makes code reuse
and maintenance a pain in the neck.

-Adam

Simon Nield wrote:
>
> Background:
> I have a 16f877 running at 20MHz communicating with a PC using 2 wire RS485 at
115200 baud.
> In other words it's half-duplex. The PC sends out a request and the PIC then
responds with a load of
> data.
> The transmission from the PIC is all dealt with via interrupts and the
hardware USART.
>
> Problem:
> When the last byte is moved from the TXREG into the TSR for shifting out, the
TXIF interrupt goes
> off...
>   If I disable the 485 output buffer now then I will truncate the last byte.
>   If I send a dummy byte now and disable when _that_ is moved into the TSR
then I send an extra byte
> of garbage... also this does not seem to work reliably
>   If I sit polling (TXSTA, TRMT) until the transmission is done then I waste
almost 400 instruction
{Quote hidden}

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]: PIC only [EE]: engineering [OT]: off topic [AD]: advertisements

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]: PIC only [EE]: engineering [OT]: off topic [AD]: advertisements

2000\08\10@135028 by Simon Nield

flavicon
face
(My problem is not that I don't want an interrupt for the last byte in a packet, it's that I want to
disable the RS485 buffer soon after that last byte is transmitted - sorry for not making that
totally clear.)

anyway...

I think I may have figured out why sending the extra byte at the end is unreliable;

1 dummy byte gets transfered from TXREG to TSR
2 interrupt goes off
3 interrupt handler takes a while to get to....
4 disable 485 output buffer

If the time taken to get between 1 and 4 is around half a bit (approx 21 instruction cycles at this
baud rate & clock speed) then the UART in the PC may or may not see the startbit of the dummy byte.
As the rest of the byte is chopped off (=> line goes to inactive state = high) then the PC may or
may not receive the 0xff.

Simon

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]: PIC only [EE]: engineering [OT]: off topic [AD]: advertisements

2000\08\10@142408 by Don Hyde

flavicon
face
Lacking an interrupt on TRMT, about the best you can do is to use a timer to
generate an interrupt about when you need to turn the bus around.  If it's
important to turn the bus around promptly, then you can set the interrupt to
happen a little early, then poll until the register is actually empty.

To achieve a robust serial protocol, I usually have a timer dedicated to
timing out messages I am receiving, so that I don't wait forever for the
last byte of a block when the other end has crashed or someone has tripped
over the plug.  In a half-duplex link, that timer is standing around idle
during transmission, so it doesn't really cost any resources to use it, only
code complexity.

> {Original Message removed}

2000\08\10@142608 by Bob Bullock

flavicon
face
I can see four methods to deal with this.

In all cases, turn off the transmit buffer empty interupt when you move the
last byte to be sent into txreg.

1) In one case, I had other interrupts happening frequently enough that I
could deal with this in the interrupt routine.  The common interrupt
service routine  first has to determine the source of the interrupt. So
right after the check for transmit interrupt flag, I checked to see if the
interrupt was enabled, if it wasn't then I knew I was waiting for the last
byte to shift out, so I checked the trmt bit to see if it was finished yet.
If it was, then I turned the line around.

2) If an extra timer is available, enable the timer to generate an
interrupt just after you expect the last character to be shifted out and
enable the timer when you move the last byte into txreg.  In the timer
interrupt code, verify the trmt bit is set (maybe loop for n times checking
before proceeding anyway) and perform your line switch.  Disable the timer
interrupt of course.

3) If your main line loop is fast enough, or your switch around
requirements are not as tight, you can simply check for the TRMT bit to be
set in the main line.  Only check when you know you are waiting for the
last byte to shift out.  This could be your own special flag bit, or the
condition when the transmitter is enabled TXEN, and transmit empty
interrupts are disabled TXIE low, which should only occur when you are
waiting for the last byte to shift out.

4) Loop waiting for the TRMT bit to be set.  If you have other interrupts
that may occur during this period, hopefully yoour main line loop would be
fast enough loop through to a point where it can check for this situation
and begin the looping wait in your main line code.  If there are no other
sources of interrupt, you can loop in the interrupt code.  Of course, if
you checked for the other interrupt source flags in your loop, you could
then exit the loop and let the other isr's run, knowing you would come back
into the isr again with the TXIE empty interrupt.

At 05:35 PM 8/10/2000 +0100, you wrote:
>Background:
>I have a 16f877 running at 20MHz communicating with a PC using 2 wire
RS485 at 115200 baud.
>In other words it's half-duplex. The PC sends out a request and the PIC
then responds with a load of
>data.
>The transmission from the PIC is all dealt with via interrupts and the
hardware USART.
>
>Problem:
>When the last byte is moved from the TXREG into the TSR for shifting out,
the TXIF interrupt goes
>off...
>  If I disable the 485 output buffer now then I will truncate the last byte.
>  If I send a dummy byte now and disable when _that_ is moved into the TSR
then I send an extra byte
>of garbage... also this does not seem to work reliably
>  If I sit polling (TXSTA, TRMT) until the transmission is done then I
waste almost 400 instruction
>cycles.

Bob Bullock
President
Western Support Group Ltd.
.....bobbKILLspamspam.....prostyle.com
Certified Microchip Consultants
http://www.microchip.com/10/Consult/Country/Canada/index6.htm#915-277

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]: PIC only [EE]: engineering [OT]: off topic [AD]: advertisements

2000\08\10@151544 by M. Adam Davis

flavicon
face
Ah, that makes sense.  Well, it shouldn't introduce too much overhead to let the
PIC read from the rs-485 at the same time.  Turn off RX interrupts except just
before sending the last byte.  You can test for the last character, and switch
over at that point:

Fill the packet buffer memory
call the start transmission routine
 Turn off the RX interrupt
 Turn on the TX interrupt
Do other stuff...

TX-Interrupt routine
If this is the last byte
 Turn the RX interrupt ON
 Clear RX flags (overrun, framing, etc)
 Clear RX register
 Turn OFF TX interrupt
 Send last byte
 Set a last byte sent flag or something
Else
 Send next byte
endif

RX interrupt routine
If last byte flag (or use TXIF, or some other method)
 Test incoming against last byte sent.
 Switch off RS-485 xmit buffer
else
 Perform whatever on incoming data
endif

-Adam


Andrew Kunz wrote:
{Quote hidden}

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]: PIC only [EE]: engineering [OT]: off topic [AD]: advertisements

2000\08\10@151722 by Bob Ammerman

picon face
Yes, you have pegged it exactly.

This brings up a way to fix this, I think.

If the idle state of the line will be detected by the PC as a valid stop bit
condition (and I think it should), then you just need to delay long enough
in the interrupt handler to ensure that you are beyond the end of the start
bit before disabling the buffer.

Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
software)

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]: PIC only [EE]: engineering [OT]: off topic [AD]: advertisements

2000\08\10@152803 by Harold M Hallikainen

picon face
       The double buffering does make it difficult to synchronize things like
turning off transceivers or sending break (like for DMX). My solution was
to not use the USART interrupt, but use a timer interrupt that's set just
a little bit longer than it takes to send one character. When you then
drop a character into the TXREG, it is transmitted immediately. I use a
state machine to keep track of where I am (transmitting data, sending
break, turning off transmitters, etc.).

Harold


On Thu, 10 Aug 2000 17:35:41 +0100 Simon Nield <KILLspamsimon.nieldKILLspamspamQUANTEL.COM>
writes:
{Quote hidden}

FCC Rules Online at http://hallikainen.com/FccRules
Lighting control for theatre and television at http://www.dovesystems.com

________________________________________________________________
YOU'RE PAYING TOO MUCH FOR THE INTERNET!
Juno now offers FREE Internet Access!
Try it today - there's no risk!  For your FREE software, visit:
dl.http://www.juno.com/get/tagj.

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]: PIC only [EE]: engineering [OT]: off topic [AD]: advertisements

2000\08\10@161148 by Olin Lathrop

flavicon
face
> When the last byte is moved from the TXREG into the TSR for shifting out,
the TXIF interrupt goes
> off...
>   If I disable the 485 output buffer now then I will truncate the last
byte.
>   If I send a dummy byte now and disable when _that_ is moved into the TSR
then I send an extra byte
> of garbage... also this does not seem to work reliably
>   If I sit polling (TXSTA, TRMT) until the transmission is done then I
waste almost 400 instruction
> cycles.

I had exactly the same problem once on a 16C77, which is identical to your
16F877 for this purpose.  I added a call to an idle routine in the wait loop
so that other parts of the system could use the processor.  Of course you
have to be careful that the idle call doesn't take too long, or that the PC
minimum turnaround time is long enough.  Keep in mind there always has to be
a spec in this kind of system that says how long the new transmitter must
wait before sending the first character, to guarantee that the new receiver
has finished turning around its end and is ready to receive.

Below is the relevant code from the UART handling module.  There some macros
in there for subroutine linkage and register bank management, but you should
be able to see what's going on.

;
;***********************************************************************
;
;   Subroutine UART_MODE_RECV
;
;   Reset the receiver and set the serial line state for receiving.
;   This routine first waits to make sure all pending data has been
;   completely transmitted.
;
        glbsub  uart_mode_recv, noregs

recv_loop                    ;back here until transmitter fully drained
        gcall   app_idle    ;let app do a little work
        dbankif txsta       ;set direct page for access to transmit status
reg
        btfss   txsta, trmt ;transmitter all done yet ?
        goto    recv_loop   ;back to check transmit done again

        dbankif rcsta
        bcf     rcsta, cren ;make sure receiver is reset
        bsf     rcsta, cren ;enable the receiver

        dbankif dirreg
 if dirin
        bsf     dirreg, dirbit ;set bit to select INPUT direction
   else
        bcf     dirreg, dirbit ;clear bit to select INPUT direction
   endif

        leaverest



*****************************************************************
Olin Lathrop, embedded systems consultant in Devens Massachusetts
(978) 772-3129, RemoveMEolinTakeThisOuTspamcognivis.com, http://www.cognivis.com

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]: PIC only [EE]: engineering [OT]: off topic [AD]: advertisements

2000\08\10@175238 by Alan B. Pearce

face picon face
A good trick with this sort of problem is to send a dummy byte of hex FF. Then
it will not matter if you turn off the transmission in mid character, as the o/c
line should result in the receiver chip still producing ones into the receiving
uart.

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]: PIC only [EE]: engineering [OT]: off topic [AD]: advertisements

2000\08\11@061833 by Peter L. Peres

picon face
>extra byte

I have done this by sending a 0xFF as the extra byte. That way the
controlling computer has the longest time to turn off the buffer in case
of interrupt latency incertitude (and causes the same byte to be received
- 0xFF). This was with a 16550 UART. The receiver will receive one bad
byte at most if the switching occurs too early, otherwise it sees a 0xFF.

The other way to do it is to set break before switching. Then the line is
always switched in break mode. For this to work, all transmitters must set
and maintain break for at least 2 character periods with the switching
occuring hopefully in the middle. The break condition is the only state
that the receiver can definitely detect without flagging an error and
without hadware help afaik (and without receiving garbage characters).

Anyway I've never ever sent RS485 data without a checksum in a defined
length packet.

Obviously the line stays in the mark condition by using suitable resistor
networks when no-one is talking.

Peter

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

2000\08\11@071139 by Andrew Kunz

flavicon
face
GONG!  Writing a 0 puts high-level (idle) on the bus.

Andy










"Alan B. Pearce" <spamBeGoneA.B.PearcespamBeGonespamRL.AC.UK> on 08/10/2000 05:50:40 PM

Please respond to pic microcontroller discussion list <TakeThisOuTPICLISTEraseMEspamspam_OUTMITVMA.MIT.EDU>








To:      RemoveMEPICLISTspamTakeThisOuTMITVMA.MIT.EDU

cc:      (bcc: Andrew Kunz/TDI_NOTES)



Subject: Re: [PIC]: Sending the last byte in a 2 wire RS485
         transmission








A good trick with this sort of problem is to send a dummy byte of hex FF. Then
it will not matter if you turn off the transmission in mid character, as the o/c
line should result in the receiver chip still producing ones into the receiving
uart.

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]: PIC only [EE]: engineering [OT]: off topic [AD]: advertisements

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

2000\08\11@083538 by Andy Jancura

picon face
{Quote hidden}

Hi,

I didn't read all the answers. But I think all messages stored in memory
have terminating char or they have fixed lengths. So if your ISR detect an
termination, then just start poll the TRMT flag or start an timer to
generate the stop-bit delay.

Andrej

________________________________________________________________________
Get Your Private, Free E-mail from MSN Hotmail at http://www.hotmail.com

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

2000\08\11@121024 by Simon Nield

flavicon
face
Thankyou all for your suggustions for this.

In the end I went for sending a dummy byte at the end of my data as i was already doing, and to
ensure this gets sent reliably all i do is spin in a delay loop for around 1 bit period then disable
the buffer.
I may reduce the amount of time I spend in that delay loop at some point, but as it is only 40
instruction cycles at the moment, I will probably not bother.


Thanks ;)
Simon

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

More... (looser matching)
- Last day of these posts
- In 2000 , 2001 only
- Today
- New search...