0
\$\begingroup\$

I'm working to send frame of 8 bytes to Micro-controller Xmega128a1 (via RS485). The frame looks like this:

{header1,header2,CMD,D1,D2,D3,D4,CRC}

For example:

{0x55,0xaa,0xFF,0x59,0xfd,0x64,0x68,0x32}

The micro-controller has to resend the frame back to the PC, if it's 'correct'. The frame received is correct if the header is {0x55,0xaa}.

I used ASF drivers for USART,TIMER,I/O,CPU and PMIC also added fifo, gpio,c lock system and IOport services.

The serial port ISR raises a flag every new byte (new_byte_resived_flag). In the while loop I add every new byte to an array of 8 bytes Rx_buf_F0 (witch represent the received frame). When the frame received is complete, I set the a flag frame_completed_flag to 1. Also, in the while loop I make a verification if the frame is correct or not. If it is, then I send it back to PC.

Sampling flag is raised every 50ms to assign the correct data frame received to variables such as CMD,data[i],i=3,4,5,6.

The problem is: when I send a frame to the micro-controller, sometimes it replies but not with the correct frame.

The serial port is working good but I think I have problems using buffers and fifo functions in the correct way. My code:

#include <asf.h>
#include <compiler.h>
#include <sysclk.h>
#include <board.h>
#include <gpio.h>
#include "tc.h"
uint8_t sampling_flag =0;
uint8_t i=0;
uint8_t n=0;
uint8_t CRC=0;
uint8_t flag_rx_Frame_F0=0;
uint8_t new_byte_resived_flag=0;
uint8_t frame_completed_flag=0;
uint8_t fram_recived_correct_flag=0;
fifo_desc_t rx_fifo_F0;
uint8_t Rx_buf_F0[8] = {0x48 , 0x75, 0x73, 0x73,  0x61, 0x6d, 0x59, 0x0d};
static void my_callback(void)
    {

        sampling_flag = 1;
    }


uint8_t rx_buffer[32];
ISR(USARTF0_RXC_vect)
{
    //ioport_set_pin_low(LED1_GPIO);
    uint8_t received_byte;
    //while(i<7){
    received_byte = usart_getchar(&USARTF0);
    //Rx_buf_F0[i] = usart_getchar(&USARTF0);   
    fifo_push_uint8(&rx_fifo_F0, received_byte);
    //if(fifo_get_used_size(&fifo_desc) == 0) break;          
    new_byte_resived_flag=1;
    //fifo_push_uint8(&rx_fifo_F0, received_byte);
    usart_clear_rx_complete(&USARTF0);
 }
 uint8_t  CMD;

 uint8_t data[4] = {0x00 , 0x00, 0x00, 0x00};


int main (void)
{
    /* Insert system clock initialization code here (sysclk_init()). */
    board_init();
    sysclk_init();

      /////////////////////////////////////////////////////////////////////////////////////tIMER C0 INIT
     tc_enable(&TCC0);
     tc_set_overflow_interrupt_callback(&TCC0, my_callback);
     tc_set_wgm(&TCC0, TC_WG_NORMAL);
     tc_set_overflow_interrupt_level(&TCC0, TC_INT_LVL_LO);
     tc_write_period(&TCC0, 25000);
     tc_write_clock_source(&TCC0, TC_CLKSEL_DIV64_gc);
//////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////USART RS232 MODE INIT
     static usart_rs232_options_t USART_SERIAL_OPTIONS = {
         .baudrate = 38400,
         .charlength = USART_CHSIZE_8BIT_gc,
         .paritytype = USART_PMODE_DISABLED_gc,
        .stopbits = true
     };
/////////////////////////////////////


///////// Initialize usart driver in RS232 mode
      usart_init_rs232(&USARTF0, &USART_SERIAL_OPTIONS);
      sysclk_enable_module(SYSCLK_PORT_F, PR_USART0_bm);
      PORTF.DIRSET = PIN3_bm;
      usart_set_rx_interrupt_level(&USARTF0, USART_INT_LVL_HI);
      fifo_init(&rx_fifo_F0, rx_buffer, 32);

     pmic_init();
     cpu_irq_enable();

     while (1)
     {


     if(new_byte_resived_flag==1)
     {
        new_byte_resived_flag=0;
        i++;
       Rx_buf_F0[i]=fifo_pull_uint8_nocheck(&rx_fifo_F0);
       if(i==7)
       {
          frame_completed_flag=1;
         i=0;
       }
     }


     if (frame_completed_flag==1)
         {
              frame_completed_flag=0;

                if (Rx_buf_F0[0]==0x55 && Rx_buf_F0[1]==0xaa )
                 {

                         for (int j = 0; j < 7; j++)
                         {
                             usart_putchar(&USARTF0, Rx_buf_F0[j]);
                          }
                          fram_recived_correct_flag=1;
                  }

       }

     if (sampling_flag==1)
          {
              sampling_flag=0;
                           if ( fram_recived_correct_flag==1)
          {
               fram_recived_correct_flag=0;

               CMD=Rx_buf_F0[2];
               for(int k=3;k<7;k++)
               data[k]=Rx_buf_F0[k];
               CRC= Rx_buf_F0[7];
               for (int j = 0; j < 7; j++)
                       {
                        Rx_buf_F0[j]='\0';
                       }
 }
           }   

    }//end of while(1)  
}//end of main
\$\endgroup\$
1
  • \$\begingroup\$ You really need to work on your indention and coding style. Use code templates and be consistent in how you write programs. This is likely the cause of many of the bugs here. \$\endgroup\$ – Lundin May 17 '16 at 6:52
2
\$\begingroup\$

Some bugs:

  • Arrays in C start at index zero. You write to index 1 to 8, instead of 0 to 7:

    i++;
    Rx_buf_F0[i] = ...
    
  • You should declare all variables shared between main and and ISR volatile to protect against incorrect compiler optimizations. Also, it would seem that you have no semaphores to protect rx_fifo_F0. Accesses to that variable will not be atomic, so if you have no semaphores you will get intermittent bugs where random garbage suddenly appears in that variable.

  • data is 4 bytes large yet you write to index 3 to 7.

    for(int k=3;k<7;k++)
    data[k]=Rx_buf_F0[k];
    

Might be more, but these are all severe bugs.

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.