Created
January 16, 2012 23:04
-
-
Save mrmekon/1623490 to your computer and use it in GitHub Desktop.
MSP430 capacitive touch sensor with ADC and capacitor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Capacitive touch sensor via ADC | |
* Trevor Bentley, January 2010 | |
* | |
* Uses ADC on MSP430 to approximate a capacitive touch sensor. | |
* | |
* 20pf cap from P1.3 to GND | |
* touch sensor (copper plate) to P1.3 | |
* optional 100k resistor P1.3 to GND | |
* | |
* Prints readings. Touch the plate, they will vary a bit. | |
* | |
* Doesn't work very well unless the human is grounded :P | |
*/ | |
#include <msp430x22x2.h> | |
#include <msp430/adc10.h> | |
#include <signal.h> | |
#include <string.h> | |
//------------------------------------------------------------------------------ | |
// Hardware-related definitions | |
//------------------------------------------------------------------------------ | |
#define UART_TXD 0x02 // TXD on P1.1 (Timer0_A.OUT0) | |
#define UART_RXD 0x04 // RXD on P1.2 (Timer0_A.CCI1A) | |
#define ADC_PIN 0x08 // LDPump detect P1.4 | |
//------------------------------------------------------------------------------ | |
// Conditions for 9600 Baud SW UART, SMCLK = 1MHz | |
//------------------------------------------------------------------------------ | |
#define UART_TBIT_DIV_2 (1000000U / (9600 * 2)) | |
#define UART_TBIT (1000000U / 9600) | |
//------------------------------------------------------------------------------ | |
// Global variables used for full-duplex UART communication | |
//------------------------------------------------------------------------------ | |
unsigned int txData = 0; // UART internal variable for TX | |
unsigned char rxBuffer = 0; // Received UART character | |
static volatile unsigned char adc_done = 1; | |
static volatile unsigned int adc_word = 0; | |
#define READING_COUNT 32 | |
#define READING_MASK (READING_COUNT-1) | |
static unsigned short readings[READING_COUNT]; | |
static unsigned char reading_idx = 0; | |
//------------------------------------------------------------------------------ | |
// Function prototypes | |
//------------------------------------------------------------------------------ | |
void Timer_A0_ISR(void); | |
static void __inline__ delay(register unsigned int n); | |
void adc_read(void); | |
void print_int(unsigned short val); | |
void uart_isr(void); | |
void TimerA_UART_init(void); | |
void TimerA_UART_tx(unsigned char byte); | |
void TimerA_UART_print(char *string); | |
void TimerB_ISR(void); | |
unsigned char hexvals[] = { | |
'0','1','2','3','4','5','6','7', | |
'8','9','A','B','C','D','E','F', | |
}; | |
//------------------------------------------------------------------------------ | |
// main() | |
//------------------------------------------------------------------------------ | |
void main(void) | |
{ | |
unsigned int i, sum; | |
// Configure clocks | |
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer | |
DCOCTL = 0x00; // Set DCOCLK to 1MHz | |
BCSCTL1 = CALBC1_1MHZ; | |
DCOCTL = CALDCO_1MHZ; | |
// Configure Port 1 | |
P1OUT = 0x00; // Initialize all GPIO | |
P1DIR = 0xFF & ~(UART_RXD | ADC_PIN); // Set all pins but RXD to output | |
P1SEL = UART_TXD | UART_RXD; // Timer function for TXD/RXD pins | |
P1REN = ADC_PIN; // enable pull-up on ADC | |
eint(); // Enable interrupts | |
__bis_SR_register(GIE); | |
TimerA_UART_init(); | |
TimerA_UART_print("\r\nCAPTOUCH_ADC\r\n"); | |
for (;;) | |
{ | |
if (adc_done) { | |
adc_read(); | |
print_int(adc_word); | |
delay(3000); | |
} | |
} | |
} | |
void print_int(unsigned short val) { | |
unsigned char mstr[10]; | |
TimerA_UART_init(); | |
mstr[0] = hexvals[val >> 12 & 0xf]; | |
mstr[1] = hexvals[val >> 8 & 0xF]; | |
mstr[2] = hexvals[val >> 4 & 0xF]; | |
mstr[3] = hexvals[val & 0xF]; | |
mstr[4] = '\r'; | |
mstr[5] = '\n'; | |
mstr[6] = 0; | |
TimerA_UART_print(mstr); | |
} | |
static void __inline__ delay(register unsigned int n) | |
{ | |
__asm__ __volatile__ ( | |
"1: \n" | |
" dec %[n] \n" | |
" jne 1b \n" | |
: [n] "+r"(n)); | |
} | |
void adc_read(void) { | |
ADC10CTL0 = 0; | |
ADC10AE0 = 0; | |
// Drive output high to charge caps | |
P1DIR |= ADC_PIN; | |
P1OUT |= ADC_PIN; | |
delay(2000); // allow caps to charge | |
// Reset back to input | |
P1DIR &= ~(ADC_PIN); | |
P1OUT = 0x00; | |
// Configure ADC | |
ADC10CTL0 = ADC10SHT_3 + ADC10ON + ADC10IE + ADC10SR; | |
ADC10CTL1 = ADC10SSEL_3 + INCH_3; | |
// Set pin to ADC mode | |
ADC10AE0 = ADC_PIN; | |
delay(1000); // allow cap to partially discharge | |
adc_done = 0; | |
ADC10CTL0 |= ENC + ADC10SC; | |
} | |
enablenested interrupt (ADC10_VECTOR) adc_isr(void) { | |
adc_word = ADC10MEM; | |
adc_done = 1; | |
} | |
//------------------------------------------------------------------------------ | |
// Timer_A UART - Transmit Interrupt Handler | |
//------------------------------------------------------------------------------ | |
enablenested interrupt (TIMERA0_VECTOR) Timer_A0_ISR(void) | |
{ | |
static unsigned char txBitCnt = 10; | |
uart: | |
TACCR0 += UART_TBIT; // Add Offset to CCRx | |
if (txBitCnt == 0) { // All bits TXed? | |
TACCTL0 &= ~CCIE; // All bits TXed, disable interrupt | |
txBitCnt = 10; // Re-load bit counter | |
} | |
else { | |
if (txData & 0x01) { | |
TACCTL0 &= ~OUTMOD2; // TX Mark '1' | |
} | |
else { | |
TACCTL0 |= OUTMOD2; // TX Space '0' | |
} | |
txData >>= 1; | |
txBitCnt--; | |
} | |
} | |
//------------------------------------------------------------------------------ | |
// Function configures Timer_A for full-duplex UART operation | |
//------------------------------------------------------------------------------ | |
void TimerA_UART_init(void) | |
{ | |
TACTL = MC_0; // Disable timer | |
TACCTL0 = OUT; // Set TXD Idle as Mark = '1' | |
TACCTL1 = SCS + CM1 + CAP + CCIE; // Sync, Neg Edge, Capture, Int | |
TACTL = TASSEL_2 + MC_2 + TACLR; // SMCLK, start in continuous mode | |
} | |
//------------------------------------------------------------------------------ | |
// Outputs one byte using the Timer_A UART | |
//------------------------------------------------------------------------------ | |
void TimerA_UART_tx(unsigned char byte) | |
{ | |
while (TACCTL0 & CCIE); // Ensure last char got TX'd | |
TACCR0 = TAR; // Current state of TA counter | |
TACCR0 += UART_TBIT; // One bit time till first bit | |
TACCTL0 = OUTMOD0 + CCIE; // Set TXD on EQU0, Int | |
txData = byte; // Load global variable | |
txData |= 0x100; // Add mark stop bit to TXData | |
txData <<= 1; // Add space start bit | |
} | |
//------------------------------------------------------------------------------ | |
// Prints a string over using the Timer_A UART | |
//------------------------------------------------------------------------------ | |
void TimerA_UART_print(char *string) | |
{ | |
while (*string) { | |
TimerA_UART_tx(*string++); | |
} | |
} | |
//------------------------------------------------------------------------------ | |
// Timer_A UART - Receive Interrupt Handler | |
//------------------------------------------------------------------------------ | |
interrupt (TIMERA1_VECTOR) Timer_A1_ISR(void) | |
{ | |
} | |
//------------------------------------------------------------------------------ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
all: default run | |
default: | |
msp430-gcc -I/usr/local/msp430-gcc-4.4.3/msp430/include/ captouch.c -save-temps -mendup-at=main -mmcu=msp430x2111 -Os | |
run: | |
mspdebug rf2500 "prog a.out" | |
dump: | |
mspdebug rf2500 "md 0x1000 256" | |
erase_info: | |
mspdebug rf2500 "erase segment 0x1000" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment