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

Problem using multiple UARTs

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



Joined: 27 May 2007
Posts: 106

View user's profile Send private message

Problem using multiple UARTs
PostPosted: Tue Jul 31, 2007 5:21 am     Reply with quote

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







PostPosted: Tue Jul 31, 2007 7:18 am     Reply with quote

What baud rates are you using?.
What do you 'do' in the two interrupt handlers?.

Best Wishes
Izzy



Joined: 27 May 2007
Posts: 106

View user's profile Send private message

PostPosted: Tue Jul 31, 2007 8:13 am     Reply with quote

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







PostPosted: Tue Jul 31, 2007 1:12 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jul 31, 2007 4:05 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Aug 01, 2007 5:22 am     Reply with quote

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. Confused

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? Shocked



And thanks for the For loop suggestion, I will change it.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Aug 01, 2007 5:29 am     Reply with quote

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.
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