This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP 430 UART Rx problem

Hello,

I'm working with the msp430 uart to interface with another component. My Tx function works just fine, but when I try to recieve a string of characters, I only end up getting the last one. I think this is because the Rx flag is only triggering once (though I thought it would trigger each time the rx buffer filled), but it could be some other issue. Please help. My code is below.

/*
* main.c
*/

#include "msp430.h"
#include "stdio.h"


// Transfers the given string over the UCSI UART port. Uses explicit length, instead
// of looking for a null byte to terminate the string.
void TXString(char* string, int length, char* check){
int pointer;
for( pointer = 0; pointer < length; pointer++)
{
UCA1TXBUF = string[pointer];
check[pointer]=UCA1TXBUF;
while (!(UCA1IFG & UCTXIFG)); // USCI_A0 TX buffer ready?
}
}

volatile int i=0;

void main(void) {

WDTCTL = WDTPW + WDTHOLD; // Stop WDT


char output[2];
output[0]='r';
output[1]='\r';


P5DIR |= (0x0040);
P5DIR &= ~(0x0080);

P5SEL |= (0x0040);
P5SEL |= (0x0080);
// P5.6,7 = USCI_A1 TXD/RXD


UCA1CTL1 |= UCSWRST; // **Put state machine in reset**
UCA1CTL1 |= UCSSEL_2; //Select 1MHz clock
UCA1BR0 = 27; // baud rate=38400 (User's guide)
UCA1MCTL |= UCBRS_2+UCBRF_0; // Modulation UCBRSx=2, UCBRFx=0

UCA1CTL0 = 0; //Does all of the below things
// Parity disabled
// 8-bit data length
// 1 Stop bit
//Asynchronous mode

UCA1CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UCA1IE |= UCRXIE+UCTXIE;                  // Enable USCI_A1 RX interrupt, AND Enable USCI_A1 TX interrupt


char check[20];

__enable_interrupt(); //Enabling interrupts without entering low power mode


P1DIR |= 0x01; // Set P1.0 to output direction for test
for(;;){

volatile unsigned int i; // volatile to prevent optimization

P1OUT ^= 0x01; // Toggle P1.0 using exclusive-OR

TXString(output, 2, check);
i = 100000000; // SW Delay
do i--;
while (i != 0);
}

}


#pragma vector=USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
{
char check2[20];


switch(__even_in_range(UCA1IV,4))
{
case 0:break; // Vector 0 - no interrupt
case 2: // Vector 2 - RXIFG
puts("Received!");
check2[i]=UCA1RXBUF; //This might not do what I think it does
i++;
printf("Check2[0]: %c \n", check2[0]);
printf("Check2[1]: %c \n", check2[1]);
printf("Check2[2]: %c \n", check2[2]);
printf("Check2[3]: %c \n", check2[3]);
printf("Check2[4]: %c \n", check2[4]);
printf("Check2[5]: %c \n", check2[5]);
printf("Check2[6]: %c \n", check2[6]);
printf("Check2[7]: %c \n", check2[7]);

break;
case 4:
puts("Transmitted!");
break; // Vector 4 - TXIFG
default: break;
}
}
  • but when I try to recieve a string of characters, I only end up getting the last one

    The char check2 array in the USCI_A1_ISR has automatic storage allocation (on the stack) and so will be uninitialized on every ISR, which is why only the last one is displayed.

    Also, what prevents writing off the end of the array after more than 20 received interrupts have occured? (i is incremented on every receive ISR but I can't see where it is reset) 

     

  • Thank you for your timely and helpful reply. Unfortunately the problem is still not quite solved. 

    I moved the declaration of the char check2[20] array outside of the ISR, to right after I declared the int i (near the top of my code and outside of main as well). Now the array will have the first and last character of any string that I try to receive, but none in between, regardless of the length of the string. Any idea why that might be? I suspect it has something to do with the triggering of the interrupt because the "Received!" message that I print to the console only gets displayed twice, regardless of the length of the string as well, which I think must mean the ISR is only running twice, right?

    In cleaning up the code for posting I accidentally deleted:

    if(i>19){

    		i=0;
    }
    But that's not really important, as it will be something different once I get the Rx working properly.
    Any additional help would be great.
  • Performing a printf in every receiver ISR could be slowing down the processing such that receive interrupts are missed

    The MSP430 UART has one Receive Shift Register to assemble a receive character and one Receive Buffer (UCA1RXBUF) to hold the last received character waiting to be read by the software. What is probably happening is:

    a) The first character is received and transfered to the UART Receive Buffer, which sets the UCRXIE receive interrupt flag

    b) The USCI_A1_ISR is entered and reads the first character from the UART Receive Buffer

    c) The printfs in the USCI_A1_ISR take longer to execute than the time to receive the complete string

    d) Further characters are receive while the 1st USCI_A1_ISR is still performing the printfs. The last received character overwrites any previous ones in the UART Receive buffer and sets the Receive Overrun UCOE flag.

    e) Once the 1st USCI_A1_ISR has completed its printfs, it is re-entered to read the last receiver character from the UART Receive buffer

    If my theory is correct, when the 2nd USCI_A1_ISR runs (which prints the last received character) the UCOE flag will be set.

    Suggest that the code needs to be changed to only perform the printf once the complete string has been received. e.g. by the main function.

  • You were absolutely correct. I moved the printing of the check array to the main function and now the receive works perfectly.

    Thank you so much for help.

    -Ryan Caskey

**Attention** This is a public forum