Skip to content

Instantly share code, notes, and snippets.

@mrmekon
Created January 16, 2012 23:04
Show Gist options
  • Save mrmekon/1623490 to your computer and use it in GitHub Desktop.
Save mrmekon/1623490 to your computer and use it in GitHub Desktop.
MSP430 capacitive touch sensor with ADC and capacitor
/*
* 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)
{
}
//------------------------------------------------------------------------------
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