Search code examples
microchipusart

dsPic Receive 11byte usart string


I'm using a dsPic33 to try and receive a 11-byte string and place it in a array, but have not been successful at receiving it completely. The string I send is "$123456789#" which should be received by the pic. I have tried using the code below. Any help will be appreciated.

char inBytes[11];
int i;
unsigned char temp;

while (U1STAbits.URXDA != 0)
{
  temp = U1RXREG;
  if (temp == '$')
  {
      inBytes[0] = temp;
      for(i = 1; i < 10; i++)
      {
        if (U1STAbits.URXDA != 0)
        inChar = U1RXREG;
        inBytes[i] = inChar;
      }
  }

Solution

  • jolati had a good point about the end value beeing too low to get 11 bytes but I must add that you have to wait for your other bytes to become available before you read them.

    In your example;

    char inBytes[11];
    int i;
    unsigned char temp;
    
    while (!U1STAbits.URXDA ); //Wait until at least one byte is available
    
    temp = U1RXREG;
    if (temp == '$')
    {
        inBytes[0] = temp;
    
        for(i = 1; i < 11; i++) //Loop over range i = 1 to 10 inclusively
        {
            while (!U1STAbits.URXDA ); //Wait until at least one byte is available
            inBytes[i] = U1RXREG;
        }
    }
    

    Ideally, you would do this in a non blocking way with interrupts so you handle your data as it comes in but, if you cant use interrupts, you can always use non blocking polling like:

    void AsyncRX()
    {
        //Note that the static variables keeps their value between invocations of the
        //  function. i is set to 0 only on the first run of this function, it keeps 
        //  its value on every other run after that.
        static int i = 0;
        static char inBytes[11];
    
        //Nothing more to do until there is at least 1 byte available
        if( !U1STAbits.URXDA ) 
            return;
    
        //Save the byte and test that our message starts with $
        inBytes[i] = U1RXREG;
        if( inBytes[0] != '$' )
            return;
    
        //Test the counter to see if we have a full 11 bytes
        i++;
        if( i < 11 )
            return;
    
        //Do something with your 11 bytes
        //...
        //...
    
        //Reset the counter for the next message
        i = 0;
    }
    

    For the interrupt example, you could simply grab the polled version and throw it into a ISR. The following is an example. Note that I do not know which dsp33 you are using and I have not programmed interrupts in high end cores (with vector tables) in a while so you may need to make a change or two. Also note that you need to enable interupts by setting the appropriate registers as they are not enabled by default.

    void __attribute__ ((interrupt, no_auto_psv)) _U1RXInterrupt(void) 
    {
        //Note that the static variables keeps their value between invocations of the
        //  function. i is set to 0 only on the first run of this function, it keeps 
        //  its value on every other run after that.
        static int i = 0;
        static char inBytes[11];
    
        //Reset the interrupt flag
        IFS0bits.U1RXIF = 0;
    
        //Use up all bytes in the buffer (the interrupt can be set to only fire 
        //  once the buffer has multiple bytes in it).
        while( U1STAbits.URXDA ) 
        {
            //Save the byte and test that our message starts with $
            inBytes[i] = U1RXREG;
            if( inBytes[0] != '$' )
                continue;
    
            //Test the counter to see if we have a full 11 bytes
            i++;
            if( i < 11 )
                continue;
    
            //Do something with your 11 bytes
            //...
            //...
    
            //Reset the counter for the next message
            i = 0;
        }
    }