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 support@ccsinfo.com

2 PICS communicating via RS232- Problems

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



Joined: 17 May 2005
Posts: 213

View user's profile Send private message

2 PICS communicating via RS232- Problems
PostPosted: Mon Aug 06, 2007 7:15 am     Reply with quote

Hi

I have two PICS communicating via RS232 over 15meters of cable. I boost the signal using a MAX232 on both ends.
I am trying to display time using the 2 PICS by having one PIC send a printf with the minutes and seconds to the second PIC.

I have an interrupt on the second PIC.

What I observe is that at first the two PICs display the same time, although the 2nd PIC is approximatley 1/2 a second slower- but this delay is variable. Then after about 20 seconds (time also variable) of transmissions, the second PIC gets "stuck", ie it ceases to receive.

I was wondering if anyone can tell me what I am doing wrong. Is it possible that the interrupt on the 2nd PIC is getting confused/ overwritten in some way?

Thank you in advance for your help.
a.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Mon Aug 06, 2007 7:34 am     Reply with quote

Hi Arrow,
After this many posts you should know we are very bad in mind reading. Please post a small and compilable program or at the least the important parts of your slave ISR, including all buffer variables and #rs232 declaration.
arrow



Joined: 17 May 2005
Posts: 213

View user's profile Send private message

PostPosted: Mon Aug 06, 2007 7:50 am     Reply with quote

Hi Ckielstra

You are 100% right, here is part of the code on the receiving end. (For brevity I have removed some of the lengthy definitions).

Thank you
a.

Code:

#include <16F873.H>

#fuses   HS,PROTECT,NOWDT,NOLVP,PUT

#use delay(clock=20000000)
#use rs232(baud=19200, XMIT=PIN_C6, rcv=PIN_C7, ERRORS)
//=============================
//***74HCT595 PARAMETERS
#define SH_CLOCK PIN_A1
#define STROBE   PIN_A2
#define DATA     PIN_A0

#define NUMBER_OF_CHARS       3
//------------------------------------------------
#byte port_b=6
//=============================
//***COMMAND Parameters
int str[NUMBER_OF_CHARS];
short blink;
//=============================
//***TIME PARAMETERS
int minutes;
int seconds;

//***FUNCTION PROTOTYPES
void displayIt();
//==================================================
//***RS232 function
#int_rda
void RS232(){
   char bbb;
   int seconds1=0,seconds2=0;
   int tempMinutes;
   bbb = getc();
   blink=true;
   if(bbb=='C' || bbb=='c'){
here:;
      if(bbb=='c')
         blink=false;
      bbb=getc();
      if(bbb=='C' || bbb=='c')
         goto here;
      tempMinutes=bbb-48;
      bbb=getc();
      if(bbb=='C'|| bbb=='c')
         goto here;
      seconds1=bbb-48;
      bbb=getc();
      if(bbb=='C'|| bbb=='c')
         goto here;
      seconds2=bbb-48;
      if(tempMinutes >=0 && tempMinutes<10){
         if(seconds1>=0 && seconds1<6){
            if(seconds2>=0 && seconds2<10){
               minutes = tempMinutes;
               seconds=seconds1*10+seconds2;
            }
         }
      }
   }
}
//==================================================
void write_expanded_outputs(int row) {
....
}
//=============================
void displayIt(){
...
}
//=============================
main() {
   int i;
   //-------------------------
   set_tris_b(0B00000000);
   port_b = 0;
   //-------------------------
   seconds = 0;
   minutes = 0;
   //---------------------------
   blink = false;

   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
  //-------------------------
   delay_ms(1000);
  //-------------------------
   for(i=0;i<NUMBER_OF_CHARS;i++)
      str[i] = 0;
  //-------------------------
   while(true){
      displayIt();
   }
}
Ttelmah
Guest







PostPosted: Mon Aug 06, 2007 8:27 am     Reply with quote

What is the nature of your cable?. 50 metres, is pushing RS232, especially at 19200bps. You can usually stretch to this sort of length, if _shielded_ cable is used, but for unshielded cable, it is asking a lot (the specified maximum length of the 'standard', is only 50 _feet_...). It would be much better to use an interface designed for this sort of length, like RS423, or use differential signalling (for much better noise rejection), with twisted cables, and something like RS422 or 485.
As a general comment, don't use GOTO's. They are considered, rather like the 'black death', in terms of programming!...
Seriously, there are places where they may be needed, but it is usually much better to write programs without them.
You don't show your 'displayit' function, but I worry about the length of your array to hold the characters. If you want to use this as a 'string', (which the name suggests), remember that one extra character is always needed in a string, for the terminating '\0'.
As a second comment, your interrupt handler, is a good example, of how _not_ to code an interrupt!. If you just want to wait for the characters to arrive, which you are doing, you might as well just wait in the main. The _point_ about interrupts,, is they allow you to leave a 'main' program that is doing other things, to handle a hardware 'event' that has occured. You stay in the handler, long after you have dealt with the 'event', making the handler basically pointless...
A written, the code can only escape from the handler, if the pattern of characters is received perfectly. As such, with the cable length, failure is very likely indeed...

Best Wishes
arrow



Joined: 17 May 2005
Posts: 213

View user's profile Send private message

PostPosted: Mon Aug 06, 2007 8:50 am     Reply with quote

Hi Ttelmah

Thank you for your post. My cable is only 15meters (actually 12m) not 50. So I dont think I should be getting noise.

I will re-write the code to do all the processing in the main(), and avoid using the interrupt.
What happens if I am waiting for a character, it arrives but I dont read it, and then another character arrives?
Will the UART buffer be swamped?
Will the UART get jammed?
If yes, can you please tell me how to "unjam" it?

All the best
a.
SherpaDoug



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

View user's profile Send private message

PostPosted: Mon Aug 06, 2007 9:59 am     Reply with quote

15 meters is pretty close to 50 feet. Could your system function at 1200 baud for a test? If so that would tell if the cable length is a problem. 15 meters should be no problem at 1200 baud.
_________________
The search for better is endless. Instead simply find very good and get the job done.
Ttelmah
Guest







PostPosted: Mon Aug 06, 2007 10:26 am     Reply with quote

arrow wrote:
Hi Ttelmah

Thank you for your post. My cable is only 15meters (actually 12m) not 50. So I dont think I should be getting noise.

I will re-write the code to do all the processing in the main(), and avoid using the interrupt.
What happens if I am waiting for a character, it arrives but I dont read it, and then another character arrives?
Will the UART buffer be swamped?
Will the UART get jammed?
If yes, can you please tell me how to "unjam" it?

All the best
a.

ERRORS, prevents the UART locking if it is not serviced in time. There are nearly two characters of buffering (the data register, and the input shift register), so you have just under two character times to service an incoming chracter.
Why not use interrupts, but use the example in EX_SISR. Then in your main, retrieve the buffered data?. This makes loss of characters very unlikely indeed. Also look at the various 'timed GETC' implementations that have been published. Then have your search, use a state machine to retrieve the characters, and walk 'along' the required data, but drop back, if the getc times out. This way, the system will recover on the very next message, rather than possibly getting out of sync...

Best Wishes
arrow



Joined: 17 May 2005
Posts: 213

View user's profile Send private message

PostPosted: Tue Aug 07, 2007 4:02 am     Reply with quote

Hi Ttelmah

Thank you for your reply.

I have looked at the example you refer to, but I do not understand it. Can you please tell me how to give getc() say 2ms to read the data, and if it does not, or no data comes along, for it to time out?
Also, please can you tell me how to access the Error flags (if there are any) on the RS232?

Once again- thank you- I appreciate your help.
a.
Ttelmah
Guest







PostPosted: Tue Aug 07, 2007 6:17 am     Reply with quote

Code:

#define KEYHIT_DELAY (2)

char timed_bgetc() {
   long timeout;
   char retval;

   timeout=0;
   while(!bkbhit() && (++timeout< (KEYHIT_DELAY*100)))
      delay_us(10);
   if(bkbhit())
      retval = bgetc();
   else
      retval = 0;
   return(retval);
}

With the EX_SISR include file loaded first.
The timing will be slightly over 2mSec as shown (because of the time taken to perform the loop), but is probably 'close enough'.
It'll return if no character appears in the buffer inside this time, returning '0' in this case.
There is a system variable called 'RS232_ERRORS', which reflects the status of the error flags (and the ninth data bit if required).

Best Wishes
arrow



Joined: 17 May 2005
Posts: 213

View user's profile Send private message

PostPosted: Wed Aug 08, 2007 9:38 am     Reply with quote

Hi Ttelmah

Thank you for your reply.

I am now leaning to the fact that there is no problem on the receiving end.

If I may explain what I have and can then ask you a question I would appreciate it. I have a PIC16F873 connected to a MAX232 chip transmitting. The MAX232 chip is connected via a 15meter cable to a computer on which a software is running reading the COM1 port. From the same MAX232 I have a SECOND 15 meter cable going to another MAX232 chip that is connected to my receiving PIC16F873.

Now when my PC program is not running, the transmission seems to be occuring fine from one PIC to the other. I can listen using the program "TermPro" and things are all in order.

However, when I start my PC pgrogram up, the 2nd PIC receives for a while and then stops. If I close my program and open up TermPro- nothing is being received or sent!- Why?

I know this is a nebulous question- but would you have an idea as to why my PC program seems to break the commuication between my 2 PICS?
(and not in a consistent way!)

Thank you for your time and help.
a.
Ttelmah
Guest







PostPosted: Wed Aug 08, 2007 9:53 am     Reply with quote

RS232, is a one master, one slave interface. You are breaking the spec, running to two receivers. This quite commonly works, but with the amount of loading you have present, it is not going to encourage reliability...
Now, is the PC's transmit line connected to the PIC?. If so, then I'd suspect the PC is seeing errors, and sending perhaps a 'break' character to the PIC (some terminal programs will do this, to show there has been a problem). The PIC will continuously loop receiving blank data if this happens.
Switch to wiring this properly. Use RS485, if you want multiple devices on one set of lines. Currently, you are a bit like the man, driving his car over heaps of nails, and then posting the question 'why do I get punctures'...

Best Wishes
arrow



Joined: 17 May 2005
Posts: 213

View user's profile Send private message

PostPosted: Wed Aug 08, 2007 10:10 am     Reply with quote

Hi Ttelmah

Thank you- I dont really know what I am doing! It seems from what you are saying- I am building a mess!

My PC is connected to two MAX232, two PICS are connected to these MAX232's.

Just to drive further with the punctures: can the PIC detect the errors sent by the PC? and if yes, how could I do that?

Let me see if I understand what you are saying:
If I have:
(a) one MAX232 that acts as both receiver and transmitter
(b) one PC that acts as both transmitter and receiver
(c) onother MAX232 that acts only as receiver

then I have one master (PIC and MAX232) and two slaves (PC and second MAX232).
The RS232 protocol is intended for only one master and one slave.
So clearly this is not going to work!

Is this accurate?


Thank you
a.
Humberto



Joined: 08 Sep 2003
Posts: 1215
Location: Buenos Aires, La Reina del Plata

View user's profile Send private message

PostPosted: Wed Aug 08, 2007 10:38 am     Reply with quote

Quote:

The RS232 protocol is intended for only one master and one slave.
So clearly this is not going to work!

First line: YES.
Second line: NO

It should work, you have 1 Master and 1 Slave + another device which is only listening.
The point is, as Ttelmah said: "the PC is seeing some errors and sending a 'break' character
to the PIC" or some unexpected (by the Master) string or char that fire the INT_RDA
interrupt and never exit again, hence you should monitor the Tx line of the PC and
watch what´s going on and write some code in the Master Rx handler routine to
manage it properly.

Assuming you can´t access the source code of the application running in the PC, but if you
at least can parametrize it, you should disable ALL outgoing Tx mssges.


Humberto
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