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

another RS232 issue

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







another RS232 issue
PostPosted: Sun Feb 01, 2004 7:47 am     Reply with quote

Hello all,

I've been experiencing a problem receiving data on the HW RS232 port on the PIC16F877A. Basically I have a do-while loop that continue to receive data from the RS232 port.

The first time throgh the do-while loop works fine. But when I renter the loop the second time the getc() function seems to lock up. I ran the debugger and found that the microcode is stuck in an infinite loop checking for the data ready flag to be set on the Rs232 register.

Do I need to reinitialize the RS232 port for each cycle of the do-while loop ? Any thought's would be appreciated.

I also have a quick question about satnd alone programs. From my understaning all you have to do is remove the "#device ICD=TRUE: statement and the program should compile as a stand alone program. When i do this however my program only seems to run up to the first line of code in my main() function and then locks up. I also noticed that I can still use the ICD to execute the program even though it should have been disabled.

Thanks again for your help.
Humberto



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

View user's profile Send private message

PostPosted: Sun Feb 01, 2004 8:22 am     Reply with quote

sapy44,

Post your code and the whole info needed to give us a chance to help you.

Regards,

Humberto
sapy44



Joined: 01 Feb 2004
Posts: 19
Location: Cedar Rapids, IA

View user's profile Send private message MSN Messenger

some sample code
PostPosted: Sun Feb 01, 2004 5:20 pm     Reply with quote

Ok, Humberto asked for some example code so here goes.

do {

do {
opr1=getc();
opr2=getc();
} while( !(opr1 == 'M' && opr2 == 'C');
/* loops until detecting "MC" in the incoming data stream */

for(i=0;i<63;i++)
data[i]=getc();
// after detecting "MC" then collect the next 63 characters

vel = atoi(data[23]);


if (vel < 2)
stop_counter++;

if(stop_counter > 10)
done = TRUE;

} while(done); //continues looping until stop_counter reaches 10


The first time throgh the outer do-while loop the getc() functions work fine. But after rentering the outer do-while loop the second time the program hangs on the first getc() inside the nested do-while. A look at the assembly code using the debugger shows that the programm hangs because when it checks the RX data ready ready bit it's not getting set. So it just it hangs because it cannot detect that bit getting set with the incomming data.


Do I need to reinitialize the RS232 port beteween loops ? If not, then what could be the problem that causes the getc() to hang the second time through the loop? Any suggestions welcome. Thanks.
Humberto



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

View user's profile Send private message

PostPosted: Sun Feb 01, 2004 7:34 pm     Reply with quote

sapy44 wrote:

Code:

do {

   do {
       opr1=getc();
       opr2=getc();
      } while( !(opr1 == 'M' && opr2 == 'C');
/* loops until detecting "MC" in the incoming data stream */

   for( i=0; i<63; i++ )
       data[i]=getc();
// after detecting "MC" then collect the next 63 characters

   vel = atoi(data[23]);

   if (vel < 2)
       stop_counter++;

   if(stop_counter > 10)
      done = TRUE;

  } while(done); //continues looping until stop_counter reaches 10



Assuming the code you sent is complete, itīs not a good practice to store an incoming string waiting for two consecutive chars into a conditional loop without getting stuck by hardware buffer overruns.

A software receive buffer is a better way to achieve this and you control it toggling interrupts. In the isr() try to catch your char_ID (opr1 & opr2) and set the buffer pointer to start the storing the incoming 63 chars, when the software buffer is full just do the buffer reading in your main.

Code:

#use rs232(baud=your_speed,xmit=PIN_C6,
rcv=PIN_C7,errors) // Include the "errors" parameter if you are using hardware UART to handle framing errors.

#define RX_SIZE 64         // buffer for serial
reception
#define opr1    'M'       
#define opr2    'C'
 
byte rxbuffer[RX_SIZE];    // RS232 serial RX buffer
byte char_index  = 0;      // RS232 RX data IN index

#int_rda
void rda_isr(void)
{
byte tmpByte, tmp1;
   
   if( !StartStoringInBuffer )
     {
      tmpByte = getc();    // Store incoming byte

      if(opr1 == tmpByte)
        {
         tmp1 = tmpByte;   //Copy to tmp1
        }
      if(opr1 == tmp1) && ( opr2 == tmpByte))
        {
         StartStoringInBuffer = TRUE;
         char_index  = 0; // Initialize index
        }
     }
   
   if( StartStoringInBuffer )
     {
      rxbuffer[char_index] = getc();
      char_index = ( char_index + 1 ) % RX_SIZE ;

      if( char_index == RX_SIZE )
        {
         Buffer_full = TRUE;
        }
     }
 
void main()
{
int n;

  while(1)
       {
        enable_interrupts(INT_RDA);
        enable_interrupts(GLOBAL);
 
//your other task ...
 
        if( Buffer_full )
          {
           disable_interrupts(INT_RDA);
           StartStoringInBuffer = FALSE;
           Buffer_full = FALSE;
           //Read the buffer & your stuffs...
           for( n=0; n <= RX_SIZE; n++ )
              printf("%C",rxbuffer[n]);
          }     
       }
}


Advice: No time to test it! just tell me your results.

Regards

Humberto
SherpaDoug



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

View user's profile Send private message

PostPosted: Mon Feb 02, 2004 8:28 am     Reply with quote

do {
do {
opr1=getc();
opr2=getc();
} while( !(opr1 == 'M' && opr2 == 'C');
/* loops until detecting "MC" in the incoming data stream */

This seems like a very fragile way to detect the start of your message. If you miss a single character in the serial input you may never recover. Instead try:

do{
do{
if (kbhit()){
if (getch() == 'M'){
if (getch() == 'C'){
<Do Stuff>
}
}
}

This way a lost character or a single extra character due to noise will caus a loss of one or two records, but you will eventually be able to rcover.
_________________
The search for better is endless. Instead simply find very good and get the job done.
sapy44



Joined: 01 Feb 2004
Posts: 19
Location: Cedar Rapids, IA

View user's profile Send private message MSN Messenger

some clarification
PostPosted: Mon Feb 02, 2004 4:09 pm     Reply with quote

I'd like to as some more detail as to the operation of the RS232 port capture that I'm attempting. The data comming in over the RS232 is continous and periodic. Even if I don't catch the first "RM" it will repeat again in less than a second so I'm sure to catch it at some point.

I don realize now that I do need to content with hardware overflow issues, especially since data is alaways comming on over the RS232 port. Humberto's idea of using interrputs seems like a good solution. However, is the isr_rda interrupt routine defined for just the hardware UART or does it also apply to a software RS232 port ?

Also, if anyone has some idea as to why I can't get a program to run properly on it's on w/o having to use the ICD to run it please let me know. Thanks again.
Humberto



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

View user's profile Send private message

PostPosted: Tue Feb 03, 2004 10:34 am     Reply with quote

sapy44 wrote:

Quote:

However, is the isr_rda interrupt routine defined for just the hardware UART or does it also apply to a software RS232 port ?


When you writte code for a device that has a built in USART (like 16F877) you have to specify the XMIT=pin and RCV=pin with #USE RS232 directive, then the compiler generates the appropriate code for the situation.
If you are using the PINS that are connected internally to the SPI block , the hardware UART is used. Check your micro pin outs.
If you are using all other PINS you should generate code to bit-bang/sample the data, namelly software UART.

Remember that you must also have a #USE DELAY() before it.

#USE RS232(BAUD=9600,XMIT=PIN_C6,RCV=PIN_C7)


Sappy44, take a time to search in this forum, there are hundredīs of samples from where you will learn about this issue.

regards,

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