|
|
View previous topic :: View next topic |
Author |
Message |
Izzy
Joined: 27 May 2007 Posts: 106
|
Problem using multiple UARTs |
Posted: Tue Jul 31, 2007 5:21 am |
|
|
Hello,
I am having problem using multiple UARTS in the PIC18F4520. I am using a hardware UART(C6 and C7) for serial communication with receive PIN interrupt.
And I have a Software UART (B0 and B1) for another serial communication with External interrupt in pin B0 for receiving.
NOW the problem is, IF I enable both interrupt then the hardware interrupt wont work! (I mean I dont receive any data), But IF I disable the external interrupt then the hardware interrupt will work (I can receive data).
And external interrupt works fine no matter the hardware interrupt enabled or disabled.
Can you guy please help me why is this happening?
I have tried searching the forum but I couldnt find the answer.
Thanks in advance |
|
|
Ttelmah Guest
|
|
Posted: Tue Jul 31, 2007 7:18 am |
|
|
What baud rates are you using?.
What do you 'do' in the two interrupt handlers?.
Best Wishes |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Tue Jul 31, 2007 8:13 am |
|
|
I am using 9600. I am reading the one byte in each interrupt.
And here is the code
Code: | #include <18f4520.h>
#device ICD=TRUE
#fuses HS,NOLVP,NOWDT
#include <stdlib.h>
#use delay(clock=40,000,000)
#use rs232(stream=debug, DEBUGGER)
#use rs232 (stream=radio, baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use rs232 (stream=pc, baud=9600, xmit=PIN_B1, rcv=PIN_B0)
int pc_data_receive_loop=0,
rs232_loop=0,
send_loop=0,
Received_signal=0,
Command_data_receive_loop=0,
First_digit,
Second_digit,
Third_digit,
pointer=0,
Command_receive_array[2];
char Robot_destination,
Receive_robot_data[22],
PC_data[3],
Temp_array[2];
/*******************************INTERRUPT SUBROUTINE***************************/
//This interrupt occurs whenever Receive Pin of RS232 port receive any data
#INT_RDA
void Data_Receive_BaseStation()
{
Receive_robot_data[rs232_loop] = fgetc(radio); //Reads one byte of the string sent by the Robot from the Rx pin (Each byte will trigger this interrupt)
rs232_loop++; //increaments the array pointer
}
/*******************************INTERRUPT SUBROUTINE***************************/
//#INT_EXT
Void PC_Command_Received()
{
PC_data[pc_data_receive_loop] = fgetc(pc); //Reads one byte of the string sent by the Basestation PC from the B0 external interrupt pin (Each byte will trigger this interrupt)
pc_data_receive_loop++; //increaments the array pointer
}
/**********************************MAIN FUNCTION*******************************/
void main()
{
//enable_interrupts(INT_EXT);
//ext_int_edge(H_TO_L);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while(true)
{
/****************************************** FOR SENDING DATA FROM PC TO ROBOTS ***************************/
if(pc_data_receive_loop == 2) // Checks if PC_data array has received 2 byte command (which will be sent to Robot through the RF module)
{
Robot_destination = PC_data[0]; //Assigns the Robot's ID number to Robot_destination
output_high(PIN_D0); //Turns CMD pin of the RF module high to enter the binary command Mode
delay_ms(2);
fputc(0x00 radio); //Sends Destination command to change the destination address of the Basestation RF module
delay_ms(10);
switch(Robot_destination) //Checks for the Robot_destination character Match
{
case '0': fputc(0xA0 radio); //If Robot_destination is '0' it will set the destination address of the module to 'AAA0' so that the module can communicate only with the Robot having the same Module address
fputc(0xAA radio);
break;
case '1': fputc(0xA1 radio); //Same as above
fputc(0xAA radio);
break;
case '2': fputc(0xA2 radio);
fputc(0xAA radio);
break;
case '3': fputc(0xA3 radio);
fputc(0xAA radio);
break;
case '4': fputc(0xA4 radio);
fputc(0xAA radio);
break;
case '5': fputc(0xA5 radio);
fputc(0xAA radio);
break;
case '6': fputc(0xA6 radio);
fputc(0xAA radio);
break;
case '7': fputc(0xA7 radio);
fputc(0xAA radio);
break;
case '8': fputc(0xA8 radio);
fputc(0xAA radio);
break;
case '9': fputc(0xA9 radio);
fputc(0xAA radio);
break;
}
output_low(PIN_D0); //Turns CMD pin of the RF module low to exit the binary command mode
for(send_loop=0;send_loop<2;send_loop++)
{
fputc(PC_data[send_loop],debug); //Sends the command sent by basestation PC to the robot
}
pc_data_receive_loop=0; //Resets the array pointer
Command_data_receive_loop=0; //Resets the array pointer
}
/****************************************** FOR SENDING DATA FROM ROBOT TO THE PC ***************************/
if(rs232_loop==22) //Checks if the Receive_robot_data array has received 30 bytes data from the Rx pin
{
disable_interrupts(INT_RDA); //Disables the Rx pin interrupt
output_high(PIN_D0); //Turns CMD pin of the RF module high to enter Binary command mode
delay_ms(2);
fputc(0x36 | 0x80, radio); //Sends command to read the Received signal strength value
delay_ms(10);
output_low(PIN_D0); //Turns the CMD pin low to exit binary command mode
while(kbhit(radio)) //checks if the RF module has sent the received signal strength value back
{
Command_receive_array[Command_data_receive_loop] = fgetc(radio); //reads the received signal strength value (of the basestation radio)sent by the RF module
Command_data_receive_loop++; //increaments the array pointer
}
enable_interrupts(INT_RDA); //Enables the Rx pin interrupt so that it can receive data sent by the base station
Received_signal = Command_receive_array[0]; //loads the Received signal strength into the array
First_digit=(Received_signal/100); //Does the calculation to get the 100th place digit
itoa(First_digit, 10, Temp_array); //Converts 100th place digit(int) into ASCII character and loads into Temp_array with a null terminator
Receive_robot_data[19] = Temp_array[0]; //Assigns the first element of the Temp_array to Robot_main_data_array[pointer], ignoring the null terminator of the Temp_array
Pointer++;
Second_digit=((Received_signal/10)-(10*First_digit)); //Does the same thing as above for the 10th place digit
itoa(Second_digit, 10, Temp_array);
Receive_robot_data[20] = Temp_array[0];
Pointer++;
Third_digit=(Received_signal - (100*First_digit) - (10*Second_digit)); //Does the same thing as above for the 1st place digit
itoa(Third_digit, 10, Temp_array);
Receive_robot_data[21] = Temp_array[0];
for(send_loop=0;send_loop<22;send_loop++)
{
fputc(Receive_robot_data[send_loop],debug); //Sends the Robot_main_data_array to the RF module for transmission
}
fputc('\n',debug);
Command_data_receive_loop=0; //Resets the Command_receive_array
rs232_loop=0; //Resets the Receive_robot_data
}
}
} |
|
|
|
Ttelmah Guest
|
|
Posted: Tue Jul 31, 2007 1:12 pm |
|
|
First, add 'ERRORS' to the use RS232 statement for the hardware UART. Otherwise if data is not read in time on this, the UART will become disabled.
Second, add limit checking to the interrupt handlers. At present, if the software serial is being driven with long streams of data, the main will hardly execute at all, the buffer will become full, and the routines will start overwriting other variables, destroying data.
Best Wishes |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Jul 31, 2007 4:05 pm |
|
|
I agree with Ttelmah, add some buffer overflow protection code.
I didn't spot the bug in your code but I do have some recommendations.
Code: | fputc(0x00 radio); //Sends Destination command to change the destination address of | A comma is missing between the two parameters. This is true for most of your fputc() calls.
Try to keep your code compact for easier maintenance. For example when you have large pieces of similar code try to discover the formula behind it. For example:
Code: | switch(Robot_destination) //Checks for the Robot_destination character Match
{
case '0': fputc(0xA0 radio); //If Robot_destination is '0' it will set the destination address of the module to 'AAA0' so that the module can communicate only with the Robot having the same Module address
fputc(0xAA radio);
break;
case '1': fputc(0xA1 radio); //Same as above
fputc(0xAA radio);
break;
case '2': fputc(0xA2 radio);
fputc(0xAA radio);
break;
case '3': fputc(0xA3 radio);
fputc(0xAA radio);
break;
case '4': fputc(0xA4 radio);
fputc(0xAA radio);
break;
case '5': fputc(0xA5 radio);
fputc(0xAA radio);
break;
case '6': fputc(0xA6 radio);
fputc(0xAA radio);
break;
case '7': fputc(0xA7 radio);
fputc(0xAA radio);
break;
case '8': fputc(0xA8 radio);
fputc(0xAA radio);
break;
case '9': fputc(0xA9 radio);
fputc(0xAA radio);
break;
} | can be reduced to: Code: | Robot_destination = PC_data[0] - '0'; // Get the Robot's ID number. Note the subtract with '0' to convert from ASCII to binary.
fputc(0xA0 + Robot_destination, radio); // Set the destination address of the module to Robot's address
fputc(0xAA, radio);
|
But don't overdo it. For example in the code below you implemented a nice general approach Code: | for(send_loop=0;send_loop<2;send_loop++)
{
fputc(PC_data[send_loop],debug); //Sends the command sent by basestation PC to the robot
} | but this is equivalent to: Code: | //Send the command sent by basestation PC to the robot
fputc(PC_data[0], debug);
fputc(PC_data[1], debug);
| The first is hard for the compiler to optimize and takes 16 instructions, the latter is easier to read and takes 4 instructions. |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Wed Aug 01, 2007 5:22 am |
|
|
Thank you guys for help!
I found out the porblem. The problem was I was changing the base station's address, so I was not receiving any data. Sorry my bad.
And thanks ckielstra for help!
One thing I am surprised about, I completely forgot about the coma in:
fputc(0x00 radio);
But how did it work without coma?
And thanks for the For loop suggestion, I will change it. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Aug 01, 2007 5:29 am |
|
|
Quote: | But how did it work without coma? Shocked | This is a compiler bug. At minimum the compiler should have given a warning for invalid parameter.
It did work by chance. In your program STDIN and the radio stream are the same. Would you have reversed the two #rs232 lines than PC would have become the standard IO stream and you would have noticed the error. |
|
|
|
|
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
|