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 */
Very Good
ReplyDeleteThanks for posting your project and the code. Just tried an experiment following your example for a PIC12F1840 and it works a treat!
ReplyDeleteSir can you plz share circuit as well. Thanks for the tutorial.
ReplyDeleteJust very basic circuit... in the code you can see RA2 used as the LED output and CPS3 as the cap sense pin... no other parts used other than a current limiting resistor for the LED
DeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteLink to the MPLABX files is right after the code list now...
Delete