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-EXP430FR5994: UART Transmit Interrupt skipping characters

Part Number: MSP-EXP430FR5994

Hi,

I am trying to transmit data using the transmit ISR, however I notice am missing some characters. I use a delay function however am trying to avoid using it. Is there a condition I can use to only run the ISR when a character has fully been sent.

#pragma vector=USCI_A1_VECTOR
__interrupt extern void USCI_A1_ISR(void)
{
switch (__even_in_range(UCA1IV, USCI_UART_UCTXCPTIFG))
{
case USCI_NONE:
break;

case USCI_UART_UCRXIFG:
if (coordinator.gpsManager.buffer.overFlow) // if write buffer is behind read buffer, break to prevent overwriting data that has not been read
{
break;
}
else
{
char byte = UCA1RXBUF;
coordinator.gpsManager.buffer.push(byte);
}
break;

case USCI_UART_UCTXIFG:
coordinator.gpsManager.sendNextByte();
break;

case USCI_UART_UCSTTIFG:
break;

case USCI_UART_UCTXCPTIFG:
break;
}
}

void Manager::sendNextByte()
{
if (transmit.mWrite == transmit.mRead) // if the mWrite == mRead, we don't have any data
{
deviceBusy = false;
return;
}

UCA1TXBUF= transmit.pop();

// __delay_cycles(16000);
}

  • Hi Kirushigan,

    there is a code example in Code Composer Studio and the TI Resource Explorer in the same, which demonstrates how to ensure based on the TX interrupt flag overriding the transmit of a byte.

    msp430fr599x_eusci_uart_standard_transceiver.c

    Please check this code example for details.

    Best regards

    Peter

  • The details of which characters are missing is critical to figuring out where the problem is. As is your non-interrupt code for sending data.

  • Hi,

    Thanks, however I tried that prior to posting, and when i have that condition, it doesn't transmit anything.

    void Manager::sendNextByte()
    {
    if (transmit.mWrite == transmit.mRead) // if the mWrite == mRead, we don't have any data
    {
    deviceBusy = false;
    return;
    }
    while(!(UCA1IFG&UCTXIFG));
    EUSCI_A_UART_transmitData(UART, transmit.pop());

    //__delay_cycles(16000);
    }

  • I am getting this as the transmission,

    $PSRF10,00,00,00,01*24
    $PSRF103,01,00,00,01*25
    $PSRF103,02,00,00,01*26
    3$PSRF03,03,00,00,01*27
    $PSRF103,04,00,70,01*27
    1$PSRF103,05,00,00,01*21

    however i need, 

    $PSRF,103,00,00,00,01*24
    $PSRF,103,01,00,00,01*25
    $PSRF,103,02,00,00,01*26
    $PSRF,103,03,00,00,01*27
    $PSRF,103,04,00,70,01*27
    $PSRF,103,05,00,00,01*21

    most of the first set of commas are missing as well as a "3" and a "1" transmitting at the wrong position. I use the sendnextbyte function to kick start the ISR routine to transmit data

  • Hello Kirushigan,

    using the while(!(UCA1IFG&UCTXIFG));, means the TXIFG is basically the only safe way, how to safely drive UART transmit. So if using this expression breaks the TX functionality of your code completely, that means there is another fundamental problem with it. So my recommendation would be not to tr solving it by removal of using the TXIFG, but trying to debug, why this breaks the transmit function.

    I would start with the non modified code example and then if that works, change it step by step towards what you're final implementation should be.

    Best regards

    Peter

  • Details still missing. I do this:

    txhar(char c)
    {
       enqueue(c);
       if(!TXIE)
       {
          TXIE = 1;
          TXIFG = 1;
       }
    }
    

    More or less. (in assembly) The ISR clears TXIE if it finds no more data to transmit. Not really required but it serves as a handy flag. Is your flag declared as volatile? (another missing detail)

  • Yes, it is declared as volatile, my code for sending data is,

    void Manager::sendNextByte()
    {
    if (transmit.mWrite == transmit.mRead) // if the mWrite == mRead, we don't have any data
    {
    deviceBusy = false;
    return;
    }

    EUSCI_A_UART_transmitData(UART, transmit.pop());

    //__delay_cycles(16000);
    }

    #pragma vector=USCI_A1_VECTOR
    __interrupt extern void USCI_A1_ISR(void)
    {
    switch (__even_in_range(UCA1IV, USCI_UART_UCTXCPTIFG))
    {
    case USCI_NONE:
    break;

    case USCI_UART_UCRXIFG:
    if (coordinator.gpsManager.buffer.overFlow) // if write buffer is behind read buffer, break to prevent overwriting data that has not been read
    {
    break;
    }
    else
    {
    //char byte = UCA1RXBUF;
    coordinator.gpsManager.buffer.push(EUSCI_A_UART_receiveData(EUSCI_A1_BASE));
    }
    break;

    case USCI_UART_UCTXIFG:

    coordinator.gpsManager.sendNextByte();


    break;

    case USCI_UART_UCSTTIFG:
    break;

    case USCI_UART_UCTXCPTIFG:

    break;
    }
    }

    and my routine to enable the Transmit ISR is:

    void GPSManager::process(TransitPacket::PacketType type, vector<char> data)
    {
    if (type == TransitPacket::GPSConfig)
    {
    deviceBusy = true;
    prepareToSend(data);
    sendNextByte();
    }
    deviceBusy = false;
    }

  • Too complicated. I have to assume that prepareToSend(data) puts a string into the queue. But that code is missing so I can't tell if it would behave well. But that final deviceBusy=false is a killer.

    You just queued up a string and started transmitting so the UART is in fact busy. Let the ISR, and only the ISR, clear that flag.

    After putting data into the queue, check the flag. If it is false, set the flag and TXIFG, then let the ISR handle the data.

  • Thanks, preparetosendata() places characters into a circular buffer which is processed 

    void Manager::prepareToSend(std::vector<char> tx_data)
    {
    unsigned int i = 0;
    int length = tx_data.size();

    for (i = 0; i < length; i++) // Increment through array, look for null pointer (0) at end of string
    {
    char temp = tx_data[i];
    transmit.push(temp);
    }
    deviceBusy = true;
    }

  • Hi Kirushigan,

    I am not sure whether you're aware of this application report, which addresses debugging serial communication. Maybe that's of help.

    But from top level point of view, as stated before, the only safe method to handle buffer overruns on the TX side is to use the TXIFG flag. As long as you have not implemented this portion working reliably, everything else will be just fighting the symptoms.

    Best regards

    Peter

**Attention** This is a public forum