⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smoke detector.c

📁 Smoke Detector Code for F2002
💻 C
字号:
//******************************************************************************
//  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 int dark_buffer[4];            // buffer for 4 ADC samples
unsigned int light_buffer[4];           // buffer for 4 ADC samples
unsigned int dark_average;              // Average 4 samples with no IRLED
unsigned int light_average;             // Average 4 samples with IRLED on
unsigned char smoke_detect_count = 0;   // Counter for smoke detections
unsigned char alarm_flag = 0;           // Alarm status. 1 means smoke

void Setup(void);                       // Function protos
void Sample (void);
void Average (void);
unsigned int Cal_VLO(void);

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;             // Stop watchdog timer
  Setup();                              // Call init routine

  for (;;)
  {
    LPM3;
    Sample();
    Average();

    if (light_average > (dark_average + 30))
    {

      if (alarm_flag == 0)
      {
        smoke_detect_count++;         // Increment detection counter
        smoke_detect_count &= 0x03;   // 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 buzzer
      alarm_flag = 0;                 // If no smoke present, clear alarm flag
      smoke_detect_count = 0;         // Clear smoke detect counter
      TACCTL1 = 0;                    // Clear output mode of buzzer driver
      TACTL |= ID_3;                  // Back to divide by 8 for TACLK for 8s interrupt
    }
  }
}


void Setup(void)
{
  unsigned int a, counts;
  signed long temp = 8000000;

// Ports
  P1DIR  = 0xed;                        // All P1 but P1.1 and P1.4 as outputs
  P1OUT = BIT1;                         // All P1 outputs low, P1.1 is pulled up
  P1SEL = BIT4;                         // P1.4 as analog, other I/O
  P1IE = BIT1;                          // Enable switch interrupt
  P1IES = BIT1;                         // H to L transition for interrupt
  P1REN = BIT1;                         // Enable internal pull-up
  P1IFG = 0;                            // Clear any pending IFGs
  P2DIR  = 0xff;                        // Output direction, except P2.3
  P2OUT = 0;                            // All P2 low
  ADC10AE = BIT4;                       // Disable A4 CMOS buffer

// Setup DCO and VLO
  BCSCTL1 = CALBC1_1MHZ;                // Use 1Mhz cal data for DCO
  DCOCTL = CALDCO_1MHZ;                 // Use 1Mhz cal data for DCO
  BCSCTL3 = LFXT1S_2;                   // Use VLO for ACLK

  counts = Cal_VLO();                   // counts is # of VLO clocks in 8MHz

// setup TA for 8 second interrupt
  TACTL = TASSEL_1 + ID_3 + TACLR;      // TA = ACLK/8
  TACCTL0 = CCIE;                       // 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;                           // TACCR0 period for 1 second
  TACCR1 = TACCR0 >> 1;                 // Put half-period into TACCR1 for use
                                        // when alarming.
// Start timer
  TACTL |= MC_1;                        // Up mode

  _EINT();
}

unsigned int Cal_VLO (void)
{
  unsigned int First_Cap, counts;

  BCSCTL1 |= DIVA_3;                    // Divide ACLK by 8
  TACCTL0 = CM_1 + CCIS_1 + CAP;        // Capture on ACLK
  TACTL = TASSEL_2 + MC_2 + TACLR;      // Start TA, MCLK(DCO), Continuous
  while ((TACCTL0 & CCIFG) == 0);       // Wait until capture

  TACCR0 = 0;                           // Ignore first capture
  TACCTL0 &= ~CCIFG;                    // Clear CCIFG

  while ((TACCTL0 & CCIFG) == 0);       // Wait for next capture

  First_Cap = TACCR0;                   // Save first capture
  TACCTL0 &= ~CCIFG;                    // Clear CCIFG

  while ((TACCTL0 & CCIFG) ==0);        // Wait for next capture

  counts = (TACCR0 - First_Cap);        // # of VLO clocks in 8Mhz
  BCSCTL1 &= ~DIVA_3;                   // Clear ACLK/8 settings
  return counts;
}

void Sample (void)
{
  unsigned volatile int i, temp;

  temp = P1OUT;                         // Preserve LED "on" if alarming
  P1OUT |= OA_power + LED;              // Turn on OA. Settling delay is below
  ADC10CTL0 = ADC10ON + REFON + ADC10SHT_1 + MSC + ADC10IE + SREF_1;
                                        // ADC on, ref = 1.5V, sampling = 8 clocks
                                        // NOTE: REF takes 30us to settle, But
                                        // because of other instructs
                                        // no need for additional delay loop
  ADC10CTL1 = INCH_4 + CONSEQ_2;        // Channel A4, repeat single channel mode
  ADC10DTC1 = 4;                        // Do 4 conversions
  ADC10SA = (unsigned int)dark_buffer;  // Start address for DTC

  i = 6;                                // Delay for OA settling
  do i--;
  while (i != 0);

  ADC10CTL0 |= ENC + ADC10SC;           // Enable and start conversions
  LPM3;                                 // 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;                                // Short delay for settling
  do i--;
  while (i != 0);

  ADC10CTL0 |= ENC + ADC10SC;           // Enable and start conversions
  LPM3;                                 // Enter LPM3 while 4 conversions made

  P1OUT = temp;                         // Restore P1OUT, turns off IRLED and OA
  ADC10CTL0 &= ~ENC;                    // Clear ENC to stop conversions
  ADC10CTL0 = 0;                        // 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;                             // ~50ms Debounce delay
  do i--;                               //
  while (i != 0);

  P1IFG = 0;                            // Clear IFG
  P1OUT ^= BIT2;                        // Toggle of P1.2 to turn on/off siren
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -