CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

rs485 communication problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
WILLEY_85



Joined: 06 Jul 2009
Posts: 3

View user's profile Send private message MSN Messenger

rs485 communication problem
PostPosted: Tue Aug 11, 2009 1:01 am     Reply with quote

Hi all,

I am new to PIC. I currently want to build a small system (school project). In this project, I would like to make 2 microcontrollers communicate with each other via rs485. However, the method I used is not working. Therefore, I hope the experts here would help me to solve my problems.

The system is:
1. using ccs provided rs485.c driver
2. using sn75176BP
3. using PIC18F4620

My question is -- is the built-in #use rs232 capable to interpret the signal sent by sn75176B? Because the PIC keep on receiving rubbish from the data line. Any suggestion? Thanks Smile
Ttelmah
Guest







PostPosted: Tue Aug 11, 2009 4:36 am     Reply with quote

Hopefully, you mean you have a pair of 75176's.
The sequence should be:

TTL serial (PIC)
75176 to RS485
RS485 back to TTL serial with another 75176
TTL serial into PIC.

You may though be experiencing the other common problem with RS485. Line biasing.

If you turn off the transmitter, when not sending (as is required if you are intending to use the line bidirecionally), what happens to the bus?. What generally happens, is that it floats, and you receive garbage. To get round this, you need to ensure that your line termination, also 'biases' the bus to the 'off' state. So, instead of terminating the bus with 100R at each end, you use a little 'network', comprising a 1.2KR to +5v, to the first line (A), a 120R between the lines (A-B), and a 1.2KR to the GND. This gives the required 100R (electrically the three resistors are seen as in parallel), but also applies a small voltage to the bus to keep it from floating.

Some RS485 line receivers, are designed to ensure that an 'undriven' bus, gives the required 5v out on the TTL connection. Also some companies do line terminators that apply this same bias.

Without this bias, your chips will continually receive garbage when not sending, and the system is not likely to work....

Best Wishes
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Tue Aug 11, 2009 8:30 am     Reply with quote

You also need to make sure you are enabling the transmitter and receiver at the proper time on the 75176. The receiver is active low and the transmitter is active high. Your PIC has to control this device properly when you when to transmit and receive.
WILLEY_85



Joined: 06 Jul 2009
Posts: 3

View user's profile Send private message MSN Messenger

PostPosted: Tue Aug 11, 2009 10:52 pm     Reply with quote

Thanks for the immediate reply. Very Happy

I used a pair of sn75176 to transmit signal.

Quote:
If you turn off the transmitter, when not sending (as is required if you are intending to use the line bidirecionally), what happens to the bus?.


I have tried this, when turned of the transmitter, the receiver will received 0 all the time. Is this mean the communication is free of noise?

I will try to add in the resistor.

But, I have another question.
I have connected the transmitter to receiver (via rs485) and then the receiver will display the input to computer (rs232). This is for me to see what is going on the the rs485 communication. The coding is as follow

For transmitter
Code:

#include <18F4620.h>
#device *=16
#fuses HS, NOWDT, NOLVP, NOBROWNOUT, NOPROTECT, PUT
#use delay(clock=4000000)

// Define the destination's RS485 ID
#define RS485_ID 0x10
#define RS485_RX_PIN pin_a4      //define the pin connection
#define RS485_TX_PIN pin_c5
#define RS485_Enable_pin pin_b5
#define RS485_Rx_Enable pin_b5

#use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, force_sw, errors, stream=RS485)
#use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, force_sw, multi_master, errors, stream=RS485_CD)

#define RCV_OFF () {disable_interrupts(INT_EXT);}

void main ()
{
   int i,x;
   char value;

   while(1)
   {
      
   fputs("~021", RS485_CD);      // send the string to rs485
   fputs("#020+08.000", RS485_CD);

   }
}
   



for receiver
Code:

#include <18F4620.h>
#device *=16
#fuses HS, NOWDT, NOLVP, NOBROWNOUT, NOPROTECT, PUT
#use delay(clock=4000000)

// Define the destination's RS485 ID
#define RS485_ID 0x11
#define RS485_RX_PIN pin_a4      //define the pin connection
#define RS485_TX_PIN pin_c5
#define RS485_Enable_pin pin_b5
#define RS485_Rx_Enable pin_b5

#use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, force_sw, errors, stream=RS485)

#define RCV_OFF () {disable_interrupts(INT_EXT);}

void main ()
{
   char value[5];
   int i=0;
   int x;
   set_tris_A(0xff);
   
   #use rs232 (baud=9600, xmit=pin_c6, parity=N, rcv=pin_c7,bits=8)
   putc('\n');                       // put character on PC
   puts("waiting ");
   putc('\n');

   while(1)
   {
      while(kbhit(rs485))      // when a character is available
      {
         value[i]= fgetc(rs485);    // receive character from rs485
         #use rs232 (baud=9600, xmit=pin_c6, parity=N, rcv=pin_c7,bits=8)
         printf("  %c the value \n",value[i]);   // print to PC
         i++;
      }
      #use rs232 (baud=9600, xmit=pin_c6, parity=N, rcv=pin_c7,bits=8)
      printf("  ------------");
   
   }
}
   


Above is my simple code. My problem face in the system is:
1. When transmitter is off. The PC will display <0>.
2. When I transmit the data. The PC will display garbage.

Hope this may give you an idea what i am facing.

For enabling the transmitter and receiver. I think the #use rs232 will push the pin high to transmit. Is it anything wrong with my code? Or is it just because of noise?
arunb



Joined: 08 Sep 2003
Posts: 492
Location: India

View user's profile Send private message Send e-mail

RE:
PostPosted: Wed Aug 12, 2009 1:13 am     Reply with quote

Why don't you use hardware usart instead of software???
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Wed Aug 12, 2009 8:38 am     Reply with quote

Sorry, I didn't see the ENABLE option before in your #use rs232 statements.

Those are not simple test programs, they are messy to say the least. You should not declare a #use rs232 statement inside the main loop multiple times like that. Actually you should not declare it anywhere but the top of the program.

I recommend you take arunb's advice and use hardware UART to keep things as simple as possible.

One more thing about RS485 transceiver chips, like anything else you get what you pay for. I would pay more for something decent like a MAX487 which work splendidly without any need for any bias resistors.
WILLEY_85



Joined: 06 Jul 2009
Posts: 3

View user's profile Send private message MSN Messenger

PostPosted: Thu Aug 13, 2009 5:32 am     Reply with quote

Thanks for the advice. That is really a good suggestion to use hardware uart. Now, after some testing, the problem is really due to the line terminator. Thanks. Laughing
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Thu Aug 13, 2009 7:16 am     Reply with quote

WILLEY_85 wrote:

Quote:
If you turn off the transmitter, when not sending (as is required if you are intending to use the line bidirecionally), what happens to the bus?.


I have tried this, when turned of the transmitter, the receiver will received 0 all the time. Is this mean the communication is free of noise?


This sounds like when the line is idle (transmitter off) it sits at Start bit level (data 0). It should sit at Stop bit level and a getc() should wait forever. You should have a string of Stop bits, until data is sent when you get a Start bit, 8 data bits, and one or more Stop bits till the next byte is ready (which could be milliseconds or months).

The idle state is best set by the terminating resistors. Some manufacturers chips interpret 0.0V as a valid Stop bit, but that is NOT in the 485 spec.
_________________
The search for better is endless. Instead simply find very good and get the job done.
a3ka2000



Joined: 26 Feb 2010
Posts: 11

View user's profile Send private message

Re: RE:
PostPosted: Thu Mar 11, 2010 11:07 pm     Reply with quote

arunb wrote:
Why don't you use hardware usart instead of software???


Hi hi, is there any reason to use hardware USART? I'm working with RS485 from normal I/O pins of PIC16F84A (simple primitive PIC). It doesn't have dedicated RS485 pins.

I'm facing a problem actually. If I connect more than 2 devices (with PIC on board) to the master, I somehow experienced intermittent when I execute "printf" statement from the PIC back to the PC.

I guarantee that the device is working one by one. No issue on hardware assignment, etc. But I doubt whether need to put 120 ohms resistor, but my cable length is less than 2 m.
arunb



Joined: 08 Sep 2003
Posts: 492
Location: India

View user's profile Send private message Send e-mail

RE:
PostPosted: Fri Mar 12, 2010 1:15 am     Reply with quote

With a dedicated USART port you can make use of interrupts, this makes the software more efficient.

For example the RDA interrupt can be enabled to receive data.

thanks
arunb
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

Re: RE:
PostPosted: Fri Mar 12, 2010 8:05 am     Reply with quote

a3ka2000 wrote:
arunb wrote:
Why don't you use hardware usart instead of software???


Hi hi, is there any reason to use hardware USART? I'm working with RS485 from normal I/O pins of PIC16F84A (simple primitive PIC). It doesn't have dedicated RS485 pins.

I'm facing a problem actually. If I connect more than 2 devices (with PIC on board) to the master, I somehow experienced intermittent when I execute "printf" statement from the PIC back to the PC.

I guarantee that the device is working one by one. No issue on hardware assignment, etc. But I doubt whether need to put 120 ohms resistor, but my cable length is less than 2 m.


You don't need termination assuming your data rate is reasonably low.
The 'rule of thumb', is that termination is not needed, if the propogation delay is less than 0.5 bit time. At low rates like 9600bps, you don't even need termination really out at lengths like a mile!....

However you will still need biasing.

This is a 'key' difference between RS232, and RS485. On RS232, a line floating at 0v, is defined as giving the 'idle state. On RS485, a signal below +/-200mV, will (normally - some receiver chips deliberately break this to avoid the problem....), leave the receiver giving the last bit value received.
With an unterminated network, with only a few nodes, something like 10KR, from signal A to ground, and the same from signal B to +5v, will be comfortably enough.

It is difficult to know what your problem may be, since you don't really describe the network well enough. PC is master?. It addresses slaves?. They monitor the line looking for what?. Are you sure your data format cannot contain a devices address?.

Best Wishes
a3ka2000



Joined: 26 Feb 2010
Posts: 11

View user's profile Send private message

PostPosted: Wed Mar 24, 2010 1:09 am     Reply with quote

Hi thanks Ttelmah for the reply.

My master is PC. From one of its serial COM port, I used RS232-RS485 converter. From the converter output, I connect in chain 6-7 RS-485 devices or boards. Each boards contain pic16f84A and is assigned slave addresses, e.g. '02'.

From my PC, I broadcast a command based on the particular board I want to control, e.g. to board '02' I send certain command and expecting readback.

The boards have MAX483 that (I assume) take care the RS-485 hardware requirement, e.g. pull-up, etc.

thanks!

Code:
void main() {
   //printf("Communication via RS-485\r\n");
   output_b (0x00);      // Initialize
   output_high(PIN_A0);    // Set MAX-483 as a driver to transmit to PC
   output_high(PIN_A1);   

   while(1) {
       output_low(PIN_A0);         // Disable back DE, enable RE, then MAX-483 is a receiver!
      gets(text);             // Get the text from UART bus            
      output_high(PIN_A0);      // Enable DE, disable RE, to set MAX-483 chip back as a driver!
      rec_data();
   }
} // end of main
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Wed Mar 24, 2010 3:30 am     Reply with quote

The MAX483, _does not bias the bus_. You _must_ do this somewhere.

Second, how have you got the enable pin connected.
There are two ways of doing this:
1) The PIC enable pin connects to the chip's 'DE' pin only. Whenever you send anything, the PIC will receive this.
2) The PIC enable pin connects to both the 'DE', and the '/RE' pin. You then need a pll up resistor (perhaps 10K), from the RO pin to +5v. Your PIC will then not receive what it sends.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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