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 sending text (sometimes work and sometimes not)

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



Joined: 27 Aug 2012
Posts: 23

View user's profile Send private message

RS485 sending text (sometimes work and sometimes not)
PostPosted: Mon Aug 27, 2012 2:54 pm     Reply with quote

Hello,

I'm trying to write a little project to make a communication between few PIC 16F628A and one PC.

communication diagram (for test only one PC and only one PIC) is below:

PC <-> MAX232 <-> MAX485 <-> ........<->MAX485<->PIC

My code is really simple:

Code:

#include <16F628A.h>
#fuses XT, NOPROTECT, NOCPD, NOLVP, NOWDT, NOBROWNOUT, PUT
#use delay(clock=4M)
#use rs232(baud=9600, xmit=PIN_B2, enable=PIN_B3, rcv=PIN_B1, errors, stream=PC)

void main()
{

   trisa = 0;
   porta = 0;

   int8 character;
   fputc('x',PC);                           //print x char
   fprintf(PC,"test_1\r\n");                  //print string
   while(TRUE)
   {
      if(kbhit())                        //if receive something
      {
         output_toggle(PIN_A0);            //toggle LED (it works)
         character=fgetc(PC);            //get char
      
         fprintf(PC,"test_2\r\n");         // doesn't work
         fputc(character,PC);            // doesn't work
         fputc('x',PC);               // doesn't work
      }
   }
}



I use enable PIN in #use rs232.

My problem is that first fputc and fprintf sends data to PC correctly but when program comes into while loop it waits for some data from PC. When I send one character, LED on PIN_A0 toggles but nothing is sent to PC. I tried to send more data and LED blinks but no data is sent.

Why before while loop I can send data but inside I can not?

Can someone help me?

Thanks in advance
Simon
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Aug 27, 2012 3:21 pm     Reply with quote

Get creative. Do some experiments. Run a test program that doesn't
use the while() loop or most of the code inside it:
Code:

void main()
{
fputc('x',PC);                       
fprintf(PC,"test_1\r\n");       

delay_ms(500);

fputc('y',PC);                   
fprintf(PC,"test_2\r\n");   

while(1);
}


Run a different test with the while() loop, but without the kbhit() test:
Code:

while(TRUE)
   {
     output_toggle(PIN_A0); 
     character=fgetc(PC);     
       
     fprintf(PC,"test_2\r\n"); 
     fputc(character,PC);       
     fputc('x',PC);               
    }


Run another test without the fgetc(). See if that works.
Code:

while(TRUE)
   {
     output_toggle(PIN_A0);
       
     fprintf(PC,"test_2\r\n");       
     fputc(character,PC);             
     fputc('x',PC);               

     delay_ms(500);
    }


In other words, simplify the program and cut out parts of it, to see
which line(s) are the problem.


The two lines below are unnecessary, because the output_toggle(PIN_A0)
function automatically sets the TRIS for Pin A0 to be an output pin:
Quote:

trisa = 0;
porta = 0;



All variable declarations should go at the start of the function. All lines
of code should be placed after the variable declarations:
Quote:

void main()
{
trisa = 0;
porta = 0;

int8 character; // Move this to the start of main()
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Tue Aug 28, 2012 1:21 am     Reply with quote

First, how is the PC controlling the enable it's end?. What circuitry/code involved?.
With standard 2 wire RS485, comms is 'half duplex', with only one end able to talk at a time. I'd suspect that when you send data from the PC, _it_ is setting it's enable to take over the bus, and is then not releasing it. Normally if you are using some of the off the shelf packages that are supplies as 'demos' for RS485 cards, they take command when characters are sent, and stay holding the bus, until an ETX, or EOL is sent.
Second comment (not the problem, but may cause problems in the future), bus termination. RS485, is designed to have termination at each end of the bus. Also (depending on the drivers you are using), the termination should be designed to bias the bus to the 'off' state. Texas have some good application notes about this.
As PCM programmer says, start a little simpler. Verify you can send in each direction, and get 'valid'' data, and that the bus goes idle when you are not sending. I suspect this is the problem at the PC end.

Best Wishes
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Tue Aug 28, 2012 7:54 am     Reply with quote

If you are using stream names, in this case you're calling the serial stream "PC", then you should use that name in the kbhit call, or anywhere else to do with serial/RS232 comms:

Code:

      if(kbhit(PC))                        //if receive something
      {
      ...
      }


RF Developer
gpsmikey



Joined: 16 Nov 2010
Posts: 588
Location: Kirkland, WA

View user's profile Send private message

PostPosted: Tue Aug 28, 2012 8:17 am     Reply with quote

One thing I didn't see (although I have not had my coffee yet either) is a delay after sending before you turn off the enable on the transmit side. My favorite trick is to send a character to the uart, then disable the output so I can listen for the next message or whatever forgetting that you need to delay a character time at least so it can be shifted out.

mikey
_________________
mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Tue Aug 28, 2012 8:44 am     Reply with quote

If you use the CCS 'enable' option in #USE RS232, it waits for the character to be sent, before disabling this.
I'm still most suspicious of the 'enable' handling at the PC end... Smile

Best Wishes
lisek_lichu



Joined: 27 Aug 2012
Posts: 23

View user's profile Send private message

PostPosted: Tue Aug 28, 2012 2:17 pm     Reply with quote

Thanks for fast reply.


PCM programmer wrote:
Get creative. Do some experiments. Run a test program that doesn't
use the while() loop or most of the code inside it:
Code:

void main()
{
fputc('x',PC);                       
fprintf(PC,"test_1\r\n");       

delay_ms(500);

fputc('y',PC);                   
fprintf(PC,"test_2\r\n");   

while(1);
}


I did a lot of experiments. with different loop types, wuth and without loop but for me most strange is that before while loop fputs work, inside loop kbhit works even without stream specified in it beacuse LED was toggling only when i sent some char. But function fput and fprintf doesn't work inside while loop.

Your first program runs correctly. PC received xtest_1 ytest_2





PCM programmer wrote:
Run a different test with the while() loop, but without the kbhit() test:
Code:

while(TRUE)
   {
     output_toggle(PIN_A0); 
     character=fgetc(PC);     
       
     fprintf(PC,"test_2\r\n"); 
     fputc(character,PC);       
     fputc('x',PC);               
    }


This program toggle LED every time i send some character from PC to PIC but no character is returned to PC.



PCM programmer wrote:

Run another test without the fgetc(). See if that works.
Code:

character = 'b';
while(TRUE)
   {
     output_toggle(PIN_A0);
       
     fprintf(PC,"test_2\r\n");       
     fputc(character,PC);             
     fputc('x',PC);               

     delay_ms(500);
    }


this program runs correctly. It's toggle LED, print "test_2" send "b" character and wait 0,5s an run again




PCM programmer wrote:

In other words, simplify the program and cut out parts of it, to see
which line(s) are the problem.


The two lines below are unnecessary, because the output_toggle(PIN_A0)
function automatically sets the TRIS for Pin A0 to be an output pin:
Quote:

trisa = 0;
porta = 0;



Thanks i was wondering if it is ok or not.


PCM programmer wrote:

All variable declarations should go at the start of the function. All lines
of code should be placed after the variable declarations:
Quote:

void main()
{
trisa = 0;
porta = 0;

int8 character; // Move this to the start of main()


thanks a lot for those informations. I will try to find this problem
lisek_lichu



Joined: 27 Aug 2012
Posts: 23

View user's profile Send private message

PostPosted: Tue Aug 28, 2012 2:29 pm     Reply with quote

Ttelmah wrote:
First, how is the PC controlling the enable it's end?. What circuitry/code involved?.

I use RTC signal from PC. I have hardware COM port not adapter from USB to RS232.
I use max232 to fit voltage level for TX RX and RTC. also i use Bray terminal for communication with PC and there is an option "Handshaking" where You can set "RTS on TX" and also "invert" so after that wnen a byte is sent RTC is set during this transmission




Ttelmah wrote:

With standard 2 wire RS485, comms is 'half duplex', with only one end able to talk at a time. I'd suspect that when you send data from the PC, _it_ is setting it's enable to take over the bus, and is then not releasing it.

I understand that and I also put a LED with 1k resistor on RTC from PC so I can see when PC has RTC high and after sending a byte it is going low so i think it is ok

Ttelmah wrote:

Normally if you are using some of the off the shelf packages that are supplies as 'demos' for RS485 cards, they take command when characters are sent, and stay holding the bus, until an ETX, or EOL is sent.

Hmm I didn't supose that maybe this is the reason



Ttelmah wrote:

Second comment (not the problem, but may cause problems in the future), bus termination. RS485, is designed to have termination at each end of the bus. Also (depending on the drivers you are using), the termination should be designed to bias the bus to the 'off' state. Texas have some good application notes about this.

In first test i had terminations but nothing work then. so after I get if out some things start to work. but now You said that termination have to set bus to "off" state?? I read in one book that it have to be set to "on"!!
And that was not logical for me hmmmm.
I put a resistor 240ohms from vcc to A and from B to GND and between A and B i put 120ohm rezistor so in this situation the bus was forced to be set to "ON"

hmmmm



Ttelmah wrote:

As PCM programmer says, start a little simpler. Verify you can send in each direction, and get 'valid'' data, and that the bus goes idle when you are not sending. I suspect this is the problem at the PC end.

Best Wishes


I realy do a lot of modification to simplify as much as it is possible. but i have to do mooooore Smile
lisek_lichu



Joined: 27 Aug 2012
Posts: 23

View user's profile Send private message

PostPosted: Tue Aug 28, 2012 2:30 pm     Reply with quote

RF_Developer wrote:
If you are using stream names, in this case you're calling the serial stream "PC", then you should use that name in the kbhit call, or anywhere else to do with serial/RS232 comms:

Code:

      if(kbhit(PC))                        //if receive something
      {
      ...
      }


RF Developer


I tried with and without and in this simple programs it doesn't matter. But I will remember about it in next programs.
Thanks
lisek_lichu



Joined: 27 Aug 2012
Posts: 23

View user's profile Send private message

PostPosted: Tue Aug 28, 2012 2:33 pm     Reply with quote

Ttelmah wrote:
If you use the CCS 'enable' option in #USE RS232, it waits for the character to be sent, before disabling this.
I'm still most suspicious of the 'enable' handling at the PC end... Smile

Best Wishes


I have written few post before how i have it done. Check me maybe I do it wrong but normally when i sent text it works, but when I do it in while loop everything works but not sending a text to PC.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Tue Aug 28, 2012 2:52 pm     Reply with quote

Remember the 'off' state on the RS485 bus, gives 'high' at the PIC. This is where the 'on' confusion comes.
If you are disabling the receive on the transceiver, when you send, then you also need a pull-up resistor on the line from the transceiver to the RX pin on the PIC. If not, then you will also receive every character you send.

Best Wishes
lisek_lichu



Joined: 27 Aug 2012
Posts: 23

View user's profile Send private message

PostPosted: Tue Aug 28, 2012 2:55 pm     Reply with quote

Ttelmah wrote:
Remember the 'off' state on the RS485 bus, gives 'high' at the PIC. This is where the 'on' confusion comes.
If you are disabling the receive on the transceiver, when you send, then you also need a pull-up resistor on the line from the transceiver to the RX pin on the PIC. If not, then you will also receive every character you send.

Best Wishes


Hmmm I don't know if I understand it correctly. Can You explain it more detail?

Lisek
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Wed Aug 29, 2012 1:32 am     Reply with quote

The problem is if you talk 0/1, or high/low, versus idle/active.

In TTL async serial, the 'idle' state, is 5v at the chip. So 'high', or '1', is the idle state. When nothing is being received, this line needs to 'idle high'.
Now over RS485, the 'idle' state, is to have the 'A' line at least 200mV above the 'B' line. The bus is defined, so that if this is not true, and the lines are just allowed to float, the receiver output, will hold the last level received, which can result in you continuously receiving zero bytes....

Now separately you have the control of the RS485 buffer. There are two lines, /RE. and DE. You can wire two different ways:
The first, you leave the receiver permanently enabled, and just turn the driver on/off when you want to talk. Done this way, you will receive every character you send (which can be a diagnostic that the data is going onto the bus), but means your software has to be able to cope with this.
For the second, you wire the /RE, and DE lines together, and turn off the receiver, when transmitting. Key here is that since you are turning the receiver 'off', _you_ have to ensure that the RO line is pulled high (idle) when not driven by the receiver, or you _will_ start receiving spurious characters as the line floats.

Now a third thing. Timing of the 'enable' line.
The chip itself has 1.99999 characters of hardware buffering in the transmit. One actual 'buffer', and the output shift register. The CCS code, when asked to control the 'enable' line, checks the TRMT bit (transmit shift register empty), and only raises the 'enable', when this goes true. This means the code has to wait for the characters to send, rather than just getting on while the hardware transmits. If you want to control the line yourself, you need to do the same, or provide a delay (the latter is slightly more dangerous, since if too short, the characters may not finish transmitting, while if too long, you may miss the start of a reply, if this is really fast). A delay is OK, provided there is a slight pause before the other end replies.

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