"msp430x20x2.h": // TXD On P1.1 // RXD On P1.2
"msp430x20x2.h": // TXD On P1.1 // RXD On P1.2
"msp430x20x2.h": // TXD On P1.1 // RXD On P1.2
Device starts up in LPM3 + blinking LED to indicate device is alive * + Upon first button press, device transitions to application mode * 2. Application Mode * + Continuously sample ADC Temp Sensor channel, compare result against * initial value * + Set PWM based on measured ADC offset: Red LED for positive offset, Green * LED for negative offset * + Transmit temperature value via TimerA UART to PC * + Button Press --> Calibrate using current temperature * Send character '' via UART, notifying PC ******************************************************************************/ #include #define #define #define #define "msp430x20x2.h" LED0 LED1 LED_DIR LED_OUT BIT0 BIT6 P1DIR P1OUT
#define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define
BUTTON BUTTON_OUT BUTTON_DIR BUTTON_IN BUTTON_IE BUTTON_IES BUTTON_IFG BUTTON_REN TXD RXD APP_STANDBY_MODE APP_APPLICATION_MODE TIMER_PWM_MODE TIMER_UART_MODE TIMER_PWM_PERIOD TIMER_PWM_OFFSET TEMP_SAME TEMP_HOT TEMP_COLD TEMP_THRESHOLD
BIT3 P1OUT P1DIR P1IN P1IE P1IES P1IFG P1REN BIT1 BIT2 0 1 0 1 2000 20 0 1 2 5 // TXD on P1.1 // RXD on P1.2
// Conditions for 9600/4=2400 Baud SW UART, SMCLK = 1MHz #define Bitime_5 0x05*4 adjustment #define Bitime 13*4//0x0D #define UART_UPDATE_INTERVAL 1000
unsigned char timerMode = TIMER_PWM_MODE; unsigned unsigned unsigned unsigned char tempMode; char calibrateUpdate = 0; char tempPolarity = TEMP_SAME; int TXByte;
/* Using an 8-value moving average filter on sampled ADC values */ long tempMeasured[8]; unsigned char tempMeasuredPosition=0; long tempAverage; long tempCalibrated, tempDifference;
void main(void) { unsigned int uartUpdateTimer = UART_UPDATE_INTERVAL; unsigned char i; WDTCTL = WDTPW + WDTHOLD; // Stop WDT InitializeClocks(); InitializeButton(); InitializeLeds(); PreApplicationMode(); /* Application Mode begins */ applicationMode = APP_APPLICATION_MODE; ConfigureAdcTempSensor(); ConfigureTimerPwm(); __enable_interrupt(); // Enable interrupts.
/* Moving average filter out of 8 values to somewhat stabilize sampled ADC */ tempMeasured[tempMeasuredPosition++] = ADC10MEM; if (tempMeasuredPosition == 8) tempMeasuredPosition = 0; tempAverage = 0; for (i = 0; i < 8; i++) tempAverage += tempMeasured[i]; tempAverage >>= 3; // Divide by 8 to get average if ((--uartUpdateTimer == 0) || calibrateUpdate ) {
ConfigureTimerUart(); if (calibrateUpdate) { TXByte = 248; // A character with high value, outside of temp range Transmit(); calibrateUpdate = 0; } TXByte = (unsigned char)( ((tempAverage - 630) * 761) / 1024 ); Transmit(); uartUpdateTimer = UART_UPDATE_INTERVAL; ConfigureTimerPwm(); }
tempDifference = tempAverage - tempCalibrated; if (tempDifference < -TEMP_THRESHOLD) { tempDifference = -tempDifference; tempPolarity = TEMP_COLD; LED_OUT &= ~ LED1; } else if (tempDifference > TEMP_THRESHOLD) { tempPolarity = TEMP_HOT; LED_OUT &= ~ LED0; } else { tempPolarity = TEMP_SAME; TACCTL0 &= ~CCIE; TACCTL1 &= ~CCIE; LED_OUT &= ~(LED0 + LED1); } if (tempPolarity != TEMP_SAME) { tempDifference <<= 3; tempDifference += TIMER_PWM_OFFSET; TACCR1 = ( (tempDifference) < (TIMER_PWM_PERIOD-1) ? (tempDifference) : (TIMER_PWM_PERIOD-1) ); TACCTL0 |= CCIE; TACCTL1 |= CCIE; } } } void PreApplicationMode(void) { LED_DIR |= LED0 + LED1; LED_OUT |= LED0; LED_OUT &= ~LED1; BCSCTL1 |= DIVA_1; BCSCTL3 |= LFXT1S_2; TACCR0 = 1200; TACTL = TASSEL_1 | MC_1; TACCTL1 = CCIE + OUTMOD_3; TACCR1 = 600; __bis_SR_register(LPM3_bits + GIE);
// ACLK/2 // ACLK = VLO // // TACLK = SMCLK, Up mode. // TACCTL1 Capture Compare // LPM0 with interrupts enabled
} void ConfigureAdcTempSensor(void) { unsigned char i; /* Configure ADC Temp Sensor Channel */ ADC10CTL1 = INCH_10 + ADC10DIV_3; // Temp Sensor ADC10CLK/4 ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ADC10IE; __delay_cycles(1000); // Wait for ADC Ref to settle ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start __bis_SR_register(CPUOFF + GIE); // LPM0 with interrupts enabled tempCalibrated = ADC10MEM; for (i=0; i < 8; i++) tempMeasured[i] = tempCalibrated; tempAverage = tempCalibrated; }
void ConfigureTimerPwm(void) { timerMode = TIMER_PWM_MODE; TACCR0 = TIMER_PWM_PERIOD; TACTL = TASSEL_2 | MC_1; TACCTL0 = CCIE; TACCTL1 = CCIE + OUTMOD_3; TACCR1 = 1; } void ConfigureTimerUart(void) { timerMode = TIMER_UART_MODE; CCTL0 TACTL P1SEL P1DIR } // Function Transmits Character from TXByte void Transmit() { BitCnt = 0xA; // Load Bit counter, 8data + ST/SP while (CCR0 != TAR) // Prevent async capture CCR0 = TAR; // Current state of TA counter CCR0 += Bitime; // Some time till first bit TXByte |= 0x100; // Add mark stop bit to TXByte TXByte = TXByte << 1; // Add space start bit CCTL0 = CCIS0 + OUTMOD0 + CCIE; // TXD = mark = idle while ( CCTL0 & CCIE ); // Wait for TX completion } = OUT; = TASSEL_2 + MC_2 + ID_3; |= TXD + RXD; |= TXD; // // TACLK = SMCLK, Up mode. // TACCTL1 Capture Compare
// Timer A0 interrupt service routine #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A (void) { if (timerMode == TIMER_UART_MODE) { CCR0 += Bitime; if (CCTL0 & CCIS0)
{ if ( BitCnt == 0) CCTL0 &= ~ CCIE; else { CCTL0 |= OUTMOD2; if (TXByte & 0x01) CCTL0 &= ~ OUTMOD2; TXByte = TXByte >> 1; BitCnt --; } } } else { if (tempPolarity == TEMP_HOT) LED_OUT |= LED1; if (tempPolarity == TEMP_COLD) LED_OUT |= LED0; TACCTL0 &= ~CCIFG; } } #pragma vector=TIMERA1_VECTOR __interrupt void ta1_isr(void) { TACCTL1 &= ~CCIFG; if (applicationMode == APP_APPLICATION_MODE) LED_OUT &= ~(LED0 + LED1); else LED_OUT ^= (LED0 + LED1); } void InitializeClocks(void) { BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; BCSCTL2 &= ~(DIVS_3); } void InitializeButton(void) { BUTTON_DIR &= ~BUTTON; BUTTON_OUT |= BUTTON; BUTTON_REN |= BUTTON; BUTTON_IES |= BUTTON; BUTTON_IFG &= ~BUTTON; BUTTON_IE |= BUTTON; } // Configure Push Button // Set range // SMCLK = DCO / 8 = 1MHz // All bits TXed, disable interrupt
// TX Space // TX Mark
void InitializeLeds(void) { LED_DIR |= LED0 + LED1; LED_OUT &= ~(LED0 + LED1); } /* ************************************************************* * Port Interrupt for Button Press * 1. During standby mode: to exit and enter application mode
* 2. During application mode: to recalibrate temp sensor * *********************************************************** */ #pragma vector=PORT1_VECTOR __interrupt void PORT1_ISR(void) { BUTTON_IFG = 0; BUTTON_IE &= ~BUTTON; /* Debounce */ WDTCTL = WDT_ADLY_250; IFG1 &= ~WDTIFG; /* clear interrupt flag */ IE1 |= WDTIE; if (applicationMode == APP_APPLICATION_MODE) { tempCalibrated = tempAverage; calibrateUpdate = 1; } else { applicationMode = APP_APPLICATION_MODE; // Switch from STANDBY to APPLICATION MODE __bic_SR_register_on_exit(LPM3_bits); } } #pragma vector=WDT_VECTOR __interrupt void WDT_ISR(void) { IE1 &= ~WDTIE; IFG1 &= ~WDTIFG; WDTCTL = WDTPW + WDTHOLD; BUTTON_IE |= BUTTON; } // ADC10 interrupt service routine #pragma vector=ADC10_VECTOR __interrupt void ADC10_ISR (void) { __bic_SR_register_on_exit(CPUOFF); }
/* /* /* /*
disable interrupt */ clear interrupt flag */ put WDT back in hold state */ Debouncing complete */