Hi, I am currently having issues configure the CTMU module in a PIC18F46K80 to respond to edges.
I am trying to measure the delay between two pulses produced by two "single photon counting module" which are connected to the CTED1 and CTED2 pins. The module can produce a new TTL signal every 62.7ns which is 35ns long. I don't mind having deadtime between new measurements (Fig1) however i can't afford to have the CTMUCONLbits.EDGE1STAT triggering if the CTMU is enabled whilst the input is active (Fig2) i would rather it waited for the next rising edge.
I have configured the following
CTMUCONH 0b10001100 // Edges are not blocked and edge1 must occur before edge2
CTMUCONL 0b11011100 //edges programmed for positive edge response and CTED1 & CTED2 connected
This config doesn't seem to work, do i miss understand the "positive edge response" settings or are they specific to the special event triggers ECCP1 & CCP2?
My code is also attached. Currently i'm using coax cable to perform tests and the input signal is generated on chip and my current resolution is around 120ps. I am testing this problem by keeping CTED1/edge1 active which should result in edge1&2 not triggering due to no rising edge being produced.
I found this data sheet for the pic24xx http://ww1.microchip.com/downloads/en/DeviceDoc/39743a.pdf which suggests it has an "EDGxMOD: Input mode selection bit" not offered on the pic18xx
Fig1
Fig2
I am trying to measure the delay between two pulses produced by two "single photon counting module" which are connected to the CTED1 and CTED2 pins. The module can produce a new TTL signal every 62.7ns which is 35ns long. I don't mind having deadtime between new measurements (Fig1) however i can't afford to have the CTMUCONLbits.EDGE1STAT triggering if the CTMU is enabled whilst the input is active (Fig2) i would rather it waited for the next rising edge.
I have configured the following
CTMUCONH 0b10001100 // Edges are not blocked and edge1 must occur before edge2
CTMUCONL 0b11011100 //edges programmed for positive edge response and CTED1 & CTED2 connected
This config doesn't seem to work, do i miss understand the "positive edge response" settings or are they specific to the special event triggers ECCP1 & CCP2?
My code is also attached. Currently i'm using coax cable to perform tests and the input signal is generated on chip and my current resolution is around 120ps. I am testing this problem by keeping CTED1/edge1 active which should result in edge1&2 not triggering due to no rising edge being produced.
I found this data sheet for the pic24xx http://ww1.microchip.com/downloads/en/DeviceDoc/39743a.pdf which suggests it has an "EDGxMOD: Input mode selection bit" not offered on the pic18xx
Fig1
Fig2
C:
#include <xc.h>
#define _XTAL_FREQ 16000000
#define TRUE 1
#define FALSE 0
#define LEDs PORTA
#define LED1 PORTAbits.RA2
#define COUNT 2 //500 //@ 8MHz = 125uS.
#define DELAY for(i=0;i<COUNT;i++)
//#define RCAL 19950 //R value is 19.95Kohm 19950
#define RCAL 1496000 //R value is 19.95Kohm 19950
//scaled so that result is in
//1/100th of uA
#define ADSCALE 4096 //for unsigned conversion 10 sig bits
#define ADREF 2
#define Current3 80 // current was calibrated to 80uA
#define Current1 0.28 // current was calibrated to 0.28uA
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <usart.h>
#include <plib.h>
#include <delays.h>
#include <sw_uart.h>
void IO_ports_init(void)
{
TRISA = 0x00; //set as output
PORTA = 0x00;
TRISB = 0;
TRISD = 0;
TRISC = 0;
//PORTB = 0;
TRISBbits.TRISB2 =1; // input for CTMU 1 edge
TRISBbits.TRISB3=1; // input for CTMU 2 edge
//LATB = 0;
//--ADC
TRISBbits.TRISB0 = 1; //set channel 10 as an input
PORTAbits.RA0 = 0;
LATAbits.LATA0 = 0;
//--UART
TRISCbits.TRISC6 = 0; // RC6 (TX1)
TRISCbits.TRISC7 = 1; //RC7 (RX1)
PORTC=0x00;
PORTD=0x00;
SLRCON = 0x00;
CTMUCONH = 0x00;
RCONbits.IPEN = 1;
INTCONbits.GIEH = 1;
}
void USART_init(void){
TXSTA1 = 0b10100100;
SPBRG1 = 103;
}
void OscillatorConfig(void){
OSCCON = 0b01111100;
OSCCON2 = 0b00010010;
}
void delayMsx(int time){
for(int x = 0; x < time; x++){
__delay_ms(1);
}
}
void delayUsx(int time){
for(int x = 0; x < time; x++){
__delay_us(1);
}
}
void ADCConfig(void){
ANCON1 = 3;
ADCON2bits.ADFM=1; // Result format 1= Right justified
ADCON2bits.ACQT=1; // Acquisition time 7 = 20TAD 2 = 4TAD 1=2TAD
ADCON2bits.ADCS=2; // Clock conversion bits 6= FOSC/64 2=FOSC/32
ADCON1bits.TRIGSEL=1;
ADCON1bits.VCFG0 =0; // Vref+ = AVdd
ADCON1bits.VCFG =2; // Vref+ = AVdd
ADCON1bits.VNCFG = 0; // Vref- = AVss
ADCON0bits.CHS=28; // Select ADC channel
ADCON0bits.ADON=0; // Turn on ADC
}
void CTMUInit (void){
CTMUCONH = 0; //make sure CTMU is disabled
CTMUCONHbits.EDGEN=1; // edge are not blocked 1 edges are blocked with 0
CTMUCONHbits.EDGSEQEN=1; // edge 1 then 2 for interrupt
CTMUCONHbits.CTTRIG=1;
CTMUCONL = 0b11011100; // CTMU trigger setup : net edge 1, neg edge 2, edge 1&2 source select CTED 1&2, clear event bits
CTMUICON = 0b01111111; // 1= base current 0.55uA 2= 5.5uA 3=55uA // max positive trim
//INTCON = 0b11100000;
//INTCON2 = 0b11111000;
//INTCON3 = 0b00000000;
}
void CTMU (void){
int Vread;
ADCON0bits.CHS=10;
CTMUCONHbits.CTMUEN = 0;
CTMUCONL = 0b11011100;
LEDs = 0;
CTMUCONHbits.IDISSEN = 1; //drain charge on the circuit
__delay_us(30);
CTMUCONHbits.IDISSEN = 0; //end drain of circuit
CTMUCONHbits.CTMUEN = 1;
__delay_us(5); // something is wrong here
LEDs = 255;
LEDs = 0;
__delay_us(5);
ADCON0bits.ADON=1;
__delay_us(5);
PIR1bits.ADIF = 0; //make sure A/D Interupt not set
ADCON0bits.GO=1; //and begin A/D conv.
while(!PIR1bits.ADIF); //Wait for A/D convert complete
Vread = ADRES; //Get the value from the A/D
PIR1bits.ADIF = 0; //Clear A/D Interrupt Flag
ADCON0bits.CHS=28; // disconnect the mux
char ac_sample_char[12];
char spacer[5];
sprintf(spacer, " ");
if(Vread > 10){
sprintf(spacer, " ");
if(Vread > 100){
sprintf(spacer, " ");
if(Vread > 1000){
sprintf(spacer, "");
}
}
}
sprintf(ac_sample_char, "%02d %s - CT1:%01d CT2:%01d E1:%01d E2:%01d", Vread, spacer , PORTBbits.RB2, PORTBbits.RB3 ,CTMUCONLbits.EDG1STAT, CTMUCONLbits.EDG2STAT);
puts1USART(ac_sample_char);
putrs1USART(" \n\r");
}
void CTMU1 (void){
int Vread;
CTMUCONHbits.CTMUEN = 0;
PIR1bits.ADIF = 0; //make sure A/D Interupt not set
ADCON0bits.GO=1; //and begin A/D conv.
while(!PIR1bits.ADIF); //Wait for A/D convert complete
Vread = ADRES; //Get the value from the A/D
PIR1bits.ADIF = 0; //Clear A/D Interrupt Flag
char ac_sample_char[12];
char spacer[5];
if(Vread > 10){
sprintf(spacer, " ");
if(Vread > 100){
sprintf(spacer, " ");
if(Vread > 1000){
sprintf(spacer, "");
}
}
}
sprintf(ac_sample_char, "%02d %s - CT1:%01d CT2:%01d E1:%01d E2:%01d", Vread, spacer , PORTBbits.RB2, PORTBbits.RB3 ,CTMUCONLbits.EDG1STAT, CTMUCONLbits.EDG2STAT);
puts1USART(ac_sample_char);
putrs1USART(" \n\r");
CTMUCONHbits.IDISSEN = 1; //drain charge on the circuit
__delay_us(1);
CTMUCONHbits.IDISSEN = 0; //end drain of circuit
CTMUCONL = 0b11011100;
CTMUCONHbits.CTMUEN = 1;
}
void CurrentCalibration (void){
int i;
int j = 0; //index for loop
int Vread = 0;
double VTot = 0;
double Vavg=0, Vcal=0, CTMUISrc = 0;
CTMUCONHbits.CTMUEN = 1; //Enable the CTMU
CTMUCONHbits.IDISSEN = 1; //drain charge on the circuit
__delay_ms(1); //wait 125us
CTMUCONHbits.IDISSEN = 0; //end drain of circuit
CTMUCONLbits.EDG1STAT = 1; //Begin charging the circuit
for(j=0;j<10;j++)
{
delayMsx(100); //wait for 125us
PIR1bits.ADIF = 0; //make sure A/D Interupt not set
ADCON0bits.GO=1; //and begin A/D conv.
while(!PIR1bits.ADIF); //Wait for A/D convert complete
Vread = ADRES; //Get the value from the A/D
PIR1bits.ADIF = 0; //Clear A/D Interrupt Flag
VTot = VTot + Vread; //Add the reading to the total
}
CTMUCONLbits.EDG1STAT = 0; //Stop charging circuit
CTMUCONHbits.CTMUEN = 0; //Enable the CTMU
Vavg = (double)(VTot/10); //Average of 10 readings
Vcal = 0.0004882812;
Vcal = (double)Vcal*Vavg;
CTMUISrc = (double)Vcal/RCAL; //CTMUISrc is in 1/100ths of uA
CTMUISrc = CTMUISrc*1000000; // current in uA
char ac_sample_char[12];
sprintf(ac_sample_char, "%0.1f Vavg : %0.3f Voltage : %0.2f CTMUISrc ", Vavg,Vcal,CTMUISrc );
puts1USART(ac_sample_char);
putrs1USART(" \n\r");
}
void CapacitanceCalibration (void){
int i;
int j = 0; //index for loop
int Vread = 0;
float CTMUISrc, CTMUCap, Vavg, VTot, Vcal;
//assume CTMU and A/D have been setup correctly
//see Example 25-1 for CTMU & A/D setup
CTMUCONHbits.CTMUEN = 1; //Enable the CTMU
for(j=0;j<10;j++)
{
CTMUCONHbits.IDISSEN = 1; //drain charge on the circuit
delayUsx(125); //wait 125us
CTMUCONHbits.IDISSEN = 0; //end drain of circuit
CTMUCONLbits.EDG1STAT = 1; //Begin charging the circuit
//using CTMU current source
delayUsx(12); //wait 125us
CTMUCONLbits.EDG1STAT = 0; //Stop charging circuit
PIR1bits.ADIF = 0; //make sure A/D Int not set
ADCON0bits.GO=1; //and begin A/D conv.
while(!PIR1bits.ADIF); //Wait for A/D convert complete
Vread = ADRES; //Get the value from the A/D
PIR1bits.ADIF = 0; //Clear A/D Interrupt Flag
VTot += Vread; //Add the reading to the total
}
Vavg = (double)(VTot/10.000); //Average of 10 readings
Vcal = 0.0004882812;
Vcal = (double)Vcal*Vavg;
CTMUISrc = 0.28; //CTMUISrc is in 1/100ths of uA
CTMUCap = (double)(CTMUISrc*12/Vcal);
char ac_sample_char[12];
sprintf(ac_sample_char, "%0.1f Vavg : %0.3f Voltage : %0.2f CTMUCap ", Vavg,Vcal,CTMUCap );
puts1USART(ac_sample_char);
putrs1USART(" \n\r");
}
void interrupt isr(void)
{
if (PIR3bits.CTMUIF) { // the current source has been on and then turned off by the edge detect inputs
int Vread;
ADCON0bits.GO=1; // and begin A/D conv, will set adc int flag when done.
PIR3bits.CTMUIF=0; // clear CTMU interrupt flag
PIR1bits.ADIF = 0; //make sure A/D Interupt not set
ADCON0bits.GO=1; //and begin A/D conv.
while(!PIR1bits.ADIF); //Wait for A/D convert complete
Vread = ADRES; //Get the value from the A/D
PIR1bits.ADIF = 0; //Clear A/D Interrupt Flag
char ac_sample_char[12];
char spacer[5];
if(Vread > 10){
sprintf(spacer, " ");
if(Vread > 100){
sprintf(spacer, " ");
if(Vread > 1000){
sprintf(spacer, "");
}
}
}
sprintf(ac_sample_char, "%02d %s - CT1:%01d CT2:%01d E1:%01d E2:%01d", Vread, spacer , PORTBbits.RB2, PORTBbits.RB3 ,CTMUCONLbits.EDG1STAT, CTMUCONLbits.EDG2STAT);
puts1USART(ac_sample_char);
putrs1USART(" \n\r");
}
}
void adcwait(void)
{
int count = 0;
if (count > 100){
CTMUCONHbits.CTMUEN = 0;
}
char ac_sample_char[12];
int Vread;
if(PIR1bits.ADIF){
CTMUCONHbits.CTMUEN = 0;
CTMUCONL = 0b11011100;
Vread = ADRES; //Get the value from the A/D
PIR1bits.ADIF = 0; //Clear A/D Interrupt Flag
char ac_sample_char[12];
char spacer[5];
if(Vread > 10){
sprintf(spacer, " ");
if(Vread > 100){
sprintf(spacer, " ");
if(Vread > 1000){
sprintf(spacer, "");
}
}
}
sprintf(ac_sample_char, "%02d %s - CT1:%01d CT2:%01d E1:%01d E2:%01d", Vread, spacer , PORTBbits.RB2, PORTBbits.RB3 ,CTMUCONLbits.EDG1STAT, CTMUCONLbits.EDG2STAT);
puts1USART(ac_sample_char);
putrs1USART(" \n\r");
CTMUCONHbits.IDISSEN = 1; //drain charge on the circuit
__delay_us(1);
CTMUCONHbits.IDISSEN = 0; //end drain of circuit
PIR1bits.ADIF = 0;
}
CTMUCONL = 0b11011100;
CTMUCONHbits.CTMUEN = 1;
//PIR1bits.ADIF = 0;
}
/*******************************************/
void main(void) {
OscillatorConfig();
IO_ports_init();
USART_init();
ADCConfig();
CTMUInit();
BAUDCON1bits.BRG16 = 1;
Open1USART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_CONT_RX & USART_BRGH_HIGH, 68); //103 for 16 mhz 51 for 8mhz
RCONbits.IPEN = 1;
INTCONbits.GIEL = 0;
INTCONbits.GIEH = 1;
CTMUCONHbits.CTMUEN = 1;
putrs1USART("Starting \n\r");
while(1)
{
// putrs1USART("Doing measurement: ");
CTMU();
delayMsx(1000);
LEDs = 0;
// adcwait();
}
}