Sei sulla pagina 1di 5

//******************************************************************************

// Smoke Detector Code for F2002


//
// THIS PROGRAM IS PROVIDED "AS IS". TI MAKES NO WARRANTIES OR
// REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
// INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR
// COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE.
// TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET
// POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY
// INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR
// YOUR USE OF THE PROGRAM.
//
// IN NO EVENT SHALL TI BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
// CONSEQUENTIAL OR INDIRECT DAMAGES, HOWEVER CAUSED, ON ANY
// THEORY OF LIABILITY AND WHETHER OR NOT TI HAS BEEN ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGES, ARISING IN ANY WAY OUT
// OF THIS AGREEMENT, THE PROGRAM, OR YOUR USE OF THE PROGRAM.
// EXCLUDED DAMAGES INCLUDE, BUT ARE NOT LIMITED TO, COST OF
// REMOVAL OR REINSTALLATION, COMPUTER TIME, LABOR COSTS, LOSS
// OF GOODWILL, LOSS OF PROFITS, LOSS OF SAVINGS, OR LOSS OF
// USE OR INTERRUPTION OF BUSINESS. IN NO EVENT WILL TI'S
// AGGREGATE LIABILITY UNDER THIS AGREEMENT OR ARISING OUT OF
// YOUR USE OF THE PROGRAM EXCEED FIVE HUNDRED DOLLARS
// (U.S.$500).
//
// Unless otherwise stated, the Program written and copyrighted
// by Texas Instruments is distributed as "freeware". You may,
// only under TI's copyright in the Program, use and modify the
// Program without any charge or restriction. You may
// distribute to third parties, provided that you transfer a
// copy of this license to the third party and the third party
// agrees to these terms by its first use of the Program. You
// must reproduce the copyright notice and any other legend of
// ownership on each copy or partial copy, of the Program.
//
// You acknowledge and agree that the Program contains
// copyrighted material, trade secrets and other TI proprietary
// information and is protected by copyright laws,
// international copyright treaties, and trade secret laws, as
// well as other intellectual property laws. To protect TI's
// rights in the Program, you agree not to decompile, reverse
// engineer, disassemble or otherwise translate any object code
// versions of the Program to a human-readable form. You agree
// that in no event will you alter, remove or destroy any
// copyright notice included in the Program. TI reserves all
// rights not specifically granted under this license. Except
// as specifically provided herein, nothing in this agreement
// shall be construed as conferring by implication, estoppel,
// or otherwise, upon you, any license or other right under any
// TI patents, copyrights or trade secrets.
//
// You may not use the Program in non-TI devices.
//
//******************************************************************************
#include <msp430x20x2.h>
#define LED 0x01
#define IRLED 0x40

#define OA_power 0x20


unsigned
unsigned
unsigned
unsigned
unsigned
unsigned

int dark_buffer[4];
int light_buffer[4];
int dark_average;
int light_average;
char smoke_detect_count = 0;
char alarm_flag = 0;

void Setup(void);
void Sample (void);
void Average (void);
unsigned int Cal_VLO(void);
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;
Setup();

//
//
//
//
//
//

buffer for 4 ADC samples


buffer for 4 ADC samples
Average 4 samples with no IRLED
Average 4 samples with IRLED on
Counter for smoke detections
Alarm status. 1 means smoke

// Function protos

// Stop watchdog timer


// Call init routine

for (;;)
{
LPM3;
Sample();
Average();
if (light_average > (dark_average + 30))
{
if (alarm_flag == 0)
{
smoke_detect_count++;
smoke_detect_count &= 0x03;

// Increment detection counter


// Only count values of up to 3

if (smoke_detect_count == 1)
TACTL &= ~ID0;
// Clear ID0 in TACTL. This sets the
// TA clock divider to /4 instead of /8.
// This cuts the sample period in half to
4s
else if (smoke_detect_count == 2)
TACTL &= ~ID_3;
// This sets the TA clock divider to /1
// which makes the sample period 1s
else if (smoke_detect_count == 3)
{
alarm_flag = 1;
// Set alarm flag
P1OUT |= LED;
// Turn on visible LED
// Enable TA1 output for .5 second alarm cadence
P1SEL |= BIT2;
// Enable P1.2 for TA1 output
TACCTL1 = OUTMOD_3;
// Set/Reset mode for PWM
}
}
}
else // light_average not > dark_average+30
{
P1OUT &= ~LED;
// Turn off visible LED, but leave pull-up
P1SEL &= ~BIT2;
// Put P1.6 back to I/O function = no buzz
er
alarm_flag = 0;
smoke_detect_count = 0;
TACCTL1 = 0;

// If no smoke present, clear alarm flag


// Clear smoke detect counter
// Clear output mode of buzzer driver

TACTL |= ID_3;
terrupt
}
}
}

// Back to divide by 8 for TACLK for 8s in

void Setup(void)
{
unsigned int a, counts;
signed long temp = 8000000;
// Ports
P1DIR = 0xed;
P1OUT = BIT1;
P1SEL = BIT4;
P1IE = BIT1;
P1IES = BIT1;
P1REN = BIT1;
P1IFG = 0;
P2DIR = 0xff;
P2OUT = 0;
ADC10AE = BIT4;

//
//
//
//
//
//
//
//
//
//

// Setup DCO and VLO


BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;
BCSCTL3 = LFXT1S_2;

// Use 1Mhz cal data for DCO


// Use 1Mhz cal data for DCO
// Use VLO for ACLK

counts = Cal_VLO();
// setup TA for 8 second interrupt
TACTL = TASSEL_1 + ID_3 + TACLR;
TACCTL0 = CCIE;

All P1 but P1.1 and P1.4 as outputs


All P1 outputs low, P1.1 is pulled up
P1.4 as analog, other I/O
Enable switch interrupt
H to L transition for interrupt
Enable internal pull-up
Clear any pending IFGs
Output direction, except P2.3
All P2 low
Disable A4 CMOS buffer

// counts is # of VLO clocks in 8MHz


// TA = ACLK/8
// Enable CCR0 interrupt

// Divide 8Mhz by counts to get # of VLO counts in 1 second period


a = 0;
do {
temp -= counts;
a++;
} while (temp > 0);
TACCR0 = a;
TACCR1 = TACCR0 >> 1;
// Start timer
TACTL |= MC_1;

// TACCR0 period for 1 second


// Put half-period into TACCR1 for use
// when alarming.
// Up mode

_EINT();
}
unsigned int Cal_VLO (void)
{
unsigned int First_Cap, counts;
BCSCTL1 |= DIVA_3;
TACCTL0 = CM_1 + CCIS_1 + CAP;
TACTL = TASSEL_2 + MC_2 + TACLR;
while ((TACCTL0 & CCIFG) == 0);

//
//
//
//

Divide ACLK by 8
Capture on ACLK
Start TA, MCLK(DCO), Continuous
Wait until capture

TACCR0 = 0;
TACCTL0 &= ~CCIFG;

// Ignore first capture


// Clear CCIFG

while ((TACCTL0 & CCIFG) == 0);

// Wait for next capture

First_Cap = TACCR0;
TACCTL0 &= ~CCIFG;

// Save first capture


// Clear CCIFG

while ((TACCTL0 & CCIFG) ==0);

// Wait for next capture

counts = (TACCR0 - First_Cap);


BCSCTL1 &= ~DIVA_3;
return counts;

// # of VLO clocks in 8Mhz


// Clear ACLK/8 settings

}
void Sample (void)
{
unsigned volatile int i, temp;
temp = P1OUT;
//
P1OUT |= OA_power + LED;
//
ADC10CTL0 = ADC10ON + REFON + ADC10SHT_1
//

Preserve LED "on" if alarming


Turn on OA. Settling delay is below
+ MSC + ADC10IE + SREF_1;
ADC on, ref = 1.5V, sampling = 8 cloc

ks

ADC10CTL1 = INCH_4 + CONSEQ_2;

//
//
//
//

NOTE: REF takes 30us to settle, But


because of other instructs
no need for additional delay loop
Channel A4, repeat single channel mod

e
ADC10DTC1 = 4;
// Do 4 conversions
ADC10SA = (unsigned int)dark_buffer; // Start address for DTC
i = 6;
do i--;
while (i != 0);

// Delay for OA settling

ADC10CTL0 |= ENC + ADC10SC;


LPM3;

// Enable and start conversions


// Enter LPM3 while 4 conversions made

ADC10CTL0 &= ~ENC;

// Clear ENC to stop conversion

P1OUT |= IRLED;
// Turn on IRLED
ADC10SA = (unsigned int)light_buffer; // Start address for DTC
i = 4;
do i--;
while (i != 0);

// Short delay for settling

ADC10CTL0 |= ENC + ADC10SC;


LPM3;

// Enable and start conversions


// Enter LPM3 while 4 conversions made

P1OUT = temp;
ADC10CTL0 &= ~ENC;
ADC10CTL0 = 0;

// Restore P1OUT, turns off IRLED and OA


// Clear ENC to stop conversions
// Turn off ADC and reference

}
void Average (void)
{
unsigned int i;

dark_average = 0;
light_average = 0;
for (i = 0; i < 4; i++)
{
dark_average += dark_buffer[i];
light_average += light_buffer[i];
}
dark_average = (dark_average >> 2);
light_average = (light_average >> 2);
}
// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0 (void)
{
LPM3_EXIT;
}
// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10 (void)
{
LPM3_EXIT;
}
// P1.0 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void P1_ISR (void)
{
unsigned volatile int i;
i = 5000;
do i--;
while (i != 0);
P1IFG = 0;
P1OUT ^= BIT2;
}

// ~50ms Debounce delay


//
// Clear IFG
// Toggle of P1.2 to turn on/off siren

Potrebbero piacerti anche