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

PIC18F2620 locking up with serial data

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



Joined: 29 Mar 2010
Posts: 11

View user's profile Send private message

PIC18F2620 locking up with serial data
PostPosted: Mon Mar 29, 2010 10:26 am     Reply with quote

I have a PIC project running on a PIC18F2620 that receives one serial data stream with two distinct data messages (received once a second). The two data messages are parsed and repackaged to a single data stream and retransmitted (from a software UART about once every 3 seconds). The serial data stream is received through a MAX232A. The TTL data is received by the RX line at the PIC and a TX line at a second MAX232A where the raw received data is rebroadcast out to a second application. I have built and tested this circuit on a breadboard and an initial PCB and it worked flawlessly. Recent builds using the same components and PCB's have resulted in inconsistent behavior. The cards power up and I receive my heartbeat indicator fine, however, when incoming serial data is received, the PIC locks up (heartbeat stops). When locked up, I can scope the incoming serial data and it is still present. The odd thing is that when the PIC locks up, the second MAX232A "listening" on the TTL RX line also has problems. Even though the input is still being seen on the TX input line, the output is railed solid at -9V. With serial data being present during power-up, I’ve been having about a 99% lock-up rate (basically, every time). My bench power supply is a BK Precision 1666 DC-Regulated Power Supply set at 28V and my board power is supplied by a Lucent (or Motorola) MC010A DC-DC convertor (18-36V in & 5V out).

I have compiled and loaded the code using IDE 4.065, PCB 4.065, PCM 4.065, PCH 4.065 and more recently, I have updated to IDE 4.104, PCB 4.104, PCM 4.104, PCH 4.104 and still have problems.

Additional info: (1) I have switched to a different manufacture date code of PIC18F2620's and they seem to be more reliable, yet not perfect

(2) I removed the second MAX232A and the problem still exists

(3) I have a similar circuit running perfectly on a PIC16F876. The code on the PIC16F876 has additional lines of code for an LCD, no MCLR #fuse, and a different header file.

(4) I have recently executed the exact code on a PIC16F876, minus the MCLR #fuse, and have had no problems.

(5) I reassembled the circuit on a breadboard and I'm seeing the same issues with the PIC18F2620 and not the PIC16F876

My code is shown below with some calculations removed:

Code:

#include <18f2620.h>
#device  *=16           // Sixteen bit pointer definition
#device  icd=TRUE
#use     delay(clock=20MHZ)
#fuses   HS, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP, DEBUG, MCLR

#use rs232(STREAM=IN, XMIT=PIN_C6, RCV=PIN_C7, BAUD=19200, ERRORS)
#use rs232(STREAM=OUT, XMIT=PIN_C2, RCV=PIN_C5, BAUD=19200, ERRORS)

#use standard_io(A)
#use standard_io(B)
#use standard_io(C)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

////////////////////////////////////////////////////////////////////////////////
// Pin Definitions
////////////////////////////////////////////////////////////////////////////////

// Port B Definition

#define  RX_VALID_IND        PIN_B0   // PIN #21 RX Valid Heartbeat Indicator
#define  RX_ERROR_IND        PIN_B1   // PIN #22 RX Error Heartbeat Indicator

////////////////////////////////////////////////////////////////////////////////
// Global Variables
////////////////////////////////////////////////////////////////////////////////

char  msg[38];                // rx message temp buffer array
char  inputData[38];          // rx message array
char  no_rx_data[20];         // default no rx data array
char  wstatus;                // status of data in output stream
char  output[20];             // output stream of data
char  dlimitr[2]={'='};       // delimiter token is "="
float speed;                  // speed value
float direction;              // direction value
float temp;                   // air temp value
float pres;                   // atm value
float rh;                     // rh value
int1  gotMsg=FALSE;           // Received Message from Modem flag
int1  gotMsg2=FALSE;          // Packed message flag
int1  hrttogl=TRUE;           // Heartbeat LED status flag
int1  error=TRUE;             // rx data timeout flag
int8  i=0;                    // Index for serial_isr()
int8  j=0;                    // Index for heartbeat_isr()
int16 t=0;                    // Data Timeout counter

typedef union                 // union used to facilitate packaging of output
 {
   int8  x08[2];
   int16 x16;
 }data1;
 data1 param[7];

////////////////////////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////////////////////////

#define  DATAOUT_TIMEOUT   3500  // Time constant for Data Timeout
#define  INTERRUPT_COUNT   50    // Interrupt count for Heartbeat toggle

////////////////////////////////////////////////////////////////////////////////
// Function Prototypes
////////////////////////////////////////////////////////////////////////////////

void serial_isr();
void timer0_isr();
void main();
void parseData();
void packData();
void init_system();
void heartbeat();

////////////////////////////////////////////////////////////////////////////////
// Interrupts
////////////////////////////////////////////////////////////////////////////////

// Serial Interrupt Service Routine
//    Interrupt entered when incomming serial data detected (HW USART only)
//    Read port 1 char at a time, do not save unless sync is present (0xFAF320)
//    If SYNC detected, record next 16 chars and set 'gotMsg'.

#int_RDA
void serial_isr()
{
   msg[i]=fgetc(IN);
   if(i<3)                      // check for sync...msg header '0R1' or '0R2'
   {
      switch (i)
      {
         case 0:
            if(msg[0]=='0')
             i=1;
            break;
         case 1:
            if(msg[1]=='R')
               i=2;
            else
               i=0;
            break;
         case 2:
            if((msg[2]=='1') || (msg[2]=='2'))
               i=3;
            else
               i=0;
            break;
         default:
            i=0;
      }
   }
   else
   {
      if(msg[i++]==0x0D)        // end of ASCII message
      {
         gotMsg=TRUE;            // complete message received
         strcpy(inputData, msg); // transfer temp buffer to INPUTDATA
         i=0;                    // reset index for next message
      }
      if(i>=37)
         i=0;                    // error if > 35 characters...reset
   }
}

// Timer0 Interrupt Service Routine
//    Interrupt entered when TIMER0 overflows.  Generates a heartbeat toggle of
//    approximately 500ms. Heartbeat LED is green with valid rx data and red
//    if data isn't rx from
//    (Timeout period is determined by DATAOUT_TIMEOUT constant)

#int_TIMER0
void timer0_isr()
{
  j++;       // increase timer for heartbeat
  t++;       // increase timer for dataout_timeout
}

////////////////////////////////////////////////////////////////////////////////
// MAIN()
//    Wait for serial message indicated by 'gotMsg' = TRUE (received through
//    RDA interrupt). If 3 sec elapse with no message, zero-out data stream to
//    DAS. If message received, parse and package data then send out to the DAS
//    on PIN_C2.
////////////////////////////////////////////////////////////////////////////////

void main()
{
   int8  k;

   init_system();                         // initialize system

   while(TRUE)
   {
      t=0;                                // reset timeout counter value
     
      while(!gotMsg)                      // wait until data message received
      {
         if(t>DATAOUT_TIMEOUT)       // check for correct number of timer interrupts
         {
            i=0;                          // reset isr index
            t=0;                          // reset timeout counter value
            error=TRUE;                   // set error status flag

            for(k=0;k<=19;k++)
            {
               fprintf(OUT, "%c", no_rx_data[k]);  // output no_rx_data stream
            }
         }
         
         heartbeat();                     // toggle LED for heartbeat
      }

      gotMsg=FALSE;                       // Reset gotMsg bit for next message
      parseData();                        // extract data & apply EU conversions
     
      if(gotMsg2)                         // execute if full data stream is rx
      {
         error=FALSE;                     // reset error flag if set
         gotMsg2=FALSE;                   // Reset gotMsg2 bit for next message
         packData();                      // assemble serial output message
         for(k=0;k<=19;k++)
            fprintf(OUT, "%c", output[k]);// Transmit packaged data to DAS
         
         heartbeat();                     // toggle LED for heartbeat
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
// Functions
////////////////////////////////////////////////////////////////////////////////

// init_system()
//    Initialize system routine enables the controller system interrupts and
//    defines the no_rx_data array used when the no data is received
//    within 3 seconds

void init_system()
{
   setup_timer_0(RTCC_INTERNAL|RTCC_8_BIT|RTCC_DIV_256); // setup timer interupt

   enable_interrupts(int_rda);      // Enable interrupt for USART serial data
   enable_interrupts(int_TIMER0);   // Enable Timer0 for Heartbeat flashing
   enable_interrupts(GLOBAL);       // Enable interrupts

   //format "no rx" data output   
   return;
}

// heartbeat()
//    Generates a heartbeat toggle of approximately 500ms when TIMER0 interrupt
//    overflows. Status of LED (On/Off) is set by hrttogl flag
//    Heartbeat LED is green with valid rx data and red if valid data
//    isn't rx within 3.5 seconds.  error flag is set within
//    main program. (Timeout period is determined by DATAOUT_TIMEOUT constant)

void heartbeat()
{
   if(j>INTERRUPT_COUNT)       // check for correct number of timer interrupts
   {
      j=0;                       // reset counter for next use
     
      hrttogl^=1;                // toggle heartbeat LED status 1=ON, 0=OFF
   }
   
   if(error)                              // is error flag set?
   {
      output_bit(RX_ERROR_IND,hrttogl);   // yes, toggle error indicator (red)
      output_low(RX_VALID_IND);           // turn off rx valid Indicator (grn)
   }
   else                                   // No error flag
   {
      output_bit(RX_VALID_IND,hrttogl);   // toggle rx valid indicator (GRN)
      output_low(RX_ERROR_IND);           // turn off rx error indicator (red)
   }

   return;
}

// parseData()
//    Transfer incomming message data 'msg[]' to parameter array 'param[]'.
//    Param is a union array used to facilitate conversion of two 8bit words
//    into one 16bit word.

void parseData()
{
   float wxData[4];
   int8  *dataPtr;
   int8  *nPtr;
   int8  k=0;

   dataPtr=strtok(inputData,dlimitr);  // move pointer to first delimiter "="
   dataPtr=strtok(0,dlimitr);    // ignore first parce (address header 0R1,0R2)
   while((dataPtr != 0) && (k <= 4))
   {
      wxData[k++]=strtod(dataPtr, &nPtr); // save parce data into temp wxData
      dataPtr=strtok(0,dlimitr);          // move pointer to next delimeter
   }
   if(k<5)
   {
      if(inputData[2]=='1')     // data received is speed & direction data
      {
         //format message 1 EU data

      }
      else if(inputData[2]=='2')// data received is temp, rh & press data
      {
         // format message 2 EU data

         gotMsg2=TRUE;
      }
   }
   
   return;
}

// packData()
//    Format output stream with required data in preparation for transmission

void packData()
{
   // format outpt data

   return;
}



Thanks,

Justin
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Mar 29, 2010 12:59 pm     Reply with quote

What's the silicon rev. of the 18F2620 that you're currently using ?
Earlier revs had problems with the EUSART. Knowing the exact rev
you're using is critical. The rev is reported by the programmer (ICD)
when it "connects" to the PIC. In MPLAB, it's given in the Output window.
jmb1539



Joined: 29 Mar 2010
Posts: 11

View user's profile Send private message

PostPosted: Mon Mar 29, 2010 3:23 pm     Reply with quote

I'm using the Mach X ICD and if I'm reading it correctly, I get the following:

Device PIC18F2620
Status Good
Device ID 0C80
Revision 07 --> I believe this is my silicon version?
Program 32768 instructions
Configuration 300000-30000D
Data F00000-7801FF
etc
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Mar 29, 2010 3:45 pm     Reply with quote

Quote:
Revision 07 --> I believe this is my silicon version?

I'm not sure if that's the revision. Your Device ID word is 0C80:
Quote:

Device ID 0C80

Look at the erratas on the 18F2620 page:
http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en010284#1
They contain the silicon rev numbers. Here is a summary:
Code:

Silicon rev  Device ID       Rev ID      ID (hex)
     A3      0000 1100 100   0 0011       0C83
     A4      0000 1100 100   0 0100       0C84
     A5      0000 1100 100   0 0110       0C86
     A6      0000 1100 100   0 0111       0C87

It's possible that CCS is masking off the bottom 4 bits of the Device ID
and just reporting "0C80" as the ID. Then they may be taking the
bottom 4 bits and reporting that raw number as the Revision. So their
"rev 7" is really silicon rev A6. That interpretation might make sense.
jmb1539



Joined: 29 Mar 2010
Posts: 11

View user's profile Send private message

PostPosted: Tue Mar 30, 2010 12:31 pm     Reply with quote

It looks like I have the B5 silicon revision. I've looked through the errata for this silicon and all others and I'm not coming across a solution. For issues concerning the USART, I see modules for synchronous transmission, 9-bit mode, and auto-baud modes. I'm not using any of those configurations. I've used the ICD to try and track down where my processor is going out to lunch, but the only thing I'm seeing is that once I enable my serial interrupt, i'm done.
jmb1539



Joined: 29 Mar 2010
Posts: 11

View user's profile Send private message

PostPosted: Wed Mar 31, 2010 1:20 pm     Reply with quote

Just FYI for anyone following this thread, the problem I encountered was do to the strcpy function that was called in the serial ISR. My incoming data wasn't null terminated so this function would just hang. The fact that the code worked on the PIC16F876 was simply a matter of luck. Once I terminated my received data, the code worked fine.
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