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.

CCS/MSP430FR5994: RS485 wait for transmitter empty

Part Number: MSP430FR5994
Other Parts Discussed in Thread: MSP430F149

Tool/software: Code Composer Studio

I use the MSP430FR5994 with an RS-485 Transceiver (SN65HVD12D).

The RS485 transmission begins always with the setting of the RE and DE pins to TX mode (of the RS-485 Transceiver). After that several Bytes are send trough the bus. And finally, we returned in the RX mode for receiving the answer. But before we could do that, we must wait that the transmit buffer is empty. I found several examples using the following command "while((UTCTL1 & TXEPT)==0x00) _NOP();". It works well for the MSP430F149, but not for the MSP430FR5994.

Do someone knew the right command for the waiting time before we could return in the receive mode? It is the time until the TX buffer is empty.

//Sending one single Byte
void sendRS232(unsigned char data)     // sends one byte
{  while (!(UCA1IFG & UCTXIFG));            // loop until USART1 TX buffer ready
   UCA1TXBUF = data;
}

//Sending an rs485 command
{  RS485TX;                                                            //Set RS485 transceiver output Pins to TX
   unsigned int i;
   for (i=0;i<size;i++)
      {sendRS232(data[i]);}
   while((UTCTL1 & TXEPT)==0x00) _NOP();    //wait for transmitter empty (false command for the MSP430FR4995)
   RS485RX;                                                              //Set RS485 transceiver output Pins to RX
}

  • If UCTXCPTIFG worked s advertised you would use that. But it doesn't (see errata). There is no official workaround but I have found that checking TXIFG in the UCTXCPTIFG interrupt handler gets the job done for me.

        case USCI_UART_UCTXCPTIFG:
          /*
            There is a hardware bug (not mentioned in the errata) causing this
            interrupt to happen early and often. I check the transmit buffer
            register empty flag as well. This seems to control the problem.
           */
          if(UCA0IFG & UCTXIFG)
            {
              P3OUT &= ~0x10;          // disable RS485 transmitter
            }
          break;
    

    The errata appeared after I wrote this code. I seem to remember other possible approaches so see if a search on UCTXCPTIFG turns up anything.

  • Thank you for your answer. It seems that it is the right direction.

    As you suggested, I placed a "while (!(UCA1IFG & UCTXIFG));" loop just before the "RS485RX;". Now the RS485 signal, that passes thought the transceiver, is longer. But it seems, that the interrupt flag is released, when the last byte of the string has just started to be send, and not when this operation is finished.

    //Sending an rs485 command for test purpose
    {  RS485TX;                                                            //Set RS485 transceiver output Pins to TX
       unsigned int i;
       for (i=0;i<size;i++)
          {sendRS232(data[i]);}
       SET(P6OUT, 0x20);                                             //Set Port (blue line)
       while (!(UCA1IFG & UCTXIFG));
       CLEAR(P6OUT, 0x20);                                        //Clear Port (blue line)
       RS485RX;                                                              //Set RS485 transceiver output Pins to RX
    }

    Blue: Duration of the "while (!(UCA1IFG & UCTXIFG));" loop
    Yellow: Signal that passes through the transceiver (A/B lines)
    Red: UART signal, that came from the micro controller (TX line)

    The oscilloscope shows that the "while (!(UCA1IFG & UCTXIFG));" released too early, before all the string sending is complete. And so the "RS485RX;" stopped the transceiver too early, while sending the last byte.

    Do you have an idea of what I could do to resolve this problem?

  • Of course checking just TXIFG is a problem. That gets set when TXBUF is empty, not when the shift register is empty. My check was in an ISR in response to another interrupt.

    For polled operation where you are absolutely certain that the receiver is idle, check UCBUSY.

  • Thanks a lot.

    With the check of "while( UCA1STATW & UCBUSY );", it works now.

**Attention** This is a public forum