Reputation: 1
#include <msp430.h>
static int next = 0;
#pragma vector=USCI_A0_VECTOR
interrupt void bc_uart_irq(void) {
int transmit_flag = UCA0IFG & UCTXIFG;
if (transmit_flag && next == 0) {
next = 1;
UCA0TXBUF = 0x01; // should clear UCTXIFG
} else if (transmit_flag) {
next = 0;
UCA0TXBUF = 0x55; // should clear UCTXIFG (doesnt!)
}
}
/**
* main.c
*/
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
// Setup UART pins
P3SEL |= 0x18; // default UCA0TXD/UCA0RXD on P3.3/4
P3DIR |= BIT3 + BIT4;
// source TA0 from SMCLK for debugging
TA0CTL = 0x0220;
UCA0CTL1 |= UCSWRST;
// source USCIA0 from SMCLK
UCA0CTL1 |= UCSSEL__SMCLK;
// set USCI module to UART mode
UCA0CTL0 &= ~UCSYNC;
// configure UART
UCA0CTL0 &= ~UCPEN; // no parity bit
UCA0CTL0 &= ~UC7BIT; // 8-bit data
UCA0CTL0 &= ~UCMSB; // LSB first
UCA0CTL0 &= ~UCMODE0; // UART mode (00)
UCA0CTL0 &= ~UCMODE1;
// Set baud rate to 9600 (br = 104, brs = 1, brf = 0)
UCA0BR0 = 107;
UCA0BR1 = 0;
UCA0MCTL = 0x02; // UCBRSx = 1
UCA0CTL1 &= ~UCSWRST;
UCA0IE |= 0xFFFF; // enable tx and rx interrupts
__bis_SR_register(GIE);
while(1) {}
return 0;
}
I've spent a while debugging this, in all cases dumping data to the transmit buffer does not clear the flag automatically (I've also tried clearing it myself in the interrupt) and does not set UCBUSY high. I also tried using the A1 UART module instead of A0, moving the pinout to 4.4/5 (as I've seen in some other questions), different clocks (I originally had ACLK), as well as setting the UCLISTEN bit high. I'm not sure what else I can try as this seems the same as code I've seen other questions about. I've confirmed that SMCLK is running as the timer goes up with each step of the debugger; the most reasonable culprit is that the clock is simply not getting to the USCI peripheral, but I don't know if that is true nor how to test it. (I'm using CCS and the only weird thing I've gotten is that the compiler yells at me if the data memory model is not small (code is large)).
Upvotes: 0
Views: 98
Reputation: 1
Turns out the issue was that the TX buffer does not actually empty if no wires are connected to it, so the flag never got set. In addition to this, when using the CCS debugger, stepping over an update to the TXBUF did not show that the interrupt flag was reset automatically, yet this does happen while the device is actually running on its own.
Upvotes: 0
Reputation: 126
First, toggle a pin in both if/else cases and check with a logic analyzer or an oscilloscope if the software actually enters these blocks. Only there can you be sure that you enter the block where you write to the transmit buffer.
Second, try the recommended interrupt routine instead, from the Reference Manual:
#pragma vector = USCI_A0_VECTOR __interrupt void USCI_A0_ISR(void) {
switch(__even_in_range(UCA0IV,18)) {
case 0x00: // Vector 0: No interrupts
break;
case 0x02: // Vector 2: UCRXIFG
break;
case 0x04: // Vector 4: UCTXIFG
if (next == 0) {
next = 1;
UCA0TXBUF = 0x01;
} else {
next = 0;
UCA0TXBUF = 0x55;
}
break;
case 0x06: // Vector 6: UCSTTIFG
break;
case 0x08: // Vector 8: UCTXCPTIFG
break;
default: break;
}
}
Upvotes: 0