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.

MSP430FR6989 UART TX interrupt reenable?

Other Parts Discussed in Thread: MSP-EXP430FR6989, MSP430FR6989

I'm using a char array to store data that I want transmitted to another device using UART.

My TX code for my UART ISR is as follows:

   case USCI_UART_UCTXIFG:
    	if (send_buffer[current_send] != '\0')
    		UCA1TXBUF = send_buffer[current_send++];
    	else
    		UCA1IE &= ~UCTXIE;
		break;

The first transmission is fine, but after

UCA1IE &= ~UCTXIE;

is executed, I can't get the ISR to send data again. I thought all I had to do was reenable the TX interrupts:  

UCA1IE |= UCTXIE;

Am I missing something?

  • Hi Sammy!

    Is the TXIFG set when you re-enable the interrupts? From the few lines you have posted, the flag should not get cleared because this happens when something is written into the TX buffer which is not done in your case. Or do you clear the flag somewhere else?

    Dennis
  • Sammy Lin said:
    ... I thought all I had to do was reenable the TX interrupts...  

    You may also need to load another string into "send_buffer[]", and make "current_send" point to the beginning of that buffer.

  • Yes, OCY is right. If current_send still points to the end of the string where the '\0' is located, there won't be any new transmission, of course. You have to reset it:

    case USCI_UART_UCTXIFG:
      if( send_buffer[current_send] != '\0' )
        UCA1TXBUF = send_buffer[current_send++];
      else
      {
        UCA1IE &= ~UCTXIE;
        current_send = 0;
      {
    
      break;

    Dennis

  • Yes, I set current_send = 0 and load a new string in to send_buffer.
    The contents of UCA1IFG after I reenable UCTXIE is 0000000000001100. TXIFG (0x02) is still set.
  • In that case, you may need to do: "UCA1TXBUF = send_buffer[current_send++];" to kickstart sending the rest of the string in ISR.
  • But is the transmit interrupt edge triggered? I'm not sure, but I always thought it is level triggered.
  • I do not know either. If it is edge triggered, we do not even need to disable that interrupt after the last byte and enable it later. That is cool!
  • "UCA1TXBUF = send_buffer[current_send++];" 

    This worked. Though I'd still like to understand why. Can you explain?

  • Could you please upload the complete code for testing? Do you work with the MSP-EXP430FR6989 LaunchPad?

  • Dennis,

    I found out that the interrupt is level triggered. But reading the IV will clear the IFG.
    I do not have a good way to handle it. Do you?

    --OCY
  • Dennis,

    Here is my clumsy attempt to let CPU go to sleep until the last bit of a string left the TXD shift resister.

    #include <msp430fr6989.h>
    
    const char msg[] = "This is a test.\r\n";
    const char * ptr;
    volatile int bytes_in_queue;
    
    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;
      PM5CTL0 &= ~LOCKLPM5;
        
      P3SEL0 |=  0x30;                      // assign UCA1TXD and UCA1RXD pins
    
      P1OUT = 0;
      P1DIR = BIT0;                         // use LED to indicate TXD status
    
      UCA1CTLW0 |= UCSWRST;
      UCA1CTLW0 = UCSWRST|UCSSEL__SMCLK;
      UCA1BRW = 6;
      UCA1MCTLW = 0x2081;
      UCA1CTLW0 &= ~UCSWRST;
    
      __delay_cycles(10000L);
     
      bytes_in_queue = 0;
      ptr = msg;
      UCA1IE = UCTXIE|UCTXCPTIE; 
      
      P1OUT |= BIT0;                        // indicate begin TXD
      __bis_SR_register(CPUOFF|GIE);
      P1OUT &= ~BIT0;                       // indicate TXD complete
    
    // ... ... ... ... ...  
    
      __delay_cycles(10000L);
    }
    
    #pragma vector = USCI_A1_VECTOR
    __interrupt void usci_a1_isr (void)
    {
      switch (__even_in_range(UCA1IV, 8))
      {
      case USCI_NONE:
        break;
      case USCI_UART_UCRXIFG:
        break;
      case USCI_UART_UCTXIFG:
        if (*ptr)
        {
          UCA1TXBUF_L = *ptr++;
          bytes_in_queue++;
        }
        break;
      case USCI_UART_UCSTTIFG:
        break;
      case USCI_UART_UCTXCPTIFG:
        if ((--bytes_in_queue) == 0)
          __bic_SR_register_on_exit(CPUOFF|GIE);
        break;
      }
    }

  • Interrupt driven serial transmit routines are tricky as I found when I first tried them on the MEX68KECB. The problem is what happens when you run out of data. On some systems (like the MEX68KECB) the only way to clear the transmit interrupt is to store data into the transmit buffer register. In that case you have to disable interrupts.

    In this case servicing the interrupt clears it and it will not happen again. So there is no need to disable the interrupt.

    The other side of this is restarting transmission. In this case all you have to do is manually store (not using the ISR) the first byte to the transmit buffer register. That can get tricky if you are using a FIFO buffer rather than well defined packets.
  • Maybe my project ASCIImage for the JMG-Day can give some further ideas. It uses the UART as well and it toggles between two data containers that are sent out interrupt driven. The project can be found here:

    It is a very long project description, but quite detailed. I start the transmission like this:

    void send_ascii_image( const uint8_t * ascii_image_pointer )               // Function starts sending an image
    {
      image_x_count = 1;                                                       // First byte is sent from this function
      image_y_count = 0;                                                       // Reset y counter
      image_pointer = ascii_image_pointer;                                     // Copy address of ASCII image
    
      LED2_GREEN_ON;                                                           // Light up green LED
      UART_CLEAR_TX_IFG;                                                       // Clear pending TX interrupt flag
      UART_ENABLE_TX_IR;                                                       // Enable TX interrupts
    
      UART_TX_BUFFER = *(image_pointer + ASCII_IMAGE_DATA_START);              // Send first byte of image
    }

    As you can see, I first clear any pending TXIFG, then enable the TX interrupts and copy the first byte into the TX buffer.

    Dennis

  • hello, old_cow_yellow !! i have Tiva (master) and MSP430FR6989 (slave), i need read data from pin (2.0) in FR6989 and transmit it via UART to TIVA, your code is work for that ?

    How can I get a UART connection physically, what pins should I connect ?

**Attention** This is a public forum