Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Need help with input capture using DSPIC

Status
Not open for further replies.

angeline

Newbie level 5
Joined
Mar 4, 2008
Messages
9
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,354
dspic input capture

I am a new user using DSPIC30F3010. I am trying to use the input capture module to capture the period of squarewave using the MPLAB IDE to do my programming. I am using the ICD2 to view the result of my register which is IC7BUF. I am not getting any changes in the buffer , however I put an LED to make sure my code enter the input capture interrupt and it shows me yes. Hope can get some advice .

Code:
# include <p30f3010.h>
# include <math.h>
# include <stdio.h>

#define LED 	LATDbits.LATD0 

/*************Global Variables and Constants*************/
unsigned int period= 0, captureresult1 = 0 , captureresult2= 0;															/*Variables used for period calculation*/

void __attribute__((__interrupt__)) _IC7Interrupt(void); 

/****FUNCTION PROTOTYPES****/
void IC_SETUP(void);
void TIMER2_SETUP (void);

/******MAIN BODY******/
int main (void)
{
TRISD=0;                  /*Setting Port D as output*/
PORTD=0;                  /*Reset The LED*/
PORTD=0xff;				  /*Light The LED, to test the PIC is working*/
TRISB=0x003f; 				  /*Setting PortB as input*/
ADPCFG=0xffff;				/*Setting the analogue pin as digital input*/


TIMER2_SETUP();             /*Calling the Timer Setup Function*/
IC_SETUP();				  /*Calling the Input Capture Setup Function*/
while(1)
{
}

		return (0);
}
/***SETUP_IC****/
void IC_SETUP (void)
{
IC7CONbits.ICM=3;		/*Capture every rising edge*/
IC7CONbits.ICBNE=0;		/*Input capture buffer is empty*/
IC7CONbits.ICOV=0;		/*No input capture overflow occured*/
IC7CONbits.ICI=0;		/*Interrupt on every capture event*/
IC7CONbits.ICTMR=1;		/*TMR2 contents are captured on captured event*/
IC7CONbits.ICSIDL=0;    /*Input capture module will continue to operate in CPU Idle mode*/
IFS1bits.IC7IF = 0;       /*Interrupt bit is cleared*/
IEC1bits.IC7IE = 1;     /*Set the IC7 interrupt enable bit */

}

/****INTERRUPT FOR IC7****/
void __attribute__((__interrupt__)) _IC7Interrupt(void) 
{
volatile unsigned int *ptr; 

ptr =&IC7BUF;             /*Initialise IC7BUF pointer*/
captureresult1= *ptr;	
captureresult2= *ptr++;
	LED =~ LED;
	
	captureresult1 = IC7BUF;

	period = captureresult2-captureresult1;
/*IFS1bits.IC7IF = 0;       /*Interrupt bit is cleared*/
}

/***TIMER_SETUP***/
void TIMER2_SETUP (void)
{
T2CONbits.TCS=1; 			/*Using Internal Clock (Fosc/4)*/
T2CONbits.T32=1;			/*TMRx and TMRy form a 32-bit timer*/
T2CONbits.TCKPS=0;  		/*Using 1:1 prescale value*/
T2CONbits.TGATE=0;			/*Timer Gate Accumulation Disabled*/
T2CONbits.TSIDL=0;			/*Continue in Idle Mode*/
T2CONbits.TON=1;			/*Starts Timer*/
}



		}

Thank you
 

input capture dspic

the buffers should not be read via ICD2. you need to examine your variables - do they change or are alwaysl 0? the buffers usualy show 0 in ICD2. that is a hardware limitation i suppose. probably you'd lost the contents of the buffer if ICD2 would read that.

another thing - why use 32bit timers? that setting can make things messy - switch that off!

T2CONbits.T32=0; /*TMRx and TMRy form a 32-bit timer*/

another one - that thing you do with the pointers in ISR is... crazy... [; it will definetely do something you didn't intended... the ICbuffer is a FIFO, but you cannot access different elements with pointers - you just read sequentially... that's all...

here is an example from dspic33 datasheet:

Code:
// Initialize Capture Module
IC1CONbits.ICM= 0b00; // Disable Input Capture 1 module
IC1CONbits.ICTMR= 1; // Select Timer2 as the IC1 Time base
IC1CONbits.ICI= 0b00; // Interrupt on every second capture event
IC1CONbits.ICM= 0b001; // Generate capture event on every Rising edge
// Enable Capture Interrupt And Timer2
IPC0bits.IC1IP = 1; // Setup IC1 interrupt priority level
IFS0bits.IC1IF = 0; // Clear IC1 Interrupt Status Flag
IEC0bits.IC1IE = 1; // Enable IC1 interrupt
// Capture Interrupt Service Routine
unsigned int timePeriod= 0;
void __attribute__((__interrupt__)) _IC1Interrupt(void)
{
unsigned int t1,t2;
t2=IC1BUF;
t1=IC1BUF;
IFS0bits.IC1IF=0;
if(t2>t1)
timePeriod = t2-t1;
else
timePeriod = (PR2 - t1) + t2
}

notice the method of reading the contents of the buffer and the method of period calculation.

0x41 0x56 0x45!!
 

input capture dspic33f

Thanks Freddie Choppin.

I have tried to remove the pointer and now when i use the debug mode I am able to get the result under both IC7 and IC8 that I am using as well as TMR2 and TMR3 register. However, my declared variable as shown in the code below , example,current_value,previous_value_new_value,when I view it through debugger watch window it says restricted memory . MAy I know why ?

Below is my code :

Code:
/*************Global Variables and Constants*************/
/*Variables used for period calculation*/
unsigned int timePeriod= 0; 
unsigned int current_value=0,previous_value=0;
unsigned int new_value=0;

void __attribute__((__interrupt__)) _IC7Interrupt(void); 
void __attribute__((__interrupt__)) _IC8Interrupt(void); 
void __attribute__((__interrupt__, __shadow__)) _T2Interrupt(void);
void __attribute__((__interrupt__, __shadow__)) _T3Interrupt(void);

/****FUNCTION PROTOTYPES****/
void IC7_SETUP(void);
void IC8_SETUP (void)
void TIMER2_SETUP (void);
void TIMER3_SETUP (void);

/******MAIN BODY******/
int main (void)
{
TRISD=0;                  /*Setting Port D as output*/
PORTD=0;                  /*Reset The LED*/
PORTD=0xff;				  /*Light The LED, to test the PIC is working*/
TRISB=0x003f; 				  /*Setting PortB as input*/
ADPCFG=0xffff;				/*Setting the analogue pin as digital input*/


TIMER2_SETUP();             /*Calling the Timer Setup Function*/
TIMER3_SETUP();
IC7_SETUP();				  /*Calling the Input Setup Function*/
IC8_SETUP();


while(1)
{
}
return (0);
}
/***SETUP_IC****/
void IC7_SETUP (void)
{
IC7CONbits.ICM=3;		/*Capture every rising edge*/
IC7CONbits.ICBNE=0;		/*Input capture buffer is empty*/
IC7CONbits.ICOV=0;		/*No input capture overflow occured*/
IC7CONbits.ICI=0;		/*Interrupt on every capture event*/
IC7CONbits.ICTMR=1;		/*TMR2 contents are captured on captured event*/
IC7CONbits.ICSIDL=0;    /*Input capture module will continue to operate in CPU Idle mode*/
IFS1bits.IC7IF = 0;       /*Interrupt bit is cleared*/
IEC1bits.IC7IE = 1;     /*Set the IC7 interrupt enable bit */
}

void IC8_SETUP (void)
{
IC8CONbits.ICM=3;		/*Capture every rising edge*/
IC8CONbits.ICBNE=0;		/*Input capture buffer is empty*/
IC8CONbits.ICOV=0;		/*No input capture overflow occured*/
IC8CONbits.ICI=0;		/*Interrupt on every capture event*/
IC8CONbits.ICTMR=0;		/*TMR3 contents are captured on captured event*/
IC8CONbits.ICSIDL=0;    /*Input capture module will continue to operate in CPU Idle mode*/
IFS1bits.IC8IF = 0;       /*Interrupt bit is cleared*/
IEC1bits.IC8IE = 1;     /*Set the IC7 interrupt enable bit */

}

/****INTERRUPT FOR IC7****/
// Capture Interrupt Service Routine 
//unsigned int timePeriod= 0; 
void __attribute__((__interrupt__)) _IC7Interrupt(void) 
{ 
previous_value=current_value;
current_value=IC7BUF;
if(current_value>previous_value)
{ 
timePeriod = current_value-previous_value; 
}
else
{ 
timePeriod = (PR2 - previous_value) + current_value ;
} 
 }

/****INTERRUPT FOR IC8****/
// Capture Interrupt Service Routine 
//unsigned int timePeriod= 0; 
void __attribute__((__interrupt__)) _IC8Interrupt(void) 
{ 
new_value=IC8BUF;
IFS1bits.IC8IF=0; 
}

/***TIMER_SETUP***/
void TIMER2_SETUP (void)
{
//T2CON = 0x00; //Stops the Timer2 and reset control reg.
T2CONbits.TCS=1; 			/*Using Internal Clock (Fosc/4)*/
T2CONbits.T32=0;			/*TMRx and TMRy form a 16-bit timer*/
T2CONbits.TCKPS=0;  		/*Using 1:1 prescale value*/
T2CONbits.TGATE=0;			/*Timer Gate Accumulation Disabled*/
T2CONbits.TSIDL=0;			/*Continue in Idle Mode*/
T2CON = 0x00; //Stops the Timer2 and reset control reg.
TMR2 = 0x00; //Clear contents of the timer register
PR2 = 0xFFFF; //Load the Period register with the value 0xFFFF
//IPC0bits.T2IP = 0x01; //Setup Timer2 interrupt for desired priority leve
// (This example assigns level 1 priority)
IFS0bits.T2IF = 0; //Clear the Timer1 interrupt status flag
IEC0bits.T2IE = 1; //Enable Timer1 interrupts
T2CONbits.TON = 1; //Start Timer1 with prescaler settings at 1:1 and 
//clock source set to the internal instruction cycle
}

/* Example code for Timer1 ISR*/
void __attribute__((__interrupt__, __shadow__)) _T2Interrupt(void)
{
/* Interrupt Service Routine code goes here         */
IFS0bits.T2IF = 0; //Reset Timer1 interrupt flag and Return from ISR
}

/***TIMER_SETUP***/
void TIMER3_SETUP (void)
{
T3CONbits.TCS=1; 			/*Using Internal Clock (Fosc/4)*/
T3CONbits.TCKPS=0;  		/*Using 1:1 prescale value*/
T3CONbits.TGATE=0;			/*Timer Gate Accumulation Disabled*/
T3CONbits.TSIDL=0;			/*Continue in Idle Mode*/
T3CON = 0x00; //Stops the Timer2 and reset control reg.
TMR3 = 0x00; //Clear contents of the timer register
PR3 = 0xFFFF; //Load the Period register with the value 0xFFFF
//IPC0bits.T2IP = 0x01; //Setup Timer2 interrupt for desired priority leve
// (This example assigns level 1 priority)
IFS0bits.T3IF = 0; //Clear the Timer1 interrupt status flag
IEC0bits.T3IE = 1; //Enable Timer1 interrupts
T3CONbits.TON = 1; //Start Timer1 with prescaler settings at 1:1 and 
//clock source set to the internal instruction cycle
}

/* Example code for Timer1 ISR*/
void __attribute__((__interrupt__, __shadow__)) _T3Interrupt(void)
{
/* Interrupt Service Routine code goes here         */
IFS0bits.T3IF = 0; //Reset Timer1 interrupt flag and Return from ISR
}

If I couldnt view my output of my result in debugger ? Is there any way I can view my output ?

I need to write a maths function as well to calculate (currentvalue/7.6E6 - new_value/7.6E6) / (timeperiod/7.6E6) * 2pi. However I know that the result is in hex form and I need to divide them with floating numbers . I am not sure whether this can be done directly , but I doubt so . HOpe to get some advice . Thanks.

I got to write a maths function to calculate
 

32bit timer dspic

change build mode in mplab from RELEASE to DEBUG. in new versions there is a dropdown menu in the center of top toolbar. in older mplab you need to find some build options and change them to 'build for ICD2'. ICD2 uses first 80b of RAM, that's why you cannot see the variables which were placed there. see the screenshot below (MPLAB v8)

**broken link removed**

you should build in DEBUG mode for debugging, and in RELEASE mode for standalone operation (final code, test without debugger, etc.)

you need to inform Linker directly, that you are using icd2, so that it will put your variables above ICD2 restricted range (0x800 - 0x850).

your results are not in HEX, they are just integers. you can do type casting to convert them to floating point.

Code:
float var_float;
int var_int;

var_int=1234;
var_float=(float)var_int;

however - it is a good thing to avoid floating points, as they are heavy in computation. maybe there is a way to do that with integers (first multiply everything by 7.6E6, than do the math, divide the result...).

you can also check the math.h file - maybe there are some functions for tupe conversion, but probably you won't need any - type casting should be just enough - try googling it to learn more about it.

gl & hf

i hope that I have helped you a bit, as I am also an absolute beginner in dsPICs [;

EDIT:

there is another big mistake in your code:

Code:
T2CONbits.TCS=1;          /*Using Internal Clock (Fosc/4)*/ 
T2CONbits.T32=0;         /*TMRx and TMRy form a 16-bit timer*/ 
T2CONbits.TCKPS=0;        /*Using 1:1 prescale value*/ 
T2CONbits.TGATE=0;         /*Timer Gate Accumulation Disabled*/ 
T2CONbits.TSIDL=0;         /*Continue in Idle Mode*/ 
T2CON = 0x00; //Stops the Timer2 and reset control reg.

notice that you first set or clear some bits in T2CON, and than you clear whole register, which makes your settings pointless - clear the T2CON before (you have that line commented):

Code:
T2CON = 0x00; //Stops the Timer2 and reset control reg.
T2CONbits.TCS=1;          /*Using Internal Clock (Fosc/4)*/ 
T2CONbits.T32=0;         /*TMRx and TMRy form a 16-bit timer*/ 
T2CONbits.TCKPS=0;        /*Using 1:1 prescale value*/ 
T2CONbits.TGATE=0;         /*Timer Gate Accumulation Disabled*/ 
T2CONbits.TSIDL=0;         /*Continue in Idle Mode*/

if you clear the T2CON you don't need to clear every bit than:

Code:
T2CON = 0x00; //Stops the Timer2 and reset control reg.
T2CONbits.TCS=1;          /*Using Internal Clock (Fosc/4)*/ 
// default:
/*TMRx and TMRy form a 16-bit timer*/ 
/*Using 1:1 prescale value*/ 
/*Timer Gate Accumulation Disabled*/ 
/*Continue in Idle Mode*/

the same is valid for your Timer3 initialization code.

EDIT2:

another thing is your clock source selection. datasheet for dspic33 (i use this family, but i suppose that in dspic30 it's the same) says:

bit 1 TCS: Timerx Clock Source Select bit
1 = External clock from TxCK pin
0 = Internal clock (FOSC/2)

and your code:
Code:
T2CONbits.TCS=1;          /*Using Internal Clock (Fosc/4)*/

(dspic33 divides input freq by 2, dspic30 by 4 - don't worry about that, it makes no difference here)

something is wrong here... if the timers work, that's only because you reset T2CON and T3CON registers after setting some bits, so eventually you have TCS=0 for both timers... check that.


0x41 0x56 0x45!!
 

dspic30f input capture module

Thanks again for all your advice and provide me the screen shot ... I ll try to verify my coding error you have mentioned.

I did it in debug mode ... but I dont understand ... How can I tell the linker directly as you have mentioned in your reply ?

haha... ya.. I ll try on the maths operation see how it goes =)
 

dspic input capture problems

by 'directly' i mean changing this field to DEBUG [; , there is also an indirect way - you need to specify a dummy table variable, and locate it under address 0x800. it's size should be 80bytes (40 words). however switching build mode to DEBUG is smarter [;

verify the address of your variables - when using ICD2 no variable should be located below address 0x850

0x41 0x56 0x45!!
 

input capture dspic

thanks again ...

i manage to get already =) i did it all in integer ... cause the accuracy level i nneed its not that high ...so i scale up my reading ...

however my debugger still show resreicted memory ... now i use MPLAB SIM ... and watch it through watch window...

thanks a lot =)
 

t2conbits.t32

hello i have a problem with input capture module but your comments don't help me. the interrupts do not work. These is the part of my code that fails:

void CONFIGcapture(void) {
CloseCapture2();
unsigned int configIC2 = IC_DLE_STOP & IC_TIMER3_SRC & IC_INT_1CAPTURE & IC_EVERY_EDGE;
OpenCapture2(configIC2);
}

void CONFIGtimers(void){
unsigned int configT3 = T3_OFF & T3_IDLE_CON & T3_GATE_OFF &
T3_PS_1_64 & T3_SOURCE_INT;
}

int void (main) {
CONFIGcapture();
CONFIGtimers();
TRISDbits.TRISD9 = 1;
while(1) {

}
return 1;
}


void __attribute__((__interrupt__)) _IC2Interrupt(void){
IFS0bits.IC2IF = 0;
putsUART1("Interrupt");
}



the problem is that "Interrupt" is only write the first time, so, there is no a interrupt
and i can not understand why. any idea?

thank you

Added after 1 minutes:

Sorry i forgot put on the function CONFIGtimer this line:

OpenTimer3(configT3, 0xffff);

Thank you again

Added after 59 seconds:

T3CONbits.TON = 1;
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top