RS485 with Pic.

Papabravo

Joined Feb 24, 2006
22,084
JohnInTX's method works fine for many different UART based applications, but it says nothing about how to handle a bidirectional tranasceiver, with or without an available pin to control DE/RE. He does address the problem of the difference between "Transmit Data Register Empty" and "Transmit Shift Register Empty". You would of course need to verify that the the "Transmit Shift Register Empty" occurs at the end of the stop bit and NOT at the end of the last data bit. In order to achieve minimum turnaround delay you must be able in time, or by some other means, to determine the end of the stop bit and enable your receiver as soon as practical thereafter. It is still possible for one or more devices to muff this up so the technique needs to be robust and able to recover from mistakes and other unforeseen circumstances.

My next suggestion would be to implement a token passing protocol where the right to speak (transmit) is passed from one device to another in such a fashion that some node on the network always has the right to speak and pass the token if they have nothing to say.
 

JohnInTX

Joined Jun 26, 2012
4,787
JohnInTX's method works fine for many different UART based applications, but it says nothing about how to handle a bidirectional tranasceiver, with or without an available pin to control DE/RE. ..
Actually, that's what it does since its receiving, under protocol, when not transmitting. It assumes a pin that turns on the transmitter. It also assumes that the transmitted data is not echoed back to the transmitter's receiver. If by bidirectional you mean half-duplex, that's what it does according to the protocol implemented.

In order to achieve minimum turnaround delay you must be able in time, or by some other means, to determine the end of the stop bit and enable your receiver as soon as practical thereafter
TRMT interrupts when the last stop is sent. The protocol, as you indicate, determines the minimum turnaround time allowed.

It is still possible for one or more devices to muff this up so the technique needs to be robust and able to recover from mistakes and other unforeseen circumstances.
That's the job of the protocol, whatever it turns out to be. My description was how to manage the TX line of the RS485 under interrupt-driven transmission.
 

Thread Starter

MaxHeadRoom

Joined Jul 18, 2013
30,693
The packet info does not stick rigidly to Modbus protocol but is a form of it, the Pic is operating as a single slave linked to one master.
The packet consists of a 6,7 0r 8 byte packet, after the pic (slave) receives it, it is transmitted back to the master after the customary one and half byte wait time.
Max.
 

Sensacell

Joined Jun 19, 2012
3,786
For what it's worth:

Leave the receiver permanently enabled, when you send a byte, enable the TX, use the receiver interrupt to turn the TX enable off.
Use your own receiver to tell when the character has been sent, looping it back to your own RX input.
I do half-duplex RS-485 @230,400 baud, this is the only fool proof way to do it, requires no extra IO.

Note that the only flaw is when the bus is physically compromised, the RX does not get the data back and the TX can get stuck- use a long time-out as a fix.
 

MrChips

Joined Oct 2, 2009
34,889
If you have one spare output pin I would use that to control DE/RE. To me that is the easiest and sane solution.

I can give you the protocol that I use if you are interested.
 

MrChips

Joined Oct 2, 2009
34,889
There is nothing proprietary about it and is similar to other existing protocols.

UART format is 7 bits, even parity, 1 stop bit, 9600 baud.

Package format

<start> <device address> <command> <message> <checksum> <end>

<start> is $ or 0x24

<device address> is single character 0-9, A-Z, or a-z. "0" is reserved as broadcast address.

<command> is two characters. First character is A-Z. Second character is A-Z or 0-9.

<message> is printable ASCII text, including, SP, +, -, A-Z, a-s, 0-9.

<checksum> is two hex characters, 0-9, A-F, upper nybble followed by lower nybble.

<end> is single character CR or 0x0D.

Slave response is similar except <start> is * or 0x2A.

<checksum> is computed as the mod 256 sum of all characters (7-bit) including <start> and up to and including <message>.
<checksum> can be replaced with ?? for testing purposes.

All characters are ASCII printable characters, 0-9, A-Z, a-z, +,-,?,$,*,SP and CR.

You may want to specify a minimum turn around delay of one character (1ms) to be on the safe side with slow devices.
 

MrChips

Joined Oct 2, 2009
34,889
I should mention, don't confuse UART, TTL, USB, RS-232 and RS-485.

Your only reason for going RS-485 is if you want industrial strength LAN over long distances, say 25m or more.

You can still use a USB interface with the above protocol to communicate with any number of devices in the same box. I have ten MCUs communicating with a PC via a single USB connection.
 

John P

Joined Oct 14, 2008
2,063
Actually, that's what it does since its receiving, under protocol, when not transmitting. It assumes a pin that turns on the transmitter. It also assumes that the transmitted data is not echoed back to the transmitter's receiver. If by bidirectional you mean half-duplex, that's what it does according to the protocol implemented.

TRMT interrupts when the last stop is sent.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The protocol, as you indicate, determines the minimum turnaround time allowed.

That's the job of the protocol, whatever it turns out to be. My description was how to manage the TX line of the RS485 under interrupt-driven transmission.
Unfortunately, the underlined sentence there is not true, at least not for the PIC16F690 that I mostly use, as I said yesterday. The manual says:
12.1.1.4 TSR Status
The TRMT bit of the TXSTA register indicates the status of the TSR register. This is a read-only bit. The
TRMT bit is set when the TSR register is empty and is cleared when a character is transferred to the TSR
register from the TXREG. The TRMT bit remains clear until all bits have been shifted out of the TSR register.
No interrupt logic is tied to this bit, so the user has to poll this bit to determine the TSR status.


By the way, the timing diagram (Figure 12.3) shows the TRMT bit as setting in the center of the stop bit. If the outgoing shift register is reloaded before a character has been fully sent (as would happen if the processor loads another character in response to the TXIF interrupt) TRMT won't become set between characters.
 

Thread Starter

MaxHeadRoom

Joined Jul 18, 2013
30,693
I should mention, don't confuse UART, TTL, USB, RS-232 and RS-485.

Your only reason for going RS-485 is if you want industrial strength LAN over long distances, say 25m or more.

You can still use a USB interface with the above protocol to communicate with any number of devices in the same box. I have ten MCUs communicating with a PC via a single USB connection.
I have been working with the various protocols for some years now, although mainly RS232 from the beginning. One of my first projects was building a paper tape reader Parallel to RS232 for reading the old CNC tapes.

The master is already a piece of equipment using a version of Modbus in which I need to communicate with, I am already communicating using my pic test board but with a RS232 to RS485 inline convertor and everything is working, I want to replace the RS232 with a RS485/MAX485 IC.
Max.
 

JohnInTX

Joined Jun 26, 2012
4,787
John_P is correct about TRMT not being the source of the IRQ, my wording was sloppy - apologies for any confusion. The point of all of it is that on a TXIF, if you have no other characters to send and TRMT is 1, you can turn the transmitter off. You may indeed be in the middle of the stop bit but if the bus is biased to a MARK condition that is OK. If the bus is not biased to MARK, the receivers will have problems between messages.

By the way, the timing diagram (Figure 12.3) shows the TRMT bit as setting in the center of the stop bit. If the outgoing shift register is reloaded before a character has been fully sent (as would happen if the processor loads another character in response to the TXIF interrupt) TRMT won't become set between characters.
..which is how you would expect it to act.
 

John P

Joined Oct 14, 2008
2,063
John_P is correct about TRMT not being the source of the IRQ, my wording was sloppy - apologies for any confusion. The point of all of it is that on a TXIF, if you have no other characters to send and TRMT is 1, you can turn the transmitter off. You may indeed be in the middle of the stop bit but if the bus is biased to a MARK condition that is OK. If the bus is not biased to MARK, the receivers will have problems between messages.

..which is how you would expect it to act.
Sorry to be hassling a guy with the excellent name John, but-- the UART in a PIC is a double-buffered shift register. You can load a character to the TXREG register while a previous character is shifting out, and the interrupt gets generated when it's possible to do that, i.e. at the start of an outgoing character, not at the end. You say "on a TXIF, if you have no other characters to send and TRMT is 1" but that condition can never occur; if you respond to the TXIF, I suppose you could wait in a loop, something like

while (!bit_test(TXSTA, TRMT)) ; // Wait for outgoing character to complete

But if you do that at 9600Bd, you'll be sitting there for a millisecond, give or take. I think it would be a better plan to set a timer for that millisecond when the last character is sent, and get an interrupt when it expires, and then go in and disable the transmitter. For a little extra confidence, you could check TRMT, but it's predictable when it would occur so there's not much practical reason to do it.
 

JohnInTX

Joined Jun 26, 2012
4,787
John_P, I have to agree with you here - especially the 'excellent' part ;). And after reviewing the datasheet, I see exactly what you mean. Hmmm.. So now I have to 1)quit popping off from memory and 2) go back through the archives to see what I did about waiting until the shift register was empty before turning xmit off.

I wouldn't use a dumb delay in an interrupt routine.
The method I did describe actually would inadvertently implement the dumb delay by repeatedly interrupting with an empty FIFO and polling TRMT (TXIF would be 1 continuously if nothing was loaded to TXREG-and I understand the double buffering aspect). Don't think I would have allowed that to happen either.
I agree with your implementation of a secondary timer after the last char was loaded. Again, hmmm.. what the heck was I thinking??

Thanks for your scholarship and kind patience.
 

Sensacell

Joined Jun 19, 2012
3,786
John_P is correct about TRMT not being the source of the IRQ, my wording was sloppy - apologies for any confusion. The point of all of it is that on a TXIF, if you have no other characters to send and TRMT is 1, you can turn the transmitter off. You may indeed be in the middle of the stop bit but if the bus is biased to a MARK condition that is OK. If the bus is not biased to MARK, the receivers will have problems between messages.

..which is how you would expect it to act.
This has vexed me quite a bit- the only bulletproof way I have found is the RX interrupt loop-back method.
It's the only way that guarantees that the last char is fully done, stop bit and all, before shutting down the TX enable.

I use this method now on my PIC based products and it works clean. My product does fast back-to-back multi-node transactions, where the timing must be crisp.
Before I tried to time out the TX EN with TMR0, but that was tricky and created timing jitter.
I ended up needing to restart the UART module to sync the TX enable with the actual data transitions, the RX interrupt gives you a true time reference to the actual data stream.

I am still bloody from that battle.
 

John P

Joined Oct 14, 2008
2,063
Sensacell, that's a very elegant solution to the problem--making the outgoing data stream tell you when the character ends! Obviously much more precise than a timer.
 
Top