275 lines
9.6 KiB
C
275 lines
9.6 KiB
C
/*
|
|
* main.c
|
|
*
|
|
* MSP-EXP430G2-LaunchPad User Experience Application
|
|
*
|
|
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
|
|
*
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the
|
|
* distribution.
|
|
*
|
|
* Neither the name of Texas Instruments Incorporated nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
|
|
* Heavily modified: Nov, 2013 Carl Michal
|
|
* Even more so, February, 2014
|
|
|
|
* This version modified to use the Hardware UART on MSP430G2553
|
|
* see code at https://bennthomsen.wordpress.com/engineering-toolbox/ti-msp430-launchpad/msp430g2553-hardware-uart/
|
|
* jumpers for TX/RX on Launchpad board must be rotated 90 degrees
|
|
* for hardware UART used here!!
|
|
* This may not work on all revisions of the board?
|
|
|
|
|
|
*/
|
|
|
|
|
|
/******************************************************************************
|
|
* MSP-EXP430G2-LaunchPad User Experience Application
|
|
*
|
|
* 1. 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
|
|
*
|
|
* + Transmit temperature value via TimerA UART to PC
|
|
*
|
|
*
|
|
* Texas Instruments, Inc.
|
|
******************************************************************************/
|
|
|
|
#include "msp430.h"
|
|
|
|
#define LED1 BIT0
|
|
#define LED2 BIT6
|
|
|
|
#define BUTTON BIT3
|
|
|
|
#define TXD BIT2 // TXD on P1.2
|
|
#define RXD BIT1 // RXD on P1.1
|
|
|
|
#define PreAppMode 0
|
|
#define RunningMode 1
|
|
|
|
unsigned int TXByte;
|
|
volatile unsigned int Mode;
|
|
|
|
void InitializeButton(void);
|
|
void PreApplicationMode(void);
|
|
|
|
void main(void)
|
|
{
|
|
long tempMeasured;
|
|
|
|
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
|
|
|
|
/* next three lines to use internal calibrated 1MHz clock: */
|
|
BCSCTL1 = CALBC1_1MHZ; // Set range
|
|
DCOCTL = CALDCO_1MHZ;
|
|
BCSCTL2 &= ~(DIVS_3); // SMCLK = DCO = 1MHz
|
|
|
|
InitializeButton();
|
|
|
|
// setup port for leds:
|
|
P1DIR |= LED1 + LED2;
|
|
P1OUT &= ~(LED1 + LED2);
|
|
|
|
P1DIR |= TXD;
|
|
P1OUT |= TXD;
|
|
|
|
Mode = PreAppMode;
|
|
PreApplicationMode(); // Blinks LEDs, waits for button press
|
|
|
|
/* 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
|
|
|
|
__enable_interrupt(); // Enable interrupts.
|
|
|
|
/* Configure hardware UART */
|
|
P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
|
|
P1SEL2 = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
|
|
UCA0CTL1 |= UCSSEL_2; // Use SMCLK
|
|
UCA0BR0 = 104; // Set baud rate to 9600 with 1MHz clock (Data Sheet 15.3.13)
|
|
UCA0BR1 = 0; // Set baud rate to 9600 with 1MHz clock
|
|
UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1
|
|
UCA0CTL1 &= ~UCSWRST; // Initialize USCI state machine
|
|
/* if we were going to receive, we would also:
|
|
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
|
|
*/
|
|
|
|
/* Main Application Loop */
|
|
while(1)
|
|
{
|
|
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
|
|
__bis_SR_register(CPUOFF + GIE); // LPM0 with interrupts enabled turns cpu off.
|
|
// an interrupt is triggered when the ADC result is ready.
|
|
// The interrupt handler restarts the cpu.
|
|
|
|
// store result
|
|
tempMeasured = ADC10MEM;
|
|
|
|
|
|
// convert to farenheit and send to host computer
|
|
TXByte = (unsigned char)( ((tempMeasured - 630) * 761) / 1024 );
|
|
while (! (IFG2 & UCA0TXIFG)); // wait for TX buffer to be ready for new data
|
|
UCA0TXBUF = TXByte;
|
|
|
|
P1OUT ^= LED1; // toggle the light every time we make a measurement.
|
|
|
|
// set up timer to wake us in a while:
|
|
TACCR0 = 2400; // period
|
|
TACTL = TASSEL_1 | MC_1; // TACLK = ACLK, Up mode.
|
|
TACCR1 = 2400; // interrupt at end
|
|
TACCTL1 = CCIE; // TACCTL0
|
|
|
|
// go to sleep, wait till timer expires to do another measurement.
|
|
__bis_SR_register(LPM3_bits + GIE); // LPM0 with interrupts enabled turns cpu off.
|
|
|
|
// could have just done this - but low power mode is nicer.
|
|
// __delay_cycles(500000);
|
|
|
|
}
|
|
}
|
|
|
|
void PreApplicationMode(void)
|
|
{
|
|
P1DIR |= LED1 + LED2;
|
|
P1OUT |= LED1; // To enable the LED toggling effect
|
|
P1OUT &= ~LED2;
|
|
|
|
/* these next two lines configure the ACLK signal to come from
|
|
a secondary oscillator source, called VLO */
|
|
|
|
BCSCTL1 |= DIVA_1; // ACLK is half the speed of the source (VLO)
|
|
BCSCTL3 |= LFXT1S_2; // ACLK = VLO
|
|
|
|
/* here we're setting up a timer to fire an interrupt periodically.
|
|
When the timer 1 hits its limit, the interrupt will toggle the lights
|
|
|
|
We're using ACLK as the timer source, since it lets us go into LPM3
|
|
(where SMCLK and MCLK are turned off). */
|
|
|
|
TACCR0 = 1200; // period
|
|
TACTL = TASSEL_1 | MC_1; // TACLK = ACLK, Up mode.
|
|
TACCTL1 = CCIE + OUTMOD_3; // TACCTL1 Capture Compare
|
|
TACCR1 = 600; // duty cycle
|
|
__bis_SR_register(LPM3_bits + GIE); // LPM3 with interrupts enabled
|
|
// in LPM3, MCLCK and SMCLK are off, but ACLK is on.
|
|
}
|
|
|
|
// this gets used in pre-application mode only to toggle the lights:
|
|
#if defined(__TI_COMPILER_VERSION__)
|
|
#pragma vector=TIMER0_A1_VECTOR
|
|
__interrupt void ta1_isr (void)
|
|
#else
|
|
void __attribute__ ((interrupt(TIMER0_A1_VECTOR))) ta1_isr (void)
|
|
#endif
|
|
{
|
|
TACCTL1 &= ~CCIFG; // reset the interrupt flag
|
|
if (Mode == PreAppMode){
|
|
P1OUT ^= (LED1 + LED2); // toggle the two lights.
|
|
}
|
|
else{
|
|
TACCTL1 = 0; // no more interrupts.
|
|
__bic_SR_register_on_exit(LPM3_bits); // Restart the cpu
|
|
}
|
|
|
|
}
|
|
|
|
void InitializeButton(void) // Configure Push Button
|
|
{
|
|
P1DIR &= ~BUTTON;
|
|
P1OUT |= BUTTON;
|
|
P1REN |= BUTTON;
|
|
P1IES |= BUTTON;
|
|
P1IFG &= ~BUTTON;
|
|
P1IE |= BUTTON;
|
|
}
|
|
|
|
/* *************************************************************
|
|
* Port Interrupt for Button Press
|
|
* 1. During standby mode: to enter application mode
|
|
*
|
|
* *********************************************************** */
|
|
|
|
#if defined(__TI_COMPILER_VERSION__)
|
|
#pragma vector=PORT1_VECTOR
|
|
__interrupt void port1_isr(void)
|
|
#else
|
|
void __attribute__ ((interrupt(PORT1_VECTOR))) port1_isr (void)
|
|
#endif
|
|
{
|
|
|
|
/* this disables port1 interrupts for a little while so that
|
|
we don't try to respond to two consecutive button pushes right together.
|
|
The watchdog timer interrupt will re-enable port1 interrupts
|
|
|
|
This whole watchdog thing is completely unnecessary here, but its useful
|
|
to see how it is done.
|
|
*/
|
|
P1IFG = 0; // clear out interrupt flag
|
|
P1IE &= ~BUTTON; // Disable port 1 interrupts
|
|
WDTCTL = WDT_ADLY_250; // set up watchdog timer duration
|
|
IFG1 &= ~WDTIFG; // clear interrupt flag
|
|
IE1 |= WDTIE; // enable watchdog interrupts
|
|
|
|
TACCTL1 = 0; // turn off timer 1 interrupts
|
|
P1OUT &= ~(LED1+LED2); // turn off the leds
|
|
Mode = RunningMode;
|
|
__bic_SR_register_on_exit(LPM3_bits); // take us out of low power mode
|
|
|
|
}
|
|
|
|
// WDT Interrupt Service Routine used to de-bounce button press
|
|
#if defined(__TI_COMPILER_VERSION__)
|
|
#pragma vector=WDT_VECTOR
|
|
__interrupt void wdt_isr(void)
|
|
#else
|
|
void __attribute__ ((interrupt(WDT_VECTOR))) wdt_isr (void)
|
|
#endif
|
|
{
|
|
IE1 &= ~WDTIE; /* disable watchdog interrupt */
|
|
IFG1 &= ~WDTIFG; /* clear interrupt flag */
|
|
WDTCTL = WDTPW + WDTHOLD; /* put WDT back in hold state */
|
|
P1IE |= BUTTON; /* Debouncing complete - reenable port 1 interrupts*/
|
|
}
|
|
|
|
// ADC10 interrupt service routine
|
|
#if defined(__TI_COMPILER_VERSION__)
|
|
#pragma vector=ADC10_VECTOR
|
|
__interrupt void adc10_isr(void)
|
|
#else
|
|
void __attribute__ ((interrupt(ADC10_VECTOR))) adc10_isr (void)
|
|
#endif
|
|
{
|
|
__bic_SR_register_on_exit(CPUOFF); // Restart the cpu
|
|
}
|
|
|