labs/lab5/temperature_demo5/main.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
}