I have managed to get two of my fr5739s to communicate through UART (at 9600bd with ACLK at 1MHz), where one is transmitting data bytes and the other is receiving. However, I can't get them to do both. That is, if one board is set up for TX, then it cannot receive, and vice versa. I think it has something to do with the P2SEL0/P2SEL1 registers. In the data sheet here: http://www.ti.com/lit/ds/symlink/msp430fr5739.pdf on pg. 76 it states that P2SEL0 should be 0 and P2SEL1 should be 1 in order to set the pins (2.0 TX and 2.1 RX) to TX/RX, but my receive function will not work if the TX bit in P2SEL1 is set to 1. I have spent a lot of time trying to figure this problem out, and I would greatly appreciate any advice that the forum has to offer.
rx.c
#include <msp430fr5739.h>
#include <stdint.h>
volatile uint16_t g_counter = 25000;
volatile uint8_t g_data = 0;
int main(void) {
/* 1. Disable the Watchdog timer. */
WDTCTL = WDTPW + WDTHOLD;
/* 2. Enable LED1-4 for output. */
PJDIR |= BIT3 + BIT2 + BIT1 + BIT0;
PJOUT &= ~(BIT3 + BIT2 + BIT1 + BIT0);
PJOUT |= BIT0;
do g_counter--;
while(g_counter != 0);
/* 3. Configure clock settings. */
CSCTL0_H = 0xA5; // Write CSKEY password to configure clock settings
CSCTL1 &= ~DCORSEL; // Set DCO to 8MHz
CSCTL1 |= DCOFSEL1 | DCOFSEL0;
__delay_cycles(4); // Allow the DCO to settle at 8MHz
CSCTL2 &= ~SELA2; // Set ACLK to DCO
CSCTL2 |= SELA1 | SELA0;
CSCTL2 &= ~SELS2; // Set SMCLK to DCO
CSCTL2 |= SELS1 | SELS0;
CSCTL2 &= ~SELM2; // Set MCLK to DCO
CSCTL2 |= SELM1 | SELM0;
CSCTL3 &= ~DIVA2; // Divide ACLK by 8
CSCTL3 |= DIVA1 | DIVA0;
PJOUT |= BIT1;
do g_counter++;
while(g_counter != 25001);
/* 4. Configure pins 2.0 (TX) and 2.1 (RX) for UART. */
P2SEL0 &= ~(BIT1 | BIT0);
P2SEL1 &= ~BIT0; // RX won't work if TX P2SEL1 is on.
P2SEL1 |= BIT1;
PJOUT |= BIT2;
do g_counter--;
while(g_counter != 0);
/* 5. Configure UART settings. */
UCA0CTLW0 |= UCSWRST; // Allow UART settings to be edited
UCA0CTLW0 &= ~UCPEN; // Disable parity bits
UCA0CTLW0 &= ~UCMSB; // Set data transfer to LSB first
UCA0CTLW0 &= ~UC7BIT; // Set 8 bit data transfer
UCA0CTLW0 &= ~UCSPB; // Use 1 stop bit
UCA0CTLW0 &= ~(UCMODE1 | UCMODE0); // set eUSCI_A to UART mode
UCA0CTLW0 &= ~UCSYNC; // Set UART to asynchronous mode
UCA0CTLW0 &= ~UCSSEL1; // Select the ACLK as the clock source
UCA0CTLW0 |= UCSSEL0;
UCA0CTLW0 &= ~UCRXEIE; // Disable erroneous characters.
UCA0CTLW0 &= ~UCBRKIE; // Disable break character interrupts
UCA0CTLW0 &= ~UCDORM; // Allow all recieved characters to set UCRXIFG
UCA0CTLW0 &= ~UCTXADDR; // Indicate the next frame to be data (not address)
UCA0CTLW0 &= ~UCTXBRK; // Indicate the next frame transmitted is not a break
UCA0BRW = 0x0006; // Clock prescalar setting of baudrate generator
UCA0MCTLW = 0x0080; // First modulation select. Ignored if oversampling off
UCA0MCTLW |= 0x2000; // Second modulation select. Mod pattern for BITCLK
UCA0MCTLW |= UCOS16; // Enable oversampling
UCA0CTLW0 &= ~UCSWRST; // Release for operation
PJOUT |= BIT3;
do g_counter++;
while(g_counter != 25001);
/* 6. Enable Rx and global interrupts. */
PJOUT &= ~(BIT3 | BIT2 | BIT1 | BIT0);
UCA0IE |= UCRXIE;
__bis_SR_register(GIE);
for(;;) {
/* 7. Enter LPM0 when not in ISR. LPM0 consists of
* CPU/MCLK disabled, ACLK active, SMCLK (optionally active),
* and DCO is enabled if sources either ACLK or SMCLK. */
__bis_SR_register(LPM0_bits);
}
return 0;
}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
#else
#error Sorry Brojangles, but your compiler isnt supported. Watcha know about mspgcc?
#endif
{
switch(__even_in_range(UCA0IV,0x08))
{
/* Vector 0: No interrupts */
case 0: break;
/* Vector 2: UCRXIFG - Receive buf is full */
case 2:
/* 1. Grab the data from Rx buffer. */
g_data = UCA0RXBUF;
/* 2. Four states corresponding to the received value. */
if(g_data == 0x55) {
PJOUT ^= BIT0;
} else if(g_data == 0x66) {
PJOUT ^= BIT1;
} else if(g_data == 0x77) {
PJOUT ^= BIT2;
} else {
PJOUT ^= BIT3;
}
/* 3. Clear the receive flag and exit. */
UCA0IFG &= ~UCRXIFG;
__bic_SR_register_on_exit(LPM0_bits);
break;
/* Vector 4: UCTXIFG - Transmit buf is empty*/
case 4: break;
/* Vector 6: USTTIFG - Start bit received */
case 6: break;
/* Vector 8: UCTXCPTIFG - Transmit complete */
case 8: break;
default:break;
}
}
tx.c
#include <msp430fr5739.h>
#include <stdint.h>
volatile uint16_t g_counter = 25000;
volatile uint8_t g_state = 0;
int main(void) {
/* 1. Disable the Watchdog timer. */
WDTCTL = WDTPW + WDTHOLD;
/* 2. Enable LED1-4 for output. */
PJDIR |= BIT3 + BIT2 + BIT1 + BIT0;
PJOUT &= ~(BIT3 + BIT2 + BIT1 + BIT0);
PJOUT |= BIT0;
do g_counter--;
while(g_counter != 0);
/* 3. Configure clock settings. */
CSCTL0_H = 0xA5; // Write CSKEY password to configure clock settings
CSCTL1 &= ~DCORSEL; // Set DCO to 8MHz
CSCTL1 |= DCOFSEL1 | DCOFSEL0;
__delay_cycles(4); // Allow the DCO to settle at 8MHz
CSCTL2 &= ~SELA2; // Set ACLK to DCO
CSCTL2 |= SELA1 | SELA0;
CSCTL2 &= ~SELS2; // Set SMCLK to DCO
CSCTL2 |= SELS1 | SELS0;
CSCTL2 &= ~SELM2; // Set MCLK to DCO
CSCTL2 |= SELM1 | SELM0;
CSCTL3 &= ~DIVA2; // Divide ACLK by 8
CSCTL3 |= DIVA1 | DIVA0;
PJOUT |= BIT1;
do g_counter++;
while(g_counter != 25001);
/* 4. Configure pins 2.0 (TX) and 2.1 (RX) for UART. */
P2SEL0 &= ~(BIT1 | BIT0);
P2SEL1 |= BIT1 | BIT0;
PJOUT |= BIT2;
do g_counter--;
while(g_counter != 0);
/* 5. Configure UART settings. */
UCA0CTLW0 |= UCSWRST; // Allow UART settings to be edited
UCA0CTLW0 &= ~UCPEN; // Disable parity bits
UCA0CTLW0 &= ~UCMSB; // Set data transfer to LSB first
UCA0CTLW0 &= ~UC7BIT; // Set 8 bit data transfer
UCA0CTLW0 &= ~UCSPB; // Use 1 stop bit
UCA0CTLW0 &= ~(UCMODE1 | UCMODE0); // set eUSCI_A to UART mode
UCA0CTLW0 &= ~UCSYNC; // Set UART to asynchronous mode
UCA0CTLW0 &= ~UCSSEL1; // Select the ACLK as the clock source
UCA0CTLW0 |= UCSSEL0;
UCA0CTLW0 &= ~UCRXEIE; // Disable erroneous characters.
UCA0CTLW0 &= ~UCBRKIE; // Disable break character interrupts
UCA0CTLW0 &= ~UCDORM; // Allow all recieved characters to set UCRXIFG
UCA0CTLW0 &= ~UCTXADDR; // Indicate the next frame to be data (not address)
UCA0CTLW0 &= ~UCTXBRK; // Indicate the next frame transmitted is not a break
UCA0BRW = 0x0006; // Clock prescalar setting of baudrate generator
UCA0MCTLW = 0x0080; // First modulation select. Ignored if oversampling off
UCA0MCTLW |= 0x2000; // Second modulation slelect. Mod pattern for BITCLK
UCA0MCTLW |= UCOS16; // Enable oversampling
UCA0CTLW0 &= ~UCSWRST; // Release for operation
PJOUT |= BIT3;
do g_counter++;
while(g_counter != 25001);
/* 6. Enable Tx and global interrupts. */
PJOUT &= ~(BIT3 | BIT2 | BIT1 | BIT0);
UCA0IE |= UCTXIE;
__bis_SR_register(GIE);
for(;;) {
/* 7. Enter LPM0 when not in ISR. LPM0 consists of
* CPU/MCLK disabled, ACLK active, SMCLK (optionally active),
* and DCO is enabled if sources either ACLK or SMCLK. */
__bis_SR_register(LPM0_bits);
}
return 0;
}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
#else
#error Sorry Brojangles, but your compiler isnt supported. Whatcha know about mspgcc?
#endif
{
switch(__even_in_range(UCA0IV,0x08))
{
/* Vector 0: No interrupts */
case 0: break;
/* Vecotr 2: UCRXIFG - Receive buf is full */
case 2: break;
/* Vector 4: UCTXIFG - Transmit buf is empty */
case 4:
/* 1. Wait for a sec then flash LED. */
g_counter = 25000;
do g_counter--;
while(g_counter != 0);
PJOUT ^= BIT0;
/* 2. Four states corresponding to different transmit vals. */
if(g_state == 0) {
UCA0TXBUF = 0x55;
g_state = 1;
} else if(g_state == 1) {
UCA0TXBUF = 0x66;
g_state = 2;
} else if(g_state == 2) {
UCA0TXBUF = 0x77;
g_state = 3;
} else {
UCA0TXBUF = 0x88;
g_state = 0;
}
/* 3. Clear the transmit flag and then exit. */
UCA0IFG &= ~UCTXIFG;
__bic_SR_register_on_exit(LPM0_bits);
break;
/* Vector 6: USTTIFG - Start bit received */
case 6: break;
/* Vector 8: UCTXCPTIFG - Transmit complete */
case 8: break;
default:break;
}
}