//***************************************************************************************
// uart test - TX
// Use 32.768 KHz crystal for SIMCLK but use DCO for MCLK
//
// MSP430G2553
// Jed Margolin 3/14/2016.
// Built with Code Composer Studio v6
//***************************************************************************************
// main.c
#include <msp430.h>
//#include <msp430G2553.h>
#define DELTA_1MHZ 244 // 244 x 4096Hz = 999.4Hz
#define DELTA_8MHZ 1953 // 1953 x 4096Hz = 7.99MHz
#define DELTA_12MHZ 2930 // 2930 x 4096Hz = 12.00MHz
#define DELTA_16MHZ 3906 // 3906 x 4096Hz = 15.99MHz
#define TIME 100
#define DCOUNT 8
void wait(unsigned int);
void wait2(void);
void Set_DCO(unsigned int Delta);
void uart_init(void);
void uartsetup_4800(void);
void uart_send_byte(unsigned char byte);
//================================================
int main(void)
{
unsigned char caldata1, caldata2; // Temp. storage for constants
volatile unsigned char k = 0;
volatile unsigned char m = 0;
volatile unsigned char n = 0;
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
wait(150); // give the crystal 500ms to stabilize
P1SEL |= BIT0; // ACLK
P1SEL2 &= ~(BIT0); // not used by msp430g2211
P1DIR |= BIT0;
P1SEL |= BIT1; // RX In
P1SEL2 |= BIT1;
P1REN |= BIT1; // pullup/pulldown enabled
P1OUT |= BIT1;
P1DIR &= ~(BIT1); // In
P1SEL |= BIT2; // TX Out
P1SEL2 |= BIT2;
P1DIR |= BIT2;
P1SEL &= ~(BIT3); // Out - for testing
P1SEL2 &= ~(BIT3); // not used by msp430g2211
P1DIR |= BIT3; //
P1SEL |= BIT4; // Out for SMCLK so we know it's working
P1SEL2 &= ~(BIT4); // not used by msp430g2211
P1DIR |= BIT4; //
P1SEL &= ~(BIT5); // In
P1SEL2 &= ~(BIT5); // not used by msp430g2211
P1REN |= BIT5; // pullup/pulldown enabled
P1OUT |= BIT5; // pullup
P1DIR &= ~(BIT5); //
P1SEL &= ~(BIT6); // Out
P1SEL2 &= ~(BIT6); // not used by msp430g2211
P1DIR |= BIT6; // pullup
P1DIR &= ~(BIT7); // In - 60Hz phase
P1OUT |= BIT7; // pullup
P1SEL &= ~(BIT7); //
P1SEL2 &= ~(BIT7); // not used by msp430g2211
P1REN |= BIT7; // pullup/pulldown enabled
// Enable the crystal
// BCSCTL1 comes out of reset with:
// XT2OFF = 1 (MSP430G2553 and MSP430G2211 don't have XT2)
// XTS = 0 (LFXT1 = Low Frequency mode)
// DIVAx = 0 (ACLK Divider = 1)
// RSELx = 7 (Range Select - should be for DCO only)
BCSCTL3 |= LFXT1S_0 + XCAP_3;
// LFXT1S = 0 (32768 crystal on LFXT1)
// XCAP = 3 (12.5pF)
while(IFG1 & OFIFG) // OFIFG is Bit1 in IFG1 (Interrupt Flag Register)
// and means oscillator fault
{
IFG1 &= ~OFIFG; // keep resetting it until it doesn't need to be reset
wait2();
}
// We are going to leave SCG1 and SCG0 off
// _bis_SR_register(SCG1 + SCG0); // Set bits SCG1 and SCG0
// SCG1 (System Clock Generator 1) When set turns off the SMCLK
// SCG0 (System Clock Generator 0) When set turns off the DCO dc generator if DCOCLK is not used for MCLK or SMCLK
// We will leave DCO dc generator on just in case
// end of setup for crystal
//-----------------------
// Lock the DCO to the 32.768 KHz crystal - 8 MHz
P1OUT |= BIT6;
Set_DCO(DELTA_8MHZ); // Set DCO and obtain constants
caldata1 = DCOCTL; // for debugging
caldata2 = BCSCTL1;
P1OUT &= ~(BIT6);
// BCSCTL2 = 0x00; // SMCLK = DCO
BCSCTL2 = 0x08; // SMCLK = ACLK
// SELMx(7,6) = 0 0 MCLK is DCO
// DIVMx(5,4) = 0 0 MCLK divider is /1
// SELS(3) = 1 SMCLK is LFXT1CLK or VLOCLK
// DIVSx(2,1) = 0 0 SMCLK is /1, will be 32.768 KHz
// DCOR(0) = 0 not present
//-----------------------
// Initialize the uart
// At 4800 baud, the bit time is 208.3 us, the actual bit time is modulated to make it average out
uartsetup_4800();
uart_init(); // no interrupts for either RX or TX
//-----------------------
m = 32; // updata uart data every m times
while (1) // main loop
{
P1OUT |= BIT6; // trigger for 'scope
wait2();
P1OUT &= ~(BIT6);
uart_send_byte(n);
for(k=10; k>0; k--) // toggle at full speed to show that DCO is working
{
P1OUT |= BIT6;
P1OUT &= ~(BIT6);
}
if(m-- == 0)
{
n++;
m=32;
}
wait(3);
} // end main loop
} // end main
//==================================
void wait(unsigned int time)
{
volatile unsigned int i,j;
for(i=time; i>0; i--)
{
for(j=1590; j>0; j--);
{
}
}
return;
} // end main
//==========================================================
void wait2()
{
volatile unsigned int i;
for(i=0; i<48; i++){}
return;
}
//========================================================
//========================================================
void Set_DCO(unsigned int Delta) // Set DCO to selected frequency
{
unsigned int Compare, Oldcapture = 0;
BCSCTL1 |= DIVA_3; // ACLK = LFXT1CLK/8
TACCTL0 = CM_1 + CCIS_1 + CAP; // CAP, ACLK
TACTL = TASSEL_2 + MC_2 + TACLR; // SMCLK, cont-mode, clear
while (1)
{
while (!(CCIFG & TACCTL0)); // Wait until capture occured
TACCTL0 &= ~CCIFG; // Capture occured, clear flag
Compare = TACCR0; // Get current captured SMCLK
Compare = Compare - Oldcapture; // SMCLK difference
Oldcapture = TACCR0; // Save current captured SMCLK
if (Delta == Compare)
break; // If equal, leave "while(1)"
else if (Delta < Compare)
{
DCOCTL--; // DCO is too fast, slow it down
if (DCOCTL == 0xFF) // Did DCO roll under?
if (BCSCTL1 & 0x0f)
BCSCTL1--; // Select lower RSEL
}
else
{
DCOCTL++; // DCO is too slow, speed it up
if (DCOCTL == 0x00) // Did DCO roll over?
if ((BCSCTL1 & 0x0f) != 0x0f)
BCSCTL1++; // Sel higher RSEL
}
}
TACCTL0 = 0; // Stop TACCR0
TACTL = 0; // Stop Timer_A
BCSCTL1 &= ~DIVA_3; // ACLK is divide by 1
}
//=================================================================
void uart_init(void)
{
IE2 &= ~UCA0RXIE; // default: Disable USCI_A0 RX interrupt
IE2 &= ~UCA0TXIE; // default: Disable USCI_A0 TX interrupt
}
//=================================================================
// Low-Frequency Baud Rate Mode
// Read chapter 15.3.10 of msp430x2xxx user's guide for baud rate generation
void uartsetup_4800(void)
{
P3SEL = 0x30; // P3.4,5 = USCI_A0 TXD/RXD, No need to set direction
UCA0CTL1 |= UCSSEL_1; // CLK = ACLK
UCA0BR0 = 0x06; // 6 = INT(6.83), 32.768KHz/4800 = 6.8
UCA0BR1 = 0x00; //
UCA0MCTL = UCBRS2 + UCBRS1 + UCBRS0; // Modulation UCBRSx = 7 = round(0.83 * 8)
UCA0CTL1 &= (~UCSWRST); // ** Initialize USCI state machine
UCA0CTL0 |= 0x80; // odd parity
}
//=================================================================
// Sends a single byte out through UART
void uart_send_byte(unsigned char byte)
{
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = byte; // TX -> RXed character
}
//=================================================================
// USCI A0/B0 Transmit ISR
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void)
{
IE2 &= ~UCA0TXIE; // Disable USCI_A0 TX interrupt
}
//=================================================================