The PIC12F1840 CSM module is simply an R/C oscillator feeding a frequency counter! You select one of the four available pins as the capacitor input pin for the oscillator, setup timer 0 as the frequency counter time base, and timer 1 as the counter to count the R/C oscillator. The time base (Timer 0) is set to interrupt the PIC at specific intervals and it also gates the R/C pulses going to Timer 1. That interval should be long enough to capture a large count in Timer 1 from the R/C oscillator. The system clock is configured for internal 4MHz and Timer 0 is configured for a prescaling of 256. This gives a count of around 33,000 in Timer 1 (16 bit counter) or about half way through. So for every time interval of Timer 0 interrupting the PIC, Timer 1 will have a count of about 33,000 in it. Now in the interrupt routine you just read Timer 1 into a global variable, reset Timer 1 to zero, and re-enable interrupts for the next read. In the main body of code you just loop and watch the Timer 1 value stored in the global variable (touch in my case) and act on that value when it changes. Simple! If there is any change in the R/C oscillator's cap sense pin (like a finger, or other larger object), that will change the capacitance on that pin and shift the oscillator down ... Timer 1 will reflect that with a smaller count. Now just have your code watch for the change to a smaller count and you have a touch switch.
Here are the XC8 files out of the MPLABX IDE:
/***********************************/
/* Simple PIC 12F1840 Touch Switch Example */
/* main.c - Tim Stoddard, 2016 */
/***********************************/
#include <xc.h> /* XC8 General Include File */
#include <stdint.h> /* For uint8_t definition */
#include <stdbool.h> /* For true/false definition */
#include "system.h" /* System funct/params, like osc/peripheral config */
#include "user.h" /* User funct/params, such as InitApp */
/***********************************/
/* User Global Variable Declaration */
/***********************************/
/* i.e. uint8_t <variable_name>; */
/***********************************/
/* Main Program */
/***********************************/
void main(void)
{
/* Configure the oscillator for the device */
ConfigureOscillator();
/* Initialize I/O and Peripherals for application */
InitApp();
/* Flash the LAMP a few times */
for(i=0;i<5;i++){
LAMP=1;
__delay_ms(50);
LAMP=0;
__delay_ms(200);
}
/* grab the latest count from Timer 1 (touch), subtract a threshold amount,
and save it (touch_cal) */
touch_cal=touch-1000;
/* MAIN LOOP */
while(1)
{
if(touch<touch_cal){// sensor is touched
LAMP=1;// turn it on
}else{// otherwise ...
LAMP=0;// turn it off
}
}
}
/***********************************/
/* user.c */
/***********************************/
#include <xc.h> /* XC8 General Include File */
#include <stdint.h> /* For uint8_t definition */
#include <stdbool.h> /* For true/false definition */
#include "user.h"
/***********************************/
/* User Functions */
/***********************************/
void InitApp(void)
{
/* Setup analog functionality and port direction */
TRISA = 0b00111011; // RA2 is output
ANSA4=1;
/* Initialize peripherals */
CM1CON1=0;
CPSCON0bits.CPSRM=0;// 1=variable voltage ref, 0=fixed
CPSCON0bits.CPSRNG=0b11;// high current
CPSCON0bits.CPSON=1;
CPSCON1bits.CPSCH=0b11;//CPS3 selected
//Timer 0 is the time base for CPS
TMR0CS=0;//Timer 0 used as time base for CPS select Fosc/4
OPTION_REGbits.PS=0b111;
OPTION_REGbits.PSA=0;
// Timer 1 is the freq counter for CPS
T1CON=0b11000101; // TMR1 capacitive sensing osc, prescaler 1/1, dedicated osc disabled,no synch,timer1 enabled
T1GSEL=0b01;// set timer 1 gate for TMR0 overflow
/* Enable interrupts */
TMR0IE=1;// enable TMR0 interrupts
PEIE=1;//enable Peripheral interrupts
GIE=1;// enable global interrupts
}
/***********************************/
/*interrupts.c */
/***********************************/
#include <xc.h> /* XC8 General Include File */
#include <stdint.h> /* For uint8_t definition */
#include <stdbool.h> /* For true/false definition */
#include "user.h"
/***********************************/
/* Interrupt Routines */
/***********************************/
#ifndef _PIC12
void interrupt isr(void)
{
#if 1
GIE=0;// disable all interrupts
if(T0IF) // Timer 0 interrupt?
{
TMR1ON=0;// turn off timer 1
touch=TMR1L+(unsigned int)(TMR1H << 8);// read timer 1
TMR1H=0;// clear timer 1
TMR1L=0;
TMR1ON=1;// enable timer 1
T0IF=0;
}else{
/* Unhandled interrupts */
}
GIE=1;// enable all interrupts
#endif
}
#endif
/***********************************/
/* user.h */
/***********************************/
#define _XTAL_FREQ 4000000
#define LAMP RA2
void InitApp(void); /* I/O and Peripheral Initialization */
/* declare variables */
unsigned int touch;
unsigned int touch_cal;
unsigned int i;
/***********************************/
/* configuration_bits.c */
/***********************************/
#if defined(__XC)
#include <xc.h> /* XC8 General Include File */
#elif defined(HI_TECH_C)
#include <htc.h> /* HiTech General Include File */
#endif
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled)
/***********************************/
/* system.c */
/***********************************/
#include <xc.h> /* XC8 General Include File */
#include <stdint.h> /* For uint8_t definition */
#include <stdbool.h> /* For true/false definition */
#include "system.h"
void ConfigureOscillator(void)
{
while (!HFIOFS) continue;// wait for stable osc
#if 0
OSCCAL=_READ_OSCCAL_DATA(); /* _READ_OSCCAL_DATA macro unloads cal memory */
#endif
}
/***********************************/
/* system.h */
/***********************************/
/* TODO Define system operating frequency */
/* Microcontroller MIPs (FCY) */
#define SYS_FREQ 4000000L
#define FCY SYS_FREQ/4
/***********************************/
/* System Function Prototypes */
/***********************************/
void ConfigureOscillator(void); /* Handles clock switching/osc initialization */