bidirectional interconnection of 2 16F877A microprocessor via uart problem

Thread Starter

NioBium

Joined May 5, 2010
6
Dear friends,

Please help me with my project. I need to maintain a reliable communication between two microprocessors using UART (asynchronous). The program is as follows. Master 16F877A sends a frame of 11 bytes every 75ms. On reception of a properly formatted packet (using header and the trailer), Slave declares the link to be established and sends a similar acknowledgement packet to the Master shortly after. On reception of the ack packet Master declares link to be established and starts sending non-zero data. If a packet is not received on any of the microprocessors in 260ms, it declares the link to be broken (thus losses for up to 2 packets are tolerated). I have connected rx to tx and tx to rx directly, also the grounds of the microprocessors are the same. unfortunately what I see is rapid blinking of the link-status led, which indicates that connection is established and broken many times per second. using some led outputs which are not present in the attached code for the sake of simplicity, I observe moderate amount of framing errors, no overrun errors and a vast majority of the errors in the formatting of the data frame. Another weird thing is that when there is no physical connection between the RX and TX terminals of a master microprocessor with anything whatsoever, RCIF is constantly flagged, indicating that transmission bytes somehow imprint themselves on the RX terminals of the same microprocessor, though there is no short connection between them (checked with multimeter several times). 20MHz oscillators are in use. Does anyone have any idea about the possible causes and the solution?

Thank you.

master code:
Rich (BB code):
#define CONST_TIMING_TRANSMISSION_LONG 11  // interval between individual transmissions
#define CONST_TIMING_TIMEOUT_LONG 40 // maximum time between reception of two frames until the link is declared broken (tolerates up to 2 packet losses if rf module is used
#define CONST_TIMING_TIMEOUT_SHORT 2 // maximum time between reception of individual bytes of a frame


unsigned int rf_timeout_counter = CONST_TIMING_TIMEOUT_LONG;
unsigned short rf_uart_transmission_queue[11] = {0x0A, 0x0D, 0x44, 0x4E, 0x45, 0x80, 0x80, 0x44, 0x46, 0x52, 0x24}; 

//backwards
signed short rf_uart_transmission_queue_length;
unsigned short rf_byte_order, rf_rx_data, rf_temp_data, rf_link_status;
signed int timing_transmission_counter=CONST_TIMING_TRANSMISSION_LONG;


void rf_init()
{
    TRISC|=0xC0;
    SPBRG = 129;
        
    TXSTA = 0b00100100;
    RCSTA = 0b10010000;
    PIE1 |= 0b00110000;
    TXREG=RCREG;

    rf_uart_transmission_queue_length=0;
    timing_transmission_ready=0;
    timing_transmission_counter=CONST_TIMING_TRANSMISSION_LONG;
    rf_byte_order=0;
    rf_link_status=0;
    rf_timeout_counter=CONST_TIMING_TIMEOUT_LONG;
    INTCON |= 0b01000000;   //peie
}

void timing_init()
{
    INTCON.T0IE=1;
    OPTION_REG.T0CS=0;                       //Set Timer0 to instruction clock
    OPTION_REG.PSA=0;                        //Assign pre-scaler to Timer0
    OPTION_REG.PS2=1;                      //Set first digit of pre-scale value
    OPTION_REG.PS1=1;                      //Set second digit of pre-scale value
    OPTION_REG.PS0=0;                      //Set third digit of pre-scale value     000 - 10ms 100, 101 - 10 ms 3
    INTCON.T0IF=0;
    INTCON.GIE=1;
}

void rf_link_lost_action()
{
    rf_timeout_counter=-1;
    rf_link_status=0;
    rf_byte_order=0;
    PORTD.F4=0; // link disrupt
}

void rf_uart_byte_ready_action()
{
        if (rf_byte_order==0)
        {
            if (rf_rx_data==0x24)
            {
                rf_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
                rf_byte_order=1;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==1)
        {
            if (rf_rx_data==0x52)
            {
                rf_byte_order=2;
                rf_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==2)
        {
            if (rf_rx_data==0x46)
            {
                rf_byte_order=3;
                rf_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==3)
        {
            if (rf_rx_data==0x41)
            {
                rf_byte_order=4;
                rf_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==4)
        {
            rf_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
            rf_temp_data = rf_rx_data;
            rf_byte_order = 5;
        }
        else if (rf_byte_order==5)
        {
            rf_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
            rf_byte_order=6;
        }
        else if (rf_byte_order==6) //e
        {
            if (rf_rx_data==0x45)
            {
                rf_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
                rf_byte_order=7;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==7) //n
        {
            if (rf_rx_data==0x4E)
            {
                rf_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
                rf_byte_order=8;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==8) //d
        {
            if (rf_rx_data==0x44)
            {
                rf_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
                rf_byte_order=9;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==9) //13
        {
            if (rf_rx_data==0x0D)
            {
                rf_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
                rf_byte_order=10;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==10) //10
        {
            if (rf_rx_data==0x0A)
            {
                rf_byte_order=0;
                rf_timeout_counter=CONST_TIMING_TIMEOUT_LONG;    //200ms
                rf_link_status=1; // link up
                PORTD.F4=1;
            }
            else
                rf_link_lost_action();

        }
  //      if (rf_timeout_counter==-1)
  //          PORTD.F5=1;
}

void rf_transmit_data()
{
    timing_transmission_ready=0;
    timing_transmission_counter=CONST_TIMING_TRANSMISSION_LONG;
    if (rf_link_status)
    {
        rf_uart_transmission_queue[6] = (unsigned short)((signed int)control_slave_left_speed+128);
        rf_uart_transmission_queue[5] = (unsigned short)((signed int)control_slave_right_speed+128);
    }
    else
    {
        rf_uart_transmission_queue[6] = 128;
        rf_uart_transmission_queue[5] = 128;
    }
    rf_uart_transmission_queue_length=10;
    TXREG=rf_uart_transmission_queue[rf_uart_transmission_queue_length];
}

void interrupt(void)
{
    INTCON.GIE=0;
    if (PIR1.RCIF)
    {
        rf_rx_data = RCREG;
        rf_uart_byte_ready_action();
    }
    if (INTCON.T0IF)
    {
       if (RCSTA.OERR)
       {
           RCSTA = 0b10000000;
           RCSTA = 0b10010000;
       }
       if (timing_transmission_counter>=0)
       {
           timing_transmission_counter--;
           if (timing_transmission_counter==0)
           {
               rf_transmit_data();
           }
       }
       if (rf_timeout_counter>=0)
       {
           rf_timeout_counter--;
           if (rf_timeout_counter==0)
           {
               rf_link_lost_action();
           }
       }
       INTCON.T0IF=0;
    }

    if (PIR1.TXIF)
     {
         if (rf_uart_transmission_queue_length>0)
          {
             rf_uart_transmission_queue_length--;
             TXREG = rf_uart_transmission_queue[rf_uart_transmission_queue_length];
          }
    }
    INTCON.GIE=1;
}


void main() {
     leds_init();
     rf_init();
     delay_ms(250);
     timing_init();

     while (1);
}
 

Thread Starter

NioBium

Joined May 5, 2010
6
slave code:
Rich (BB code):
#define CONST_TIMING_ACKNOWLEDGEMENT 1 //delay before sending an acknowledgement
#define CONST_TIMING_TIMEOUT_LONG 40
#define CONST_TIMING_TIMEOUT_SHORT 2

unsigned short rf_uart_transmission_queue[11] = {0x0A, 0x0D, 0x44, 0x4E, 0x45, 0x00, 0x00, 0x41, 0x46, 0x52, 0x24}; 

//backwards
signed short rf_uart_transmission_queue_length;
unsigned short rf_byte_order, rf_rx_data, rf_temp_data, rf_link_status;
signed int timing_recepetion_timeout_counter;
signed int timing_acknowledgement_counter=CONST_TIMING_ACKNOWLEDGEMENT;



void rf_init()
{
    TRISC|=0xC0;
    SPBRG = 129;
    TXSTA = 0b00100100;
    RCSTA = 0b10010000;
    PIE1 |= 0b00110000;
    TXREG=RCREG;
    rf_uart_transmission_queue_length=0;
    rf_link_status=0;
    timing_acknowledgement_counter=CONST_TIMING_TIMEOUT_LONG;
    rf_byte_order=0;
    timing_recepetion_timeout_counter = -1;
}

void timing_init()
{
    INTCON.T0IE=1;
    OPTION_REG.T0CS=0;                       //Set Timer0 to instruction clock
    OPTION_REG.PSA=0;                        //Assign pre-scaler to Timer0
    OPTION_REG.PS2=1;                      //Set first digit of pre-scale value
    OPTION_REG.PS1=1;                      //Set second digit of pre-scale value
    OPTION_REG.PS0=0;                      //Set third digit of pre-scale value
    INTCON.T0IF=0;
    INTCON|= 0b01000000;   //peie
    timing_acknowledgement_counter=-1;
    INTCON.GIE=1;
}


void rf_link_lost_action()
{
    rf_link_status=0;
    rf_byte_order=0;
    timing_recepetion_timeout_counter=-1;
    PORTD.F4=0; //link disrupt  
}

void rf_uart_byte_ready_action()
{
      rf_rx_data=RCREG;
        if (rf_byte_order==0)
        {
            if (rf_rx_data==0x24)
            {
                rf_byte_order=1;
                timing_recepetion_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==1)
        {
            if (rf_rx_data==0x52)
            {
                rf_byte_order=2;
                timing_recepetion_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==2)
        {
            if (rf_rx_data==0x46)
            {
                rf_byte_order=3;
                timing_recepetion_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==3)
        {
            if (rf_rx_data==0x44)
            {
                rf_byte_order=4;
                timing_recepetion_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==4)
        {
            rf_temp_data = rf_rx_data;

                rf_byte_order=5;
                timing_recepetion_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;

        }
        else if (rf_byte_order==5)
        {
            motors_set_left((signed int)rf_temp_data-128);
            motors_set_right((signed int)rf_rx_data-128);

            rf_byte_order=6;
            timing_recepetion_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;

        }
        else if (rf_byte_order==6) //e
        {
            if (rf_rx_data==0x45)
            {
                rf_byte_order=7;
                timing_recepetion_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==7) //n
        {
            if (rf_rx_data==0x4E)
            {
                rf_byte_order=8;
                timing_recepetion_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==8) //d
        {
            if (rf_rx_data==0x44)
            {
                rf_byte_order=9;
                timing_recepetion_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==9) //13
        {
            if (rf_rx_data==0x0D)
            {
                rf_byte_order=10;
                timing_recepetion_timeout_counter=CONST_TIMING_TIMEOUT_SHORT;
            }
            else
                rf_link_lost_action();
        }
        else if (rf_byte_order==10) //10
        {
            if (rf_rx_data==0x0A)
            {
                rf_byte_order=0;
                timing_recepetion_timeout_counter=CONST_TIMING_TIMEOUT_LONG;
                timing_acknowledgement_counter=CONST_TIMING_ACKNOWLEDGEMENT;
                rf_link_status=1;
                PORTD.F4=1;		//link is established
            }
            else
                rf_link_lost_action();

        }
        #ifndef RF_LEDS_BLINKING_MAD
        if (timing_recepetion_timeout_counter<0) PORTD.F5=1;
        #endif
}

void rf_acknowledge()
{
    rf_uart_transmission_queue[6] = 0x00;
    rf_uart_transmission_queue[5] = 0x00;
    rf_uart_transmission_queue_length=10;
    TXREG=rf_uart_transmission_queue[rf_uart_transmission_queue_length];
}

void interrupt(void)
{
    INTCON.GIE=0;
    if (PIR1.RCIF)
    {
        #ifdef RF_LEDS_BLINKING_MAD
        PORTD.F5=!PORTD.F5;
        #endif
        rf_uart_byte_ready_action();

    }
    if (INTCON.T0IF)
    {
         if (RCSTA.OERR)
         {
             RCSTA = 0b10000000;
             RCSTA = 0b10010000;
         }

       if (timing_acknowledgement_counter>=0)
       {
           timing_acknowledgement_counter--;
           if (timing_acknowledgement_counter==0)
           {
              rf_acknowledge();
           }
       }
       if (timing_recepetion_timeout_counter>=0)
       {
           timing_recepetion_timeout_counter--;
           if (timing_recepetion_timeout_counter==0)
           {
               rf_link_lost_action();
               #ifndef LEDS_FOR_US
               #ifndef RF_LEDS_BLINKING_MAD
               PORTD.F5=0;
               #endif
               #endif
//             PORTB = 0xF0;
           }
       }
       INTCON.T0IF=0;
    }

    if (PIR1.TXIF)
     {
         if (rf_uart_transmission_queue_length>0)
          {
             rf_uart_transmission_queue_length--;
             TXREG = rf_uart_transmission_queue[rf_uart_transmission_queue_length];
          }
    }
    INTCON.GIE=1;
}




void main()
{
    leds_init(); // trisd assignment
    rf_init();
    delay_ms(250);
    timing_init();
    while (1) ;
}
 

BMorse

Joined Sep 26, 2009
2,675
plus adding some comments to your code would help in deciphering it to give any advice....

and also try running them synchronous instead of asynchronous, especially since you are doing a slave and master......

B. Morse
 
Top