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

RS422 comm slowing down the CPU

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







RS422 comm slowing down the CPU
PostPosted: Thu Apr 21, 2005 1:11 am     Reply with quote

Hi friends;
The code below is for a 30 node PIC18F452 connected to a PC via 4 wire RS422 system. System is working perfectly except.

1) When I set the adress , the CPU is getting correct address numbre. Say , If I give 0x01 as the node number , it is answering all the calls to node 0x01. But when I use the printf ("#%2X\r\n",RS485_ID) to read adress back , it is giving 0xD9 instead of 0x01.

2) After a couple of minutes of communication , total system is slowing down in communication, nearly 10-20 times.

Each message sent from PC contains @@nnCCPP+0x0d
where @@=header
nn : Node number
CC : Command
PP : Param value if needed.
CR (0x0d)
Do you think Should I rewrite the comms routines?.

Can somebody give me a ASCII charecter based example to broadcast just 5-6 bytes of data to subscribers of line.

Note. My compiler is PCWH 3.221

All ideas are wellcome.
Code:

#include <18F452.h>
#device adc=8
#use delay(clock=16000000)
#fuses NOWDT,WDT128,HS, PROTECT, NOOSCSEN, BROWNOUT, BORV20, NOPUT, STVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOWRTB, NOWRTC, NOCPD, NOCPB, NOEBTR, NOEBTRB
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9,ENABLE=PIN_C1,stream=PC)

#ZERO_RAM
int RS485_ID;
char inbuf[12]="         ";

byte gethex(char digit) {
   if(digit<='9')
     return(digit-'0');
   else
     return((toupper(digit)-'A')+10);
}
#int_RDA
RDA_isr()
{
int a,b;
 gets(inbuf);
 //output_high(PIN_C1);
  //puts(inbuf);
 if(inbuf[0]=='@' && inbuf[1]=='@') // @@ message header
 {
   if (inbuf[2]=='G' && inbuf[3]=='M') //GLOBAL SET metre sayac
   {
    metre_hedef=256*(inbuf[4])*16+gethex(inbuf[5]) + (inbuf[6])*16+gethex(inbuf[7]);
   }
   if (inbuf[2]=='G' && inbuf[3]=='R') //GLOBAL RUN
   {
    WM_RUN=1;
   }
   if (inbuf[2]=='G' && inbuf[3]=='S') //GLOBAL STOP
   {
    WM_RUN=0;
   }
   // Adres set procedure  @@ AS NN ,(00..FF)
   // During address set , node number not required.
   if (inbuf[2]=='A' && inbuf[3]=='S')
   {
     RS485_ID=gethex((inbuf[4])*16+gethex(inbuf[5]));
     write_eeprom (0,RS485_ID);
     output_high(PIN_C1);
     delay_ms(100); // EEpromda yazma tamamlanana dek bekle
     printf ("#%2X\r\n",RS485_ID-208);
     output_low(PIN_C1);
   }

   //If message blongs to this CPU
   if (RS485_ID==gethex((inbuf[2])*16+gethex(inbuf[3])))
   { //output_high(PIN_C1);
     switch (inbuf[4])
     {
       case 'M': { if (inbuf[5]=='S')//Metre counter value
                    {
                      metre_hedef=256*(inbuf[6])*16+gethex(inbuf[7]) + (inbuf[8])*16+gethex(inbuf[9]);
                      #IF (DEBUG==TRUE)
                      #ENDIF
                    }
                   Break;}
       case 'W' : { if (inbuf[5]=='R')// Wax motor run
                     {
                       WM_RUN=1;
                     }
                    if (inbuf[5]=='S')     // Wax motor Stop
                     {
                       WM_RUN=0;
                     }
                  }
                   Break;
       case 'S'  :{ if (inbuf[5]=='S')  // Status send (inquiry)
                    {
                    }
                    printf("#%2X%c\r\n",RS485_ID-208,ST_stat); //Node status
                   Break;
                  }
     }
    }
   }
//Clear comm buffer
 for (a=0;a++;a<12) {
 inbuf[a]=' ';
  }

}
void INIT_MCU()
{
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16|RTCC_8_bit);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_2);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   
   RS485_ID=read_eeprom(0);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);

   set_tris_a(0b00111111);  // All in
   set_tris_b(0b11001111);
   set_tris_c(0b10110000);
   set_tris_d(0b00000000);
   set_tris_e(0b00000000);
}

void main()
{
  INIT_MCU();
  MPC_Reset();
  init_vars();
  enable_interrupts(INT_RDA);  // open serial port
   ST_stat='R'; // Status :=AFTER_RESET 
While(1)
  {
     //Normal tasks
  }
}
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

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

PostPosted: Thu Apr 21, 2005 6:23 am     Reply with quote

See this line
Code:
   enable_interrupts(INT_TIMER1);


I don't see an interrupt handler for it. This will cause your program to constantly run the interrupt handler and run dog slow.
TSchultz



Joined: 08 Sep 2003
Posts: 66
Location: Toronto, Canada

View user's profile Send private message

PostPosted: Thu Apr 21, 2005 6:52 am     Reply with quote

You really need to reduce the code in your serial interrupt handler. You should just receive, maybe validate, the packet, then once you have the full packet set a flag so a handler in the main loop can decode and process the packet.

Here is the code I run for RS485, it is a custom prototocol but should be easy to follow. The code has been fairly well optimized (I think).
Code:
/****************************************************************************
 Interrupt routine to receive data using internal USART.
 Routine handles all aspects of packet collection and validation.
 NewData is set when a complete and valid packet has been received if;
 - BOF must be valid
 - ID must be ours, or global id
 - number of bytes must match LEN field
 - FCS must be valid, will be zero if correct
 - EOF must be found after FCS character
 - all bytes must be received within allowed timeframe (see timer ISR routine)
*****************************************************************************/
#INT_RDA
void isr_RXSerial( void ) {
   static byte FCS, c;

   if( kbhit() ) {   //test to make sure byte is in buffer, ISR may have been called erroneously
      c = getc();   //get byte from buffer
      if ( !serialA_Working ) {   //Are we already getting a packet?
         serialA_Working = ( c == BOF );      //if BOF then we are getting a packet
         serialA_Timeout = false;         //clear timeout
         serialA_Bytes = 0;               //we have no data bytes yet
         serialA_GoodData = 0;
         PacketErr++;      //Assume packet is bad until verified
      } else {
         serialA.Buffer[serialA_Bytes] = c;   //put character in buffer
         serialA_Working = ( serialA_Bytes++ < SERIAL_BUFFER_SIZE );  //don't exceed buffer size
         if (serialA_Bytes == 1) {
            serialA_Working = ( ClientID == c ) || ( GlobalID == c );   // If ID no good then discard remaining chars
            serialA_Reply = ( ClientID == c );   // Allow reply if ID is ClientID, don't reply if GlobalID
            FCS = c;   //set FSC with first byte
         } else if ( serialA_Bytes <= serialA.Data.LEN + 1 ) {
            FCS ^= c;   //Still getting data bytes so accumulate FSC
         } else if ( c == EOF ) {            //Check EOF
            if( FCS == 0 ){
               PacketErr--;   //FSC is valid so packet is not in error
               serialA_GoodData = 1;
            }
            serialA_NewData = 1; //( FCS == 0 );   //If FSC is good then we have good packet
            serialA_Working = false;   //We are no longer getting data
            PacketsRX++;               //Increment good packet count
         } else {
            serialA_Working = false;   // data receive error so stop grabbing data
         }
      }
   }
}


In my main loop I then check for serialA_NewData, it true then I have a good packet to work with. The only other thing not in the code above is a timeout which is handled in a timer irq, it just clears SerialA_Working which aborts the current RX.

Hope this helps some.
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