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

trouble with serial input data

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



Joined: 09 Aug 2004
Posts: 97

View user's profile Send private message

trouble with serial input data
PostPosted: Mon Sep 19, 2005 9:59 am     Reply with quote

Hi all,

I have a number of PIC modules interconnected using an RS485 network. Each module has a unique address assigned by a set of DIP switches, and controls two digital output lines. I am sending the following command string to the modules:

#NX:A,B<CR> where X is the module address (0 to 9), and A and B are the desired digital output states.

At this point I'm just trying to see if I can uniquely command a specific module. My code contains a serial interrupt routine that fills a receive buffer until a CR is received, and then the Main() routine checks for an address match in the received data. I know the CR is being received because I toggle one of the digital outputs (they are connected to LEDs) as a diagnostic, but the address test that follows is never successful....... A putc() of the module address returns an unprintable ASCII character. I think this is just a problem with how the data is represented in the receive buffer. I have a routine (gethexbyte) to handle that, but using it doesn't seem to help the problem. I don't think this is a hardware issue because I have a small test program that uses getc() and putc() to receive and transmit characters. Any one of the modules connected individually works fine.

My compiler version is: 3.162

Code:


//-----< Include Files, setup fuses >-----

#include <16f73.h>
#fuses HS, NOWDT, NOPROTECT

//-----< Compiler use statements >-----

// Tell compiler clock speed is 20.00 MHZ Crystal
#use delay(clock=20000000)

//-----< General Program Defines >-----
#define RS232_OUT PIN_A4       // RS232 Output to Terminal
#define RS485_OUT PIN_C6       // RS485 Output Pin
#define RS485_IN PIN_C7       // RS485 Input Pin
#define RS485_Enable PIN_C5    // RS485 Enable Pin
#define Relay1_Out Pin_B0       // Relay 1 Output (active hi, and inverted by output FET)
#define Relay2_Out Pin_B1       // Relay 2 Output (active hi, and inverted by output FET)

//-----< Firmware Version >-----
#define SW_Data1 PIN_C0
#define SW_Data2 PIN_C1
#define SW_Data3 PIN_C2
#define SW_Data4 PIN_C3
#define SW_Data5 PIN_C4
#define CR         0x0d      // ASCII Value for a Carriage Return

//-----< Serial Port Definition >-----
#use rs232(baud=9600, xmit=RS232_Out, stream = Console, Restart_WDT, ERRORS)
#use rs232(baud=9600, xmit=RS485_Out, rcv=RS485_In, enable = RS485_Enable, stream = Network, Restart_WDT, ERRORS)
 
//-----< RS232 Packet definitions >-----
int RX_Command_Ready;      // TRUE If a receive packet is ready

#define RX_SIZE 20         // RS485 buffer for serial reception
char RxBuffer[RX_SIZE];    // RS485 serial RX buffer
int Index = 0;           // RS485 RX data IN index

int iAddress;

//-----< Get a RS232 command packet >-----
// Note: This routine is interrupt driven. RS485 input takes priority
// over every other operation in the system.

#INT_RDA   // Interrupt driven RS485 routine
void rs485_isr(void)
{
   char temp;   // local data storage
   
   temp = fgetc(Network);   // get rx data

   // If we got a CR, then the command is completed.
   if (temp == CR)
      {
         RxBuffer[Index] = temp;
         RX_Command_Ready = TRUE;
         return;
      }

   // Save the character to the receive buffer.
   RxBuffer[Index]=temp;

   // Check for buffer overflow.
   if ( Index >= (RX_SIZE - 1) )
      Index = 0;
   else
      Index++;
}

// This routine is used to convert characters for checking the checksum
// It simply converts an ASCII hex value into true decimal form
// ASCII allows for a quick and dirty conversion routine!

byte gethexbyte(char digit) {
   if(!BIT_TEST(digit,6))      // Its a number if bit 6 is 0
      return(digit & 0x0F);   // Simple way to convert 0-9
   else
      return((digit & 0x0F) + 9);
}

void main(void)
{
   
   // Here we read the DIP switch to determine the module network address
   iAddress= input(SW_Data1) + ( 2 * input(SW_Data2)) + (4 * input(SW_Data3)) + (8 * input(SW_Data4)) + (16 * input(SW_Data5));
   //fPrintf(Network, "Address: %d\n\r",iAddress);

   // Here we set the initialize program variables.....
   Output_low(Relay1_Out);
   Output_low(Relay2_Out);
   setup_adc_ports( NO_ANALOGS );
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);

   while(1)
   {
      // Here we wait for a character to show up in the Rcv buffer, and then read the received string      
      
      if ( RX_Command_Ready == TRUE )
      {      

         // Just to be safe, first things first...
         disable_interrupts(GLOBAL);
         RX_Command_Ready = FALSE;
         Output_high(Relay1_Out);   //turn on the LED so we know we received a command...
         putc(RxBuffer[2], Network);

         // Let's start to decode the command if we have the correct address.....
         if (gethexbyte(RxBuffer[2]) == iAddress)
         {
            Output_high(Relay2_Out);
            delay_ms(500);
            // fprintf(Network, "#N%d:0,0,1234!", iAddress);
            delay_ms(500);
            Output_low(Relay2_Out);
            // decode_command();
         }

      }
         // Done so re-enable RS485
         Index = 0;
         enable_interrupts(GLOBAL);                     
   } // while

} // end Main



Does anyone have an idea what might be going on?

Thanks!

John
_________________
John Morley
Mark



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

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

PostPosted: Mon Sep 19, 2005 10:48 am     Reply with quote

Looks like to me that your index = 0 and enable interrupt statements are in the main loop so index is just about always 0. Also, you need some sort of signal that this is the start of a message. This could be a timeout or a special char recieved or even a break signal. You this to reset the index to 0.
John Morley



Joined: 09 Aug 2004
Posts: 97

View user's profile Send private message

PostPosted: Mon Sep 19, 2005 6:51 pm     Reply with quote

Mark,

Yep, I can't believe I did that with Index=0 Rolling Eyes ....... I was moving some code around and never picked up on the error even after many checks! Also, I added a check for the start character (#) in the interrupt handler and all is well now!

Thanks!
_________________
John Morley
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