📄 msp430x20x1_ro keys.c
字号:
//******************************************************************************
// F2011 demo code for relaxation osc demo
//
// Version 0-00: 10-21-2006
//
// Single key detection
// This version determines if one of 4 keys has been pressed. Base capacitance
// is tracked for changes and slider max endpoint is handled for no backoff
// or back in position detections.
//
// Testing using 3.5mm insulated keys. At 1MHz/8/512, ~50counts are achieved.
// Icc is ~57uA. Sensors are sampled ~16 times per second when a key is pressed;
// and ~3 times per second when no key is pressed after ~2 seconds. Current
// Consumption in this case is ~ 10uA.
//
// For demonstration, LEDs show finger position.
// Last "Key" maintains LED status
//
// Zack Albus
//******************************************************************************
#include "msp430x20x1.h"
// Define User Configuration values //
//----------------------------------//
// Defines WDT SMCLK interval for sensor measurements
#define WDT_meas_setting (DIV_SMCLK_512)
// Defines WDT ACLK interval for delay between measurement cycles
#define WDT_delay_setting (DIV_ACLK_512)
// Sensor settings
#define Num_Sen 4 // Defines number of sensors
#define KEY_lvl 25 // Defines the min count for a "key press"
// Set to ~ half the max delta expected
// Definitions for use with the WDT settings
#define DIV_ACLK_32768 (WDT_ADLY_1000) /* ACLK/32768 */
#define DIV_ACLK_8192 (WDT_ADLY_250) /* ACLK/8192 */
#define DIV_ACLK_512 (WDT_ADLY_16) /* ACLK/512 */
#define DIV_ACLK_64 (WDT_ADLY_1_9) /* ACLK/64 */
#define DIV_SMCLK_32768 (WDT_MDLY_32) /* SMCLK/32768 */
#define DIV_SMCLK_8192 (WDT_MDLY_8) /* SMCLK/8192 */
#define DIV_SMCLK_512 (WDT_MDLY_0_5) /* SMCLK/512 */
#define DIV_SMCLK_64 (WDT_MDLY_0_064) /* SMCLK/64 */
// Define Hardware Inputs/Outputs
#define CA_Out (0x80) // Comparator output on P1.7
#define CA_Ref (0x02) // Comparator reference on P1.1
#define TA_Clk (0x01) // Timer_A clock input on P1.0
#define Ref_En (0x40) // External CA+ ref enable on P1.6
#define S_1 (0x04) // Sensor 1 P1.2
#define S_2 (0x08) // Sensor 2 P1.3
#define S_3 (0x10) // Sensor 3 P1.4
#define S_4 (0x20) // Sensor 4 P1.5
#define CA_1 (P2CA4) // Mux settings: CA+ Vref at CA1
#define CA_2 (P2CA2) // Mux settings: Sensor 1 at CA2
#define CA_3 (P2CA1+P2CA2) // Mux settings: Sensor 2 at CA2
#define CA_4 (P2CA3) // Mux settings: Sensor 3 at CA2
#define CA_5 (P2CA1+P2CA3) // Mux settings: Sensor 4 at CA2
#define LED_1 (0x80) // P2.7
#define LED_2 (0x40) // P2.6
#define BUZZ (0x80) // Buzzer on P2.7
// Global variables for sensing
unsigned int base_cnt[Num_Sen];
unsigned int meas_cnt[Num_Sen];
int delta_cnt[Num_Sen];
unsigned char key_press[Num_Sen];
char key_pressed, key_loc;
int cycles;
// System Routines
void initialize(void); // Configure modules & control Registers
void measure_count(void); // Measures each capacitive sensor
void pulse_LED(void); // LED gradient routine (for demo only)
// Main Function
void main(void)
{ volatile unsigned int i,j;
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1, 8, 12 or 16MHz
DCOCTL = CALDCO_1MHZ;
BCSCTL1 |= DIVA_0; // ACLK/(0:1,1:2,2:4,3:8)
BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO
IE1 |= WDTIE; // enable WDT interrupt
P1OUT = 0x00; // P1.x = 0
P1DIR = 0xFE; // P1.0 = TACLK input
P1SEL |= 0x81; // P1.0 = TACLK input, P1.7 = CAOUT
P2OUT = 0x00; //
P2DIR = LED_1 + LED_2; // P2.6, P2.7 = outputs
P2SEL = 0x00; // No XTAL
CAPD = CA_Ref; // disable input buffer for CA+ ref input
CACTL2 = CA_1; // CA1 = CA+ Vref
_EINT(); // Enable interrupts
P1OUT |= Ref_En; // Enable CA+ external reference
measure_count(); // Establish an initial baseline capacitance
for (i = 0; i<Num_Sen; i++)
base_cnt[i] = meas_cnt[i];
for(i=15; i>0; i--) // Repeat and average base measurement
{ measure_count();
for (j = 0; j<Num_Sen; j++)
base_cnt[j] = (meas_cnt[j]+base_cnt[j])/2;
}
P1OUT &= ~Ref_En; // Disable CA+ external reference
// Main loop starts here
while (1)
{
key_pressed = 0; // Assume no keys are pressed
measure_count(); // Measure all sensors
for (i = 0; i<Num_Sen; i++)
{ delta_cnt[i] = base_cnt[i] - meas_cnt[i]; // Calculate delta: c_change
// Handle baseline measurment for a base C decrease
if (delta_cnt[i] < 0) // If negative: result increased
{ // beyond baseline, i.e. cap decreased
base_cnt[i] = (base_cnt[i]+meas_cnt[i]) >> 1; // Re-average baseline up quickly
delta_cnt[i] = 0; // Zero out delta for position determination
}
if (delta_cnt[i] > KEY_lvl) // Determine if each key is pressed per a preset threshold
{
key_press[i] = 1; // Specific key pressed
key_pressed = 1; // Any key pressed
}
else
key_press[i] = 0;
}
// Delay to next sample, sample more slowly if no keys are pressed
if (key_pressed)
{
BCSCTL1 = (BCSCTL1 & 0x0CF) + DIVA_0; // ACLK/(0:1,1:2,2:4,3:8)
cycles = 20;
}
else
{
cycles--;
if (cycles > 0)
BCSCTL1 = (BCSCTL1 & 0x0CF) + DIVA_0; // ACLK/(0:1,1:2,2:4,3:8)
else
{
BCSCTL1 = (BCSCTL1 & 0x0CF) + DIVA_3; // ACLK/(0:1,1:2,2:4,3:8)
cycles = 0;
}
}
WDTCTL = WDT_delay_setting; // WDT, ACLK, interval timer
// Handle baseline measurment for a base C increase
if (!key_pressed) // Only adjust baseline down if no keys are touched
{
for (i = 0; i<Num_Sen; i++)
base_cnt[i] = base_cnt[i] - 1; // Adjust baseline down, should be slow to
} // accomodate for genuine changes in sensor C
pulse_LED();
LPM3;
}
} // End Main
// Measure count result (capacitance) of each sensor
// Routine setup for four sensors, not dependent on Num_Sen value!
void measure_count(void)
{ char i;
TACTL = TASSEL_0+MC_2; // TACLK, cont mode
TACCTL1 = CM_3+CCIS_2+CAP; // Pos&Neg,GND,Cap
P1OUT |= Ref_En; // Turn on CA ref ladder
CACTL1 |= CAON; // Turn on comparator
BCSCTL2 |= DIVS_3; // SMCLK = DCO/8, maximize counts
for (i = 0; i<Num_Sen; i++)
{
switch (i)
{
case 0: // Sensor 1
CAPD = CA_Ref+S_1; // Diable I/Os for CA1 ref, 1st sensor
CACTL2 = CA_1+CA_2; // CA1 ref, CAx sensor
break;
case 1: // Sensor 2
CAPD = CA_Ref+S_2; // Diable I/Os for CA1 ref, 2nd sensor
CACTL2 = CA_1+CA_3; // CA1 ref, CAx sensor
break;
case 2: // Sensor 3
CAPD = CA_Ref+S_3; // Diable I/Os for CA1 ref, 3rd sensor
CACTL2 = CA_1+CA_4; // CA1 ref, CAx sensor
break;
case 3: // Sensor 4
CAPD = CA_Ref+S_4; // Diable I/Os for CA1 ref, 4th sensor
CACTL2 = CA_1+CA_5; // CA1 ref, CAx sensor
break;
}
WDTCTL = WDT_meas_setting; // Set duration of sensor measurment
TACTL |= TACLR; // Clear Timer_A TAR
LPM0; // Wait for WDT interrupt
meas_cnt[i] = TACCR1; // Save result
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
}
BCSCTL2 &= ~DIVS_3; // SMCLK = DCO
// End Sequence
P1OUT &= ~Ref_En; // Turn off CA ref ladder
CACTL1 &= ~CAON; // Turn off comparator
CAPD = CA_Ref; // Re-init Mux: all sensors = GND
CACTL2 = CA_1; // Only CA Ref connected
}
void pulse_LED(void)
{ char i;
TACTL = TACLR; // SMCLK, up mode, int enabled
TACCTL1 = CCIE; // interrupt enabled
TACCR0 = 40001; // max leftover counts in one pass though of main
TACCR1 = 40000; // time for led to be on
if (key_pressed)
{
for (i = 0; i<Num_Sen; i++)
{
if (key_press[i]) // key pressed?
key_loc = i+1;
}
}
switch (key_loc)
{
case 1: P2OUT = 0;
TACCR1 = 1;
break;
case 2: P2OUT = LED_1;
break;
case 3: P2OUT = LED_2;
break;
case 4: P2OUT = LED_1 + LED_2;
break;
default:
break;
}
TACTL = TACLR + TASSEL_2 + MC_1; // SMCLK, up mode, int enabled
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
TACTL = TACLR;
P2OUT &= ~(LED_1 + LED_2);
}
// Watchdog Timer interrupt service routine
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
TACCTL1 ^= CCIS0; // Create SW capture of CCR1
LPM3_EXIT; // Exit LPM3 on reti
}
// Timer A1 interrupt service routine
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A1 (void)
{
TACCTL1 &= ~CCIE; // interrupt disbled
LPM0_EXIT;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -