![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
John Morley
Joined: 09 Aug 2004 Posts: 97
|
trouble with serial input data |
Posted: Mon Sep 19, 2005 9:59 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Sep 19, 2005 10:48 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
John Morley
Joined: 09 Aug 2004 Posts: 97
|
|
Posted: Mon Sep 19, 2005 6:51 pm |
|
|
Mark,
Yep, I can't believe I did that with Index=0 ....... 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 |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|