//****************************************************************************** // MSP430G2xx2 Demo - Timer_A, Ultra-Low Pwr UART 9600 Echo, 32kHz ACLK // // Description: Use Timer_A CCR0 hardware output modes and SCCI data latch // to implement UART function @ 9600 baud Software does not directly read and // write to RX and TX pins, instead proper use of output modes and SCCI data // latch are demonstrated Use of these hardware features eliminates ISR // latency effects as hardware insures that output and input bit latching and // timing are perfectly synchronised with Timer_A regardless of other // software activity In the Mainloop the UART function readies the UART to // receive one character and waits in LPM3 with all activity interrupt driven // After a character has been received, the UART receive function forces exit // from LPM3 in the Mainloop which configures the port pins (P1 & P2) based // on the value of the received byte (i.e., if BIT0 is set, turn on P1.0) // ACLK = TACLK = LFXT1 = 32768Hz, MCLK = SMCLK = default DCO // //* An external watch crystal is required on XIN XOUT for ACLK *// // // MSP430G2xx2 // // /|\| XIN|// | | | 32kHz // |RST XOUT|// | | // | CCI0B/TXD/P1.1| > // | | 9600 8N1 // | CCI0A/RXD/P1.2|< -// // D Dang // Texas Instruments Inc // December 2010 // Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10 //****************************************************************************** #include "msp430g2452.h" // -// Hardware-related definitions // -#define UART_TXD 0x02 // TXD on P1.1 (Timer0_A.OUT0) #define UART_RXD 0x04 // RXD on P1.2 (Timer0_A.CCI1A) // -// Conditions for 9600 Baud SW UART, SMCLK = 1MHz // -#define UART_TBIT_DIV_2 (1000000 / (9600 * 2)) #define UART_TBIT (1000000 / 9600) // -// Global variables used for full-duplex UART communication // -unsigned int txData; // UART internal variable for TX unsigned char rxBuffer; // Received UART character // -// Function prototypes // -void TimerA_UART_init(void); void TimerA_UART_tx(unsigned char byte); void TimerA_UART_print(char *string); // // main() // -void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer DCOCTL = 0x00; BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; // Set DCOCLK to 1MHz P1OUT P1SEL P1DIR P2OUT P2SEL P2DIR // Initialize all GPIO // Timer function for TXD/RXD pins // Set all pins but RXD to output = = = = = = 0x00; UART_TXD + UART_RXD; 0xFF & ~UART_RXD; 0x00; 0x00; 0xFF; enable_interrupt(); TimerA_UART_init(); // Start Timer_A UART TimerA_UART_print("G2xx2 TimerA UART\r\n"); TimerA_UART_print("READY.\r\n"); for (;;) { // Wait for incoming character bis_SR_register(LPM0_bits); // if if if if if if if if Update board outputs according to received byte (rxBuffer & 0x01) P1OUT |= 0x01; else P1OUT &= ~0x01; (rxBuffer & 0x02) P1OUT |= 0x08; else P1OUT &= ~0x08; (rxBuffer & 0x04) P1OUT |= 0x10; else P1OUT &= ~0x10; (rxBuffer & 0x08) P1OUT |= 0x20; else P1OUT &= ~0x20; (rxBuffer & 0x10) P1OUT |= 0x40; else P1OUT &= ~0x40; (rxBuffer & 0x20) P1OUT |= 0x80; else P1OUT &= ~0x80; (rxBuffer & 0x40) P2OUT |= 0x40; else P2OUT &= ~0x40; (rxBuffer & 0x80) P2OUT |= 0x80; else P2OUT &= ~0x80; // Echo received character TimerA_UART_tx(rxBuffer); // // // // // // // // P1.0 P1.3 P1.4 P1.5 P1.6 P1.7 P2.6 P2.7 } } // -// Function configures Timer_A for full-duplex UART operation // -void TimerA_UART_init(void) { TACCTL0 = OUT; // Set TXD Idle as Mark = '1' TACCTL1 = SCS + CM1 + CAP + CCIE; // Sync, Neg Edge, Capture, Int TACTL = TASSEL_2 + MC_2; // SMCLK, start in continuous mode } // -// Outputs one byte using the Timer_A UART // -void TimerA_UART_tx(unsigned char byte) { while (TACCTL0 & CCIE); // Ensure last char got TX'd TACCR0 = TAR; // Current state of TA counter TACCR0 += UART_TBIT; // One bit time till first bit TACCTL0 = OUTMOD0 + CCIE; // Set TXD on EQU0, Int txData = byte; // Load global variable txData |= 0x100; // Add mark stop bit to TXData txData = 1; txBitCnt ; } // // // // Add Offset to CCRx All bits TXed? All bits TXed, disable interrupt Re-load bit counter // TX Mark '1' // TX Space '0' } // -// Timer_A UART - Receive Interrupt Handler // -#pragma vector = TIMER0_A1_VECTOR interrupt void Timer_A1_ISR(void) { static unsigned char rxBitCnt = 8; static unsigned char rxData = 0; switch ( even_in_range(TA0IV, TA0IV_TAIFG)) { // Use calculated branching case TA0IV_TACCR1: // TACCR1 CCIFG - UART RX TACCR1 += UART_TBIT; // Add Offset to CCRx if (TACCTL1 & CAP) { // Capture mode = start bit edge mode latch TACCTL1 &= ~CAP; TACCR1 += UART_TBIT_DIV_2; } else { rxData >>= 1; if (TACCTL1 & SCCI) { rxData |= 0x80; } rxBitCnt ; if (rxBitCnt == 0) { // Switch capture to compare // Point CCRx to middle of D0 // Get bit waiting in receive // All bits RXed? rxBuffer = rxData; rxBitCnt = 8; TACCTL1 |= CAP; mode from 0(SR) // Store in global variable // Re-load bit counter // Switch compare to capture bic_SR_register_on_exit(LPM0_bits); // Clear LPM0 bits } } break; } } //