|
|
View previous topic :: View next topic |
Author |
Message |
Quest Guest
|
RS485 Problem |
Posted: Sat May 27, 2006 9:34 am |
|
|
hi,
I am testing the CCS RS232-RS485 adapter board. I use the example code from CCS EX_RS232_485.C. The board uses the 16F628A PIC.
The RS232-RS485 adapter board is connect to RS485 bus, and also connect to PC hyperterminal program via RS232 cable.
With only one RS485 device connect to the RS485 bus. It works fine.
When I have multiple RS485 devices connect the rx485 bus. After sending and receiving data from multiple RS485 devides for a while, suddendly, the RS232-RS485 adapter board is hanged. Unfortunate, the 16F628A PIC needs a special ICD to debug it, but mine is just a normal ICD-U from CCS.
I modified EX_RS232_485.C to have some code to output a HIGH or LOW on some of the spared IO pins on RS232-RS485 adapter board. By doing that, I have some ideas what is really hanged. It seems that when the problem happens, the INT_RDA still runs and be able to receive incoming data from the hyper terminal sending to the RS232-RS485 adapter board via the RS232.
I think the INT_EXT is hanged. I guess this is the one is used to receive incoming data from RS485 bus...
If anyone has any ideas or suggestion about this problem, please help me.
Thank you
Jim |
|
|
Ttelmah Guest
|
|
Posted: Sat May 27, 2006 10:19 am |
|
|
It is not really possible to 'hang' the receive interrupt. It should recover if data is present on the RS485 bus. The only way it can get 'hung', is if a very narrow 'edge' is seen on the 485 bus, which triggers the call to the interrupt handler, and then no data arrives, which will leave the getc 'waiting'. However if this happens, there would be no response from the int_rda interrupt. The fact that you are seeing int_rda interrupts occuring, implies that the code is outside the interrupt handlers, in the main (interrupts can't interrupt other handlers in general on the PIC)....
Now, there is a question about your wiring of the RS485 bus. Depending on what RS485 transceivers you are using, and the termination networks, it is possible for the bs to sit, when not driven, in an 'active' state. If this was happening, you could potentially be permanently receiving RS485 comms, but never getting any that matched the device ID.
Best Wishes |
|
|
Guest
|
|
Posted: Sat May 27, 2006 3:35 pm |
|
|
hi,
I use the MAX3440 for RS485 transceiver. Between the TX and RX line, there is a 120 Ohm resistor.
Currently, I have 3 RS485 devices connect to the RS485 bus. One of them is the rs485-rs232 adapter board. The others devices send messages with the same message lenght to the adapter board via rs485.
When in the good state, the adapter board declares it receives messages with passed the checksum, the to-address is correct and the message is also correct.
Yes, you are right! the external interrupt on the adapter board still runs when it is in the bad state or "hang", but When in bad state, the rs485-rs232 adapter board keeps declaring that it receives all message with failed checksum, incorrect to-address and incorrect message-length.
It seems to me that RS485 message format (Format: source | destination | data-length | data | checksum), there is no special pattern or characters to indicate the the start message. So later on, we can use to re-synch.
looking at the fucntion incomming_rs485() from CCS driver RS485.c, I wonder how the function will resyn after receiving a corrupted message???
// Purpose: Interrupt service routine for handling incoming RS485 data
#if (RS485_USE_EXT_INT==FALSE)
#int_rda
#else
#int_ext
#endif
void incomming_rs485() {
int16 b;
static int8 cs,state=0,len;
static int16 to,source;
b=fgetc(RS485);
cs^=(int8)b;
switch(state) {
case 0: // Get from address
temp_ni=rs485_ni;
source=b;
cs=b;
rs485_add_to_temp(source);
break;
case 1: // Get to address
to=b;
#if (getenv("AUART")&&(RS485_USE_EXT_INT==FALSE))
setup_uart(UART_DATA);
#endif
test_to_adress = to;
break;
case 2: // Get len
len=b;
rs485_add_to_temp(len);
test_len_msg = len;
break;
case 255: // Get checksum
if ((!cs)&&(bit_test(to,8))&&(bit_test(source,8))&&((int8)to==RS485_ID))
{ // If cs==0, then checksum is good
rs485_ni=temp_ni;
test_msg_crc_status = 'P'; /* passed */
}
else
{
test_msg_crc_status = 'F'; /* falied */
}
test_data_rs485++;
#if (getenv("AUART")&&(RS485_USE_EXT_INT==FALSE))
setup_uart(UART_ADDRESS);
#endif
state=0;
return;
default: // Get data
rs485_add_to_temp(b);
--len;
break;
}
if ((state>=3) && (!len)) {
state=255;
}
else {
++state;
}
} |
|
|
Ttelmah Guest
|
|
Posted: Sun May 28, 2006 3:04 am |
|
|
Good news here is that the 3440, is one of the 'good' transceivers, that is designed to give a 'idle' out, when the bus is not driven. As a mild comment, normally RS485, uses 100R terminators, not 120R. 120R is used, when you provide a bias to the bus with two 1200R resistors as well, with the parallel resistance of 120, with 2*1200, giving the required 100R. However this is unlikely to cause problems over short runs.
You are presumably aware, that the bus _must_ be terminated at each end, and _nowhere else_.
The CCS implementation tries to resync, to an extent, by making any failure go to the checksum code, which then sets the state back to zero, with a failure. This then pulls a 'source', and 'to' value, and if the 'to' does not match, it should keep retrying. It is only a 'demo' though, and as such it is possible, if a data packet retrieved like this, kept containing legitimate 'to' values, the system could get into an infinite loop. Unless the data packets are repeated many times with the same contents, it should recover eventually as the data changes. The speed of recovery, will depend on the relationship between the packet 'length', and the number of bytes pulled on a retry. If (for instance), the complete stream (header+data), happens to be an even multiple of the number of bytes retrieved in the retry 'loop', then if the system gets on byte out of sync, it would be possible for it never to recover. Hence it is worth trying the experiment, of deliberately altering your packet length by one, and seeing if this helps recovery. Also making sure that there are gaps between the packets (to allow for recovery if a bit is missed).
Best Wishes |
|
|
Jim Guest
|
|
Posted: Sun May 28, 2006 4:30 pm |
|
|
hi,
Many thanks Ttelmah for the explainations and infos. I modified the code so that the message format has a start-of-message pattern. It helps to re-synch very quickly. So, I no longer see any "stuck" or "hang"...
About the bias thing..why we need to give the bus a 200 mV biased voltage. I thought if there is a 200 mV difference between the TX and RX, then the chip will assume that a bit is being transmissted. So if we give the bus a 200 mV bias, then the buss will never be in IDLE state.???
Jim |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Mon May 29, 2006 6:13 am |
|
|
Quote: |
About the bias thing..why we need to give the bus a 200 mV biased voltage. I thought if there is a 200 mV difference between the TX and RX, then the chip will assume that a bit is being transmissted.
|
When an RS-485 network is in idle state, all nodes are in listen (receive) mode. Under this
condition there are no active drivers on the network, so the state of the lines are unknown.
By adopted convention, the RS485 lines are labeled and named "A" and "B" respectively.
Bias resistors are applied only to force the data lines to the idle condition (OFF STATE)
while the node is floating, generating a DC bias current in the network to maintain a
minimum of 200mV between the B and A data lines. The value of the bias resistors will
depends of the number of nodes wired in the network.
Quote: |
So if we give the bus a 200 mV bias, then the buss will never be in IDLE state.???
|
Nop exactly.
Idle doesn�t mean "nothing" nor "equal", it is a know and stable OFF state.
As stated, the problem is when the lines are floating in its high impedance state, they can
adopt an indeterminated level.
When the "A" terminal of the driver is negative with respect to the "B" terminal,
the line is in a binary 1 (MARK or OFF) state.
When the "A" terminal of the driver is positive with respect to the "B" terminal,
the line is in a binary 0 (SPACE or ON) state.
Humberto |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|