1 | #include <msp430x20x3.h>
|
2 |
|
3 | #define LED_OUT BIT0 // Bit location for LED
|
4 | #define SENSOR_PWR BIT7 // Bit location for power to sensor
|
5 | #define THRESHOLD 50 // Threshold for motion
|
6 |
|
7 | static unsigned int result_old = 0; // Storage for last conversion
|
8 | char LED_ENABLE = 1; // LED control
|
9 |
|
10 | void main(void)
|
11 | {
|
12 | WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL; // ACLK/32768, int timer: ~10s
|
13 | BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1MHz
|
14 | DCOCTL = CALDCO_1MHZ;
|
15 | BCSCTL1 |= DIVA_2; // ACLK = VLO/4
|
16 | BCSCTL3 |= LFXT1S_2;
|
17 |
|
18 | P1OUT = 0x10; // P1OUTs
|
19 | P1SEL = 0x08; // Select VREF function
|
20 | P1DIR = 0xEF; // Unused pins as outputs
|
21 | P1REN |= 0x10; // P1.4 pullup
|
22 | P1IE |= 0x10; // P1.4 interrupt enabled
|
23 | P1IES |= 0x10; // P1.4 Hi/lo edge
|
24 | P1IFG &= ~0x10; // P1.4 IFG cleared
|
25 | P2OUT = 0x00 + SENSOR_PWR; // P2OUTs
|
26 | P2SEL &= ~SENSOR_PWR; // P2.7 = GPIO
|
27 | P2DIR = 0xff; // Unused pins as outputs
|
28 |
|
29 | SD16CTL = SD16VMIDON + SD16REFON + SD16SSEL_1;// 1.2V ref, SMCLK
|
30 | SD16INCTL0 = SD16GAIN_4 + SD16INCH_4; // PGA = 4x, Diff inputs A4- & A4+
|
31 | SD16CCTL0 = SD16SNGL + SD16IE; // Single conversion, 256OSR, Int enable
|
32 | SD16CTL &= ~SD16VMIDON; // VMID off: used to settle ref cap
|
33 | SD16AE = SD16AE1 + SD16AE2; // P1.1 & P1.2: A4+/- SD16_A inputs
|
34 |
|
35 | // Wait for PIR sensor to settle: 1st WDT+ interval
|
36 | P1SEL |= LED_OUT; // Turn LED on with ACLK (for low Icc)
|
37 | while(!(IFG1 & WDTIFG)); // ~5.4s delay: PIR sensor settling
|
38 | P1SEL &= ~LED_OUT; // Turn LED off with ACLK (for low Icc)
|
39 |
|
40 | // Reconfig WDT+ for normal operation: interval of ~341msec
|
41 | WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS1;// ACLK/512, int timer: 341msec
|
42 | BCSCTL1 |= DIVA_3; // ACLK = VLO/8
|
43 | IE1 |= WDTIE; // Enable WDT interrupt
|
44 |
|
45 | _BIS_SR(LPM3_bits + GIE); // Enter LPM3 with interrupts
|
46 | }
|
47 |
|
48 | /******************************************************
|
49 | // SD16_A interrupt service routine
|
50 | ******************************************************/
|
51 | #pragma vector = SD16_VECTOR
|
52 | __interrupt void SD16ISR(void)
|
53 | { unsigned int result_new;
|
54 |
|
55 | SD16CTL &= ~SD16REFON; // Turn off SD16_A ref
|
56 | result_new = SD16MEM0; // Save result (clears IFG)
|
57 |
|
58 | if (result_new > result_old) // Get difference between samples
|
59 | result_old = result_new - result_old;
|
60 | else
|
61 | result_old = result_old - result_new;
|
62 |
|
63 | if (result_old > THRESHOLD) // If motion detected...
|
64 | if (LED_ENABLE & 0x01)
|
65 | P1OUT |= LED_OUT; // Turn LED on
|
66 |
|
67 | result_old = SD16MEM0; // Save last conversion
|
68 |
|
69 | __bis_SR_register_on_exit(SCG1+SCG0); // Return to LPM3 after reti
|
70 | }
|
71 |
|
72 | /******************************************************
|
73 | // Watchdog Timer interrupt service routine
|
74 | ******************************************************/
|
75 | #pragma vector=WDT_VECTOR
|
76 | __interrupt void watchdog_timer(void)
|
77 | {
|
78 | if (!(P1OUT & LED_OUT)) // Has motion already been detected?
|
79 | {
|
80 | SD16CTL |= SD16REFON; // If no, turn on SD16_A ref
|
81 | SD16CCTL0 |= SD16SC; // Set bit to start new conversion
|
82 | __bic_SR_register_on_exit(SCG1+SCG0); // Keep DCO & SMCLK on after reti
|
83 | }
|
84 | else
|
85 | P1OUT &= ~LED_OUT; // If yes, turn off LED, measure on next loop
|
86 | }
|
87 |
|
88 | // Port 1 interrupt service routine
|
89 | #pragma vector=PORT1_VECTOR
|
90 | __interrupt void Port_1(void)
|
91 | {
|
92 | LED_ENABLE ^= 0x01; // Toggle LED enable for current measurement
|
93 | P1IFG &= ~0x10; // P1.4 IFG cleared
|
94 | }
|