teddydogowners
Newbie level 4
Hi!
I am using the CTMU of a PIC24FJ64GA106, and I can't seem to calibrate it at all. The CTMUIsrc value always returns as 0, and the CTMUCap always returns as NaN. What could be the problem?
Thanks in advance!
I am using the CTMU of a PIC24FJ64GA106, and I can't seem to calibrate it at all. The CTMUIsrc value always returns as 0, and the CTMUCap always returns as NaN. What could be the problem?
Thanks in advance!
Code:
#include "p24Fxxxx.h"
#include "p24FJ64GA106.h"
#include "adc.h"
#include "comparator.h"
#include "crc.h"
#include "ctmu.h"
#include "i2c.h"
#include "incap.h"
#include "outcompare.h"
#include "pmp.h"
#include "ports.h"
#include "PPS.h"
#include "PwrMgnt.h"
#include "Rtcc.h"
#include "spi.h"
#include "sram.h"
#include "timer.h"
#include "uart.h"
#include "wdt.h"
#include "stdio.h"
#include "stdlib.h"
#include "xc.h"
#include "PIC24F_periph_features.h"
// CONFIG3
#pragma config WPFP = WPFP511 // Write Protection Flash Page Segment Boundary (Highest Page (same as page 42))
#pragma config WPDIS = WPDIS // Segment Write Protection Disable bit (Segmented code protection disabled)
#pragma config WPCFG = WPCFGDIS // Configuration Word Code Page Protection Selectbit (Last page(at the top of program memory) and Flash configuration words are not protected)
#pragma config WPEND = WPENDMEM // Segment Write Protection End Page Select bit (Write Protect from WPFP to the last page of memory)
// CONFIG2
#pragma config POSCMOD = EC // Primary Oscillator Select (EC Oscillator mode Selected)
#pragma config IOL1WAY = OFF // IOLOCK One-Way Set Enable bit (Write RP Registers Once)
#pragma config OSCIOFNC = OFF // Primary Oscillator Output Function (OSCO functions as CLKO (FOSC/2))
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor (Both Clock Switching and Fail-safe Clock Monitor are disabled)
#pragma config FNOSC = PRI // Oscillator Select (Primary oscillator (XT, HS, EC))
#pragma config IESO = OFF // Internal External Switch Over Mode (IESO mode (Two-speed start-up)disabled)
// CONFIG1
#pragma config WDTPS = PS1 // Watchdog Timer Postscaler (1:1)
#pragma config FWPSA = PR32 // WDT Prescaler (1:32)
#pragma config WINDIS = OFF // Watchdog Timer Window (Standard Watchdog timer is enabled(Windowed mode is disabled))
#pragma config FWDTEN = OFF // Watchdog Timer Enable (Watchdog timer is disabled)
#pragma config ICS = PGx1 // Comm Channel Select (EMUC/EMUD share PGC1/PGD1)
#pragma config GWRP = OFF // General Code Segment Write Protect (Writes to program memory are allowed)
#pragma config GCP = OFF // General Code Segment Code Protect (Code protection is disabled)
#pragma config JTAGEN = OFF // JTAG Port Enable (JTAG port is disabled)
/**************************************************************************/
//Setup CTMU
/**************************************************************************/
double CTMUISrc=0;
double CTMUCap=0;;
int setupcur(void);
int setupcap(void);
int CurCal(void);
int CapCal(void);
int StartPulse(void);
int TimeMeasure(void);
int main(void)
{
RCON=0x0000;
OSCCONL=0x46;
OSCCONH=0x78;
//OSCCONH=0x9A;
//OSCCONH=0x22;
/*OSCCONbits.CLKLOCK=0;
OSCCONbits.IOLOCK=1;
OSCCONbits.LOCK=0;
OSCCONbits.CF=0;
OSCCONbits.POSCEN=1;
OSCCONbits.SOSCEN=1;
OSCCONbits.OSWEN=0;*/
CLKDIV=0x0000;
REFOCON=0x0000;
CurCal();
CapCal();
/*while(1)
{
// Step 7: Wait for ADC interrupt
while(IFS0bits.AD1IF == 0)
{
// Steps 8-11
IFS0bits.AD1IF = 0; // clear the interrupt
result = ADC1BUF0; // read ADC result
CTMUCONbits.IDISSEN = 1; // begin manual discharge of cap
asm("NOP"); // may be required for external caps
asm("NOP");
asm("NOP");
asm("NOP");
CTMUCONbits.IDISSEN = 0; // stop discharge of cap
CTMUCON &= ~0x0300; // clear the edge status bits
}
}*/
//TimeMeasure();
int i=0;
TRISFbits.TRISF0=0;
LATFbits.LATF0=1;
while(1)
{
LATFbits.LATF0=0;
for(i=0;i<8100;i++);
LATFbits.LATF0=1;
for(i=0;i<8100;i++);
}
return(1);
}
int setupcur(void)
{ //CTMUCON - CTMU Control register
CTMUCON = 0x80FC; //make sure CTMU is disabled
//CTMU continues to run when emulator is stopped,CTMU continues
//to run in idle mode,Time Generation mode disabled, Edges are blocked
//No edge sequence order, Analog current source not grounded, trigger
//output disabled, Edge2 polarity = positive level, Edge2 source =
//source 0, Edge1 polarity = positive level, Edge1 source = source 0,
// Set Edge status bits to zero
//CTMUICON - CTMU Current Control Register
CTMUICON = 0x0100; //0.55uA, Nominal - No Adjustment
//-------------------------------------------------------------------------
//setupAD converter;
//-------------------------------------------------------------------------
TRISB=0x0001; //set channel 0 as an input
AD1PCFGL=0x0000; //
AD1PCFGH=0x0000;
AD1CHS=0x0000; //select the analog channel(0)
AD1CSSL=0x0001; //
AD1CON1 = 0x8000; //Turn On A/D Converter, continue in
// idle mode, Unsigned fractional format, Clear Samp bit to start
//conversion, Sample when SAMP bit is set, sampling on hold
AD1CON2 = 0x0000; //VR+ = AVDD, V- = AVSS, Don't scan,
//always use MUX A inputs
AD1CON3 = 0x0100; //A/D uses system clock, conversion
//clock = 1xTcy
return(1);
}
int setupcap(void)
{
//CTMUCON - CTMU Control register
CTMUCON = 0x80FC; //make sure CTMU is disabled
//CTMU continues to run when emulator is stopped,CTMU continues
//to run in idle mode,Time Generation mode disabled, Edges are blocked
//No edge sequence order, Analog current source not grounded, trigger
//output disabled, Edge2 polarity = positive level, Edge2 source =
//source 0, Edge1 polarity = positive level, Edge1 source = source 0,
// Set Edge status bits to zero
//CTMUICON - CTMU Current Control Register
CTMUICON = 0x0100; //0.55uA, Nominal - No Adjustment
//-------------------------------------------------------------------------
//setupAD converter;
//-------------------------------------------------------------------------
TRISB=0x0002; //set channel 1 as an input
AD1PCFGL=0x0000; //
AD1PCFGH=0x0000;
AD1CHS=0x0101; //select the analog channel(1)
AD1CSSL=0x0002; //
AD1CON1 = 0x8000; //Turn On A/D Converter, continue in
// idle mode, Unsigned fractional format, Clear Samp bit to start
//conversion, Sample when SAMP bit is set, sampling on hold
AD1CON2 = 0x0000; //VR+ = AVDD, V- = AVSS, Don't scan,
//always use MUX A inputs
AD1CON3 = 0x0100; //A/D uses system clock, conversion
//clock = 1xTcy
return(1);
}
#define COUNT 500 //@ 8MHz = 125uS.
#define DELAY for(i=0;i<COUNT;i++)
#define RCAL .027 //R value is 4200000 (4.2M)
//scaled so that result is in
//1/100th of uA
#define ADSCALE 1023 //for unsigned conversion 10 sig bits
#define ADREF 3.3 //Vdd connected to A/D Vr+
int CurCal(void)
{
int i;
int j = 0; //index for loop
double Vread = 0;
double VTot = 0;
float Vavg=0, Vcal=0; //float values stored for calculations
setupcur();
CTMUCONbits.CTMUEN = 1; //Enable the CTMU
for(j=0;j<10;j++)
{
AD1CON1bits.SAMP = 1; //Manual sampling start
CTMUCONbits.IDISSEN = 1; //drain charge on the circuit
DELAY; //wait 125us
CTMUCONbits.IDISSEN = 0; //end drain of circuit
CTMUCONbits.EDG1STAT = 1; //Begin charging the circuit
//using CTMU current source
DELAY; //wait for 125us
CTMUCONbits.EDG1STAT = 0; //Stop charging circuit
IFS0bits.AD1IF = 0; //make sure A/D Int not set
AD1CON1bits.SAMP = 0; //and begin A/D conv.
while(!IFS0bits.AD1IF); //Wait for A/D convert complete
AD1CON1bits.DONE = 0;
Vread = ADC1BUF0; //Get the value from the A/D
IFS0bits.AD1IF = 0; //Clear A/D Interrupt Flag
VTot += Vread; //Add the reading to the total
}
Vavg = (float)(VTot/10.000); //Average of 10 readings
Vcal = (float)(Vavg/ADSCALE*ADREF);
CTMUISrc = Vcal/RCAL; //CTMUISrc is in 1/100ths of uA
return(1);
}
#define COUNT2 25 //@ 8MHz INTFRC = 62.5 us.
#define ETIME COUNT2*2.5 //time in uS
#define DELAY2 for(i=0;i<COUNT2;i++)
#define ADSCALE 1023 //for unsigned conversion 10 sig bits
#define ADREF 3.3 //Vdd connected to A/D Vr+
int CapCal(void)
{
int i;
int j = 0; //index for loop
unsigned int Vread = 0;
float Vavg;
float VTot;
float Vcal;
//assume CTMU and A/D have been setup correctly
//see Example 11-1 for CTMU & A/D setup
setupcap();
CTMUCONbits.CTMUEN = 1;//Enable the CTMU
for(j=0;j<10;j++)
{
AD1CON1bits.SAMP = 1; //Manual sampling start
CTMUCONbits.IDISSEN= 1; //drain any charge on the circuit
DELAY2; //wait 62.5 us
CTMUCONbits.IDISSEN = 0; //end drain of circuit
CTMUCONbits.EDG1STAT = 1; //Begin charging the circuit
//using the CTMU current source
DELAY2; //wait for 62.5 us for circuit to charge
CTMUCONbits.EDG1STAT = 0; //Stop charging circuit and begin A/D conv.
AD1CON1bits.SAMP = 0;
while(!IFS0bits.AD1IF); //Wait for A/D conversion to complete
Vread = ADC1BUF0; //Get the value from the A/D converter
IFS0bits.AD1IF = 0; //Clear AD1IF
VTot += Vread; //Add the reading to the total
}
Vavg = (VTot/10); //Average of 10 readings
Vcal = (Vavg/ADSCALE*ADREF);
CTMUCap = (CTMUISrc*ETIME/Vcal)/100;
//CTMUISrc is in 1/100ths of uA,
//calculated in Example 1-2
//time is in us
//CTMUCap is in pF
return(1);
}
int StartPulse(void)
{
/*TRISDbits.TRISD10=0;
RPOR1bits.RP3R=18;
OC1CON1=0x0000;
OC1R=0x0002;
OC1RS=0x0008;
PR1=0x0004;
TMR2=0x0002;
OC1CON1=0x1004;
OC1CON2=0x001F;
IEC0bits.T1IE=0;
IEC0bits.OC1IE=0;
T1CON=0x0000;
PR1=0.000000125;
T1CONbits.TON=1;
AD1PCFGL=0x0000;
AD1CON2=0x0000;//comment till here*/
TRISDbits.TRISD0=0;
RPOR5bits.RP11R=18;
asm("NOP");
OC1CON1 = 0x0000; // Turn off Output Compare 1 Module
OC1CON1 = 0x0004; // Load new compare mode to OC1CON
OC1R = 0x3000; // Initialize Compare Register1 with 0x3000
OC1RS = 0x6000; // Initialize Secondary Compare Register1 with 0x3003
PR3=0x6000;
IPC0bits.OC1IP0 = 1; // Setup Output Compare 1 interrupt for
IPC0bits.OC1IP1 = 0; // desired priority level
IPC0bits.OC1IP2 = 0; // (this example assigns level 1 priority)
IFS0bits.OC1IF = 0; // Clear Output Compare 1 interrupt flag
IEC0bits.OC1IE = 0; // Enable Output Compare 1 interrupts
T2CONbits.TSIDL=0;
T2CONbits.TGATE=0;
T2CONbits.TCS=0;
T2CONbits.TCKPS=0b00;
T2CONbits.T32=0;
T2CONbits.TON = 1; // Start Timer2 with assumed settings
return(1);
}
int TimeMeasure(void)
{
float vread=0;
float time=0;
int i;
//setup CTMU
//CTMUCON
CTMUCONbits.CTMUEN = 0; //make sure CTMU is disabled
CTMUCONbits.CTMUSIDL = 0; //CTMU continues to run in idle mode
CTMUCONbits.TGEN = 0; //disable edge delay generation mode of the CTMU
CTMUCONbits.EDGEN = 1;
CTMUCONbits.EDGSEQEN = 1;
CTMUCONbits.IDISSEN = 0; //Do not ground the current source
CTMUCONbits.CTTRIG = 0; //Trigger Output is disabled
CTMUCONbits.EDG2POL = 0;
CTMUCONbits.EDG2SEL = 0b10; //Edge2 Source = CTED2
CTMUCONbits.EDG1POL = 1;
CTMUCONbits.EDG1SEL = 0b11; //Edge1 Source = CTED1
CTMUCONbits.EDG1STAT=0;
CTMUCONbits.EDG2STAT=0;
//CTMUICON
CTMUICON=0x0000;
CTMUICONbits.IRNG=0b01; //55uA
CTMUICONbits.ITRIM = 0b000000; //Nominal - No Adjustment
//setup A/D converter
TRISBbits.TRISB12 = 1; // Configure RB12 as a input CTED2
TRISBbits.TRISB13 = 1; // Configure RB13 as a input CTED1
TRISBbits.TRISB2 = 1; // Configure RB2 as a input
AD1PCFGL=0x0000; //-----------------IT SAID 0x0004, find out why
AD1PCFGH=0x0000;
AD1CHS=0x0004; //select the analog channel(2)
AD1CSSL=0x0004; //
AD1CON1 = 0x0000; //Turn Off A/D Converter, continue in idle mode, Unsigned fractional format, Sample when SAMP bit is set, sampling on hold
AD1CON1bits.SSRC = 4; // CTMU is the conversion trigger source
AD1CON2 = 0x0000; //VR+ = AVDD, V- = AVSS, Don't scan, always use MUX A inputs
AD1CON3 = 0x0000; //A/D uses system clock, conversion clock = 1xTcy
AD1CON3bits.ADCS = 8; // conversion clock = 1xTcy
AD1CON1bits.ADON = 1;
AD1CON1bits.ASAM = 1; // Auto-sample
AD1CHSbits.CH0SA = 2; // Select AN2
CTMUCONbits.CTMUEN=1;
CTMUCONbits.IDISSEN = 1; //drain charge on the circuit
DELAY; //wait 125us
CTMUCONbits.IDISSEN = 0; //end drain of circuit
AD1CON1bits.SAMP=1;
StartPulse();
DELAY; //wait for 125us
DELAY;
IFS0bits.AD1IF = 0; //make sure A/D Int not set
AD1CON1bits.SAMP = 0; //and begin A/D conv.
while(!IFS0bits.AD1IF); //Wait for A/D convert complete
AD1CON1bits.DONE = 0;
vread = ADC1BUF0;
time=vread*(CTMUCap/CTMUISrc)*(ADREF/ADSCALE); //Get time difference
return(1);
}