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.

UART Transmit Shift Register

Other Parts Discussed in Thread: MSP430F5529

Is there a way to set an interrupt to occur when the transmit shift register is empty?

  • Hi,

    you might want to tell us which device you are using because there are different UART modules available (USART, USCI, eUSCI) on the MSP430 devices.

  • Msp430f5529.

  • Hi,

    so the MSP430F5529 has the USCI_A module which can be used as UART interface. Looking into the User's Guide documentation, there is no way to generate an interrupt if the UART transmit shift register is empty. However i think you can poll the UCBUSY bit of UCAxSTAT register to find out whether the module is currently transmitting or receiving.

  • The easiest is to check UCBUSY in the Transmit ISR.  Unfortunately, this ties up other ISR's while it is busy. 

    The simplest would be get an interrupt when the serial port is empty ... needed for half duplex operation. 

  • Hi,

    i have an idea which i haven't tested myself, however you could do the following way:

    - if the baud rate is known, you can setup a timer to run in the USCI TX interrupt when the byte is transfered from TX buffer to the shift register.

    - the timer should trigger an interrupt around e.g. 10 bit time for 8 bit data (+1 for start bit and, +1 for stop bit) of the UART baud rate. You might add some small delay to make sure that the byte has been fully shifted out or even check the UCBUSY bit in the timer interrupt.

    By this, you can have an interrupt after the byte is shifted out from the TX shift register, although it is not 100% accurate.

    Hope this helps.

  • I've considered that.  The timers are quite busy, although mux'ing could be done.  I would be much simpler to get an interrupt when the serial port shift register is empty.

    The code already exists inside the MSP ... indicates when the byte is to be transferred to the shift register.  It would be good to give users access ... and provide an interrupt for folks who use half duplex. 

  • 460822 said:
    would be much simpler to get an interrupt when the serial port shift register is empty.

    Indeed. I required this myself for RS485 operation. However, the eUSCI of the FR57xx family is the first one that offers this feature.

    460822 said:
    The code already exists inside the MSP ... indicates when the byte is to be transferred to the shift register.

    No, this information means that there was something in TXBUF, so transmission will continue and TXIFG has to be raised.
    A shift register empty should come when there is nothing in TXBUF and operation cannot continue (otherwise you'd get spurious interrupts on each byte).

    I'd too like to get additional interrupts like frame error or parity error interrupt. However all these are only connected to RXIFG and need to be checked in software (or do not, if you chose to ignore defective bytes). This makes it impossible to detect bus errors while doing normal receive in DMA.

    I ended up with a busy delay too. But not inside the ISR. The main code waits for the end of a transfer anyway, so it adds 2ms (on 9600bd) after the last byte was written to TXBUF and then disables the transmitter.
    I even considered a monoflop: the start bit on TX triggers the monoflop, which will expire >10 bit times after the las low-goping edge., This way, the transceiver disables the oputput 0..9 bit times after the last stopbit (depending on the data of the last byte). Our simple RS232/RS485 ocnverter uses this, but of course it works only for a fixed baudrate.

  • Hi 460822,

    I use the UCLISTEN bit in the UCAxSTAT register to get an RX interrupt.  When you RX your last TX'd byte, the TX shift register is empty.  The TX side might still be finishing the stop bit, but you can manage that issue if needed.

    Obviously this solution works only for half-duplex applications, but you did mention "folks who use half duplex".

    I'm excited about the eUSCI and its seemingly small improvements, including the TXEPT interrupt.  But none of our projects have it yet.

    Jeff

  • Jeff Tenney said:
    I use the UCLISTEN bit in the UCAxSTAT register to get an RX interrupt. 

    Wow! Why didn't I think of it? The USART already had a LISTEN mode (I used RS485 on the 1611 only). Smart idea.
    However, the rather poor RS485 bus implementation (no my design) did have rahter high reflections when the transmitter was deactivated too soon, so I had to do a delay of 1-2ms anyway.

  • Jens-Michael Gross said:
    Wow! Why didn't I think of it?

    Funny how these ideas often come as "inspiration" -- which inevitably means many great ideas just don't come up!

    Notice that in this case, the UCLISTEN bit (or LISTEN bit on USART) doesn't work properly in a multi-master situation since this approach precludes collision detection.  But for many applications using half duplex, this solution works because there is just one master.

    Jeff

  • Jeff,

    Jeff Tenney said:

    I use the UCLISTEN bit in the UCAxSTAT register to get an RX interrupt.  

    This is indeed the most elegant solution for this problem!

    I added this to the MSP430 FAQ Tips and Tricks! http://processors.wiki.ti.com/index.php/MSP430_FAQ#How_to_generate_interrupt_on_transmission_completion_using_the_USCI_module.3F

  • When do you set the UCLISTEN bit to ensure the last byte is read properly?  ... concern is that the UCLISTEN bit is set while the transmit serial port is transmitting a previous byte. 

    Perhaps UCLISTEN is set at the very beginning? Then the serial port receive interrupt is set when the last byte is put into the serial port register? 

  • 460822 said:
    When do you set the UCLISTEN bit ... ?

    Yes, that is the question.  But the answer is application dependent.  For example, in my application, I set UCLISTEN whenever I switch to transmit mode (and I clear UCLISTEN whenever I switch to receive mode).  I think it is the most modular solution since it works for any high-level protocol.  However, it also has the highest cost since it results in two interrupts per transmitted character.  Plus in my application I use an echo counter, which must be handled with care.  (Again, this is to support any HLP.)

    However, your communication protocol may allow for simpler implementations.  For example, if the protocol is character based (eg, ASCII), then maybe you could use a dedicated End-Of-Transmission character.  In that case, you could set UCLISTEN when you put the EOT character into TXBUF.  Your RX ISR could watch for the EOT character.

    Good luck.

  • EOT is not an option.  What are the details? ... when a byte is loaded into the shift register -> generates a transmit buf empty interrupt, is it solid (bullet proof) to enable the receive interrupt in the ISR and know it is going to work every time?

    It would be best if TI modified the design and generated an interrupt when the shift register is empty.  Half duplex is very common. 

  • 460822 said:
    It would be best if TI modified the design and generated an interrupt when the shift register is empty.

    They have done exactly that.  The eUSCI (now available in several 5xx/6xx devices) has that interrupt.

    460822 said:
    is it solid (bullet proof) to enable the receive interrupt in the ISR and know it is going to work every time?

    No, it's not.  To be bullet proof, the RX interrupt should be enabled when you put the character into the TXBUF.

    Jeff

  • Jeff Tenney said:
    it also has the highest cost since it results in two interrupts per transmitted character.

    Not necessarily. You can set UCLISTEN when you go into transmit mdoe but keel RXIE clear. When you write the last byte to TXBUF, you clear TXIE, clear RXIFG and set RXIE. When the RX interrupt comes, check UCBUSY. You have either received the forelast byte and exit or the last byte and are done.
    You don't knwo whether ou received the forelast or last byte because you don't know whether the shift register was already empty or still transmitting the forelast byte when you stuff the last byte in, depending on interupt latency. If you can be sure by design that you're handling the TX interrupt after the last byte while the last byte is still being sent, you can enable RX interrupt then. However, it makes no difference whether you get one more TX interrupt or one more RX interrupt. And the RX version is more safe.

  • Great idea, but I don't think it is safe to count on UCBUSY being cleared in time.  TI docs are not clear on the issue, and TI has been unwilling to commit to particular behavior.

    When using the "standard" 3x sampling (not 16x oversampling), the character can be fully received after half of the stop bit.  (After the first 2 samples agree, there is no need for the third sample.)  It is reasonable that UCBUSY would remain set for the rest of the bit time.  At many common UART bit rates, a half a bit time is plenty of time for an ISR to run to completion.  The ISR could see UCBUSY set when the design requires that the ISR find UCBUSY clear.

    So I use an echo counter and an RX interrupt for every TX character.  And I'm looking forward to upgrading to silicon with the eUSCI to get rid of these two drawbacks.

    Jeff

  • Jeff Tenney said:
    Great idea, but I don't think it is safe to count on UCBUSY being cleared in time. 

    I agree. Anoteh ridea: by knowing the MCLK/USCI timing relation, you can check whether the TXBUF is already empty or still sending previous byte when stuffing the last byte into TXBUF (check TXIFG bit immediately). So you can flag to the RX ISr whether to expect one or two bytes. However, since as you said RX interrupt can be come early, it is advised to add a safe delay after knowing the last bit has been received. e.g. by starting a timer. And the timer ISR is shuttong the transmitter off then.

  • If RXIFG is received early, then you can probably busy-poll UCBUSY inside the ISR with minimal overhead (worst case half a stop bit as Jeff pointed out). You can then switch to receive mode by setting TX pin to high impedance input; if your MCLK is high enough there should be no effect on the UART timing.

    If you can sacrifice a few cycles inside the ISR this may be preferable than using the already-busy timers.

    Tony

  • Good that new devices include this feature.  Will it be added to existing devices? ... perhaps add a letter such as 'A' to the part number to distinguish the added capabilities.

    The safest way, for now, appears to set an interrupt timer after the TXBUF is empty ... allows time to the shift register to complete the transmit.

  • 460822 said:
    The safest way, for now, appears to set an interrupt timer after the TXBUF is empty ... allows time to the shift register to complete the transmit.

    That should work nicely.  It saves you from 2 interrupts per character and the corresponding maintenance of an echo counter.

    Just use appropriate caution since you'll be starting the timer from an ISR.  If you can dedicate a CCRx for this task then there's probably no issue (depending on your software design and other uses of the timer module).

    Jeff

  • In case you are building rs485 which is half-duplex - do not switch TX/RX direction at all but leave receiver always operational. When you send byte out, set flag for receiver IRQ routine to ignore it. That's it!

**Attention** This is a public forum