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.

PIC24 PWM Input read

Status
Not open for further replies.
I initially set TRISB bits (12, 13, 14 and 15) to '0' and it didnt work so I removed it completely. Later when I got your response about looking at the section 14.12 then again I want to try it. as you mentioned 0 is output and 1 is input. TRIS is used to set output. LAT is to set high or low. I set LAT as 0 which is low. So I didnt bother about setting TRIS as input or output as any how the pin is low.
Firstly, don't guess these things. The data sheet states very clearly what each of the PORT, LAT and TRIS registers do (as well as the various analog/digital registers where appropriate). TRIS (short for tri-state) selects whether the pin is used for input (tri-state of the output drivers) or output (the output drivers control the pin state). PORT is used to read the status of the pin (except in analog mode when it will always read 0). The LAT register is used to set the value of the pin when it is in output mode.
Because the power-on defaults are for all TRIS registers to be input, unless you set a pin for output then the LAT register setting is ignored.
If you see my code I started with the following initialisation
void initPWM(void){

}
That is a function definition and the call to that function in the 'main()' function is commented out. Further the function definition is empty so, even if you did call it, nothing would happen.
However, on each call to he (badly named) 'initPWM1()' and 'initPWM2()' funciotns, you go through the complete initialisation sequence.
Initially I started with "xc.h" and it throwed an error while compiling saying it cant find the path. hence I added the complete path.
Again, if you get an error while doing something that the documentation tells you to do, then you have some other problem that needs to be sorted out.
However, you do have some code modules that (apparently) compile successfully with just the '<xc.h>'. Are you compiling the ones that give you an error differently to those that work? If so, that may well be the source of your problem.
All I am trying to do here is to disable any one signal of the complementary PWM . wither high or low. But yes I am trying to turn off all outputs because just to see if I can do it. Sorry I am totally vexed of trying this again and again.
Please show us the code that exhibits your problem. We also get 'vexed' trying to help you when we are shown the wrong code.
So - when you leave out that code to disable the outputs do you get the waveforms from the PWM?
And when you put in the code to disable one of the pins, does it stop and the other one continue?
Initially I started with learning PIC24HJ and I find dspic33 is bit difficult and advanced in terms of learning ADC and PWM. So I used PIC24F as a base and developing from it.
So what MCU have you defined in the IDE and therefore are compiling this code for? (And please provide the full device name.)
This information is critical as there can be subtle (and not so subtle) differences families of devices (and even within a family).
Now I have 3 ADC's working, UART working, PWM working and when I vary the potentiometer I can see my PWM duty cycle varies.
So all of the code you have shown us (above) is actually working. Great news but I think that is the first time you have told us this.
the following first three line is always like the below.

"Potentiometer Value = 0.00
Onboard Temperature Value = -20.51
Sensor Value = 0"

when do I get -20.5 when my actual,onbaord temp is 21.85 ?

am I doing anything wrong with initialising ADC ?
And now we get to a new problem!
Lets look at your code to calculate the onboard temperature value
Code:
TempVal = readTempADC(); //Read onboard Temp value

//Onboard temperature measurement (MCP9701A)
TempADC = (TempVal * 4.8875)/1000; //10-bit to voltage
Temperature = (TempADC - 0.4)/0.0195; //to calculate the temperature
printf("Onboard Temperature Value = %.2f", Temperature);
Firstly I would try to set a breakpoint after you read 'readTempADC()' and see what value you ACTUALLY have in 'TempVal'.
But working backwards through your calcuations, if 'Temperature' is -20.5, then 'TempADC' = ('Temperature' * 0.0195) + 0.4 and substituting in we get (-20.5*0.0195)-0.4 = 0.4-0.4 = 0
So 'tempADC' starts off at 0.
That also means that 'TempVal' will be 0.
Therefore you must have read a value of 0 from 'readTempADC()'!
[Side issue: I note that you divide by 0.0195: floating pint division can be quite an 'expensive' operation on these devices and so it is better to perform floating point multiplications where possible (and even better if you can keep thing as integer so the hardware multiply/device hardware can be used). Therefore it is better to multiply by 51.282 than divide by 0.0195.
Taking this further, if you put everything into a single equation from 'TempVal' to 'Temperature' you get "Temperature = ((tempVal*4.8875/1000) - 0.4) * 51.282". Expanding out you get
"Temperature = TempVal * 4.8875 * 51.282/1000 - 0.4 * 51.282 = TempVal * 0.25 - 20.5128. Now as TempVal is an integer, we can re-write this as "TempVal/4 - 20.5128" which means that we use the integer division hardware for the division, once integer to floating point conversion and then a floating point subtraction. (If you want to you can go further and note that division by 4 is shift-right by 2 bits for '(tempVal>>2)' is the same thing but even faster. I'd not recommend going that far in this case - you already have a 1 second delay in the main loop so you can't be worried bout the time the calculation takes.)]
As this only happens the first time, you need to look at how you initialise the ADC for that channel and what is different the 2nd time around. Again the debugger will help you greatly here.
By the way, this is classic debugging and fault-finding.
Susan
 

Hi Aussie,

I implemented some of your above comments like avoiding division and use multiplication.

Also for the temperature readings where I said I am getting 0, I have used a for loop to get 50 values and take the 49th value so that when I print I will get the temperature value and not 0.

Now I have 2 complementary PWM working, 4 X ADC working .

Now I am trying to do input capture to get the duty cycle for my input PWM 250Hz.

Can you please have a look at my code where I have initialised IC1 and timer 3 for input capture.

I have build it with no errors.

I try to print my values but I get only 0

Code:
/**********************************************************************
 * © AVID Technology
 *
 * FileName:        Prototype
 * Dependencies:    dsPIC33EV256GM106.h
 * Processor:       DSPIC33EV
 * Compiler:        MPLAB® XC16 
 **~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * ADDITIONAL NOTES:  
 *
 * Program to read the sensor values of temperature, inductive sensor and input 
 * PWM and run the brushed DC motor using two H bridge 
 * 
 * //Pins used on dsPIC33EV256GM106
 * 
 * On board Potentiometer - AN19/RG6
 * On board Temperature Sensor - AN18/RG7
 * External Inductive Sensor - AN3/RB1
 * Current Sensor  - AN0/RA0
 * UART_TX - RC0
 * Digital Output for Potentiometer - AN17/RG8
 * PWM1H2 - RB12
 * PWM1L2 - RB13
 * PWM1H1 - RB14
 * PWM1L1 - RB15
 * Digital Output for motor control - RB2
 * Digital Output for motor control - RB3
 * Digital Output for motor control - RB4
 * Digital Output for motor control - RB7
 *********************************************************************/
#include "xc.h"                                                                 /* generic header for PIC24H family */
#include "CONU2.h"                                                              //UART header
#include "adc.h"                                                                //ADC header  
#include "PWM.h"                                                                //PWM header
#include "Motor_Ctrl.h"                                                         //Motor Control header
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "math.h"
#include "stdio.h"
#define FCY 7370000/2
#include <libpic30.h>                                                           //delay header

#pragma config FNOSC = FRC
#pragma config FWDTEN = OFF
#pragma config ICS = PGD2
#pragma config POSCMD = NONE
#pragma config OSCIOFNC = ON
#pragma config FCKSM = CSDCMD
//_FOSCSEL(FNOSC_FRC);                                                            // set oscillator mode for FRC ~ 8 Mhz
//_FOSC(FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_NONE);                                // use OSCIO pin for RA3
//_FWDT(FWDTEN_OFF);                                                              // turn off watchdog
//_FICD(ICS_PGD2);

//***************************************************

static char rxchar = '0';                                                       //received character
unsigned char got_rx = '0';                                                       //rx char flag
double Temperature = 0;
double SensorADC = 0;
double CurrSenADC = 0;
double PotADC_Low = 0;
double PotADC_High = 0;
char Motor_Direction = '0';
double PotADC = 0;
int j = 0;
double PotValtoPWM = 0;
unsigned int Capture1 = 0;
unsigned int Capture2 = 0;
unsigned int TP = 0;

unsigned short i;
unsigned short capture[4];	// buffer for capture 2 buttons press and release
/********************************* 
    main entry point
 *********************************/
int main(void) 
{
    initU1();                                                                   //Initialise UART2
    initADC();                                                                  //Initialise ADC    
    rxchar = 0;                                                                 
    got_rx = 0;         
    Mot_Stop();                                                                 //Initialise Motor Stop           
    __delay_ms(100);
    _U1RXIP = 4;
    _IPL = 0;
    
    initPWM1_2();
    initPWM2_2();
    PWM1_Duty_2();
    PWM2_Duty_2();
    pwm_in();
    timer3();
    // Hyperterminal Startup Inro Screen
    clrscr();                                                                   //clear hyper terminal screen
    home();     
    
    //Temperature = Temp_Conv();
    
    void __attribute__ ((__interrupt__, no_auto_psv)) _IC1Interrupt(void)
    {
    IFS0bits.IC1IF =  0; 		// Reset respective interrupt flag
    if (i>=4) i = 0; 
    capture[i++]   =  IC1BUF;
    }

        printf("capture1 = %d", capture[0]);
        putU1(0x0a);
        putU1(0x0d);
        printf("capture2 = %d", capture[1]);
        putU1(0x0a);
        putU1(0x0d);
        printf("capture3 = %d", capture[2]);
        putU1(0x0a);
        putU1(0x0d);
        printf("capture4 = %d", capture[3]);
        putU1(0x0a);
        putU1(0x0d);
         __delay_ms(1000);
         while(1){
             
         }
    /*while (1) 
    {        
         
        PotADC = Pot_Conv();
        PotValtoPWM = PotADC * 5896;
        printf("Potentiometer Value = %.2f", PotADC);
        PotADC_Low = PotADC - 0.3;
        PotADC_High = PotADC + 0.3;
        putU1(0x0a);
        putU1(0x0d);
        
        Temperature = Temp_Conv();
        printf("Onboard Temperature Value = %.2f", Temperature);
        putU1(0x0a);
        putU1(0x0d);

        
        SensorADC = Sensor_Conv();
        printf("Sensor Value = %.2f", SensorADC);
        putU1(0x0a);
        putU1(0x0d);
        
        CurrSenADC = CurrSen_Conv();
        printf("Current Sensor Value = %.2f", CurrSenADC);
        putU1(0x0a);
        putU1(0x0d);
        __delay_ms(1000);
        Nop();

        if ((SensorADC >= PotADC_Low) && (SensorADC <= PotADC_High)) 
        {
            Motor_Direction = 'S';
            Mot_RST();
        } 
        else if (PotADC >= SensorADC) 
        {
            Motor_Direction = 'F';
            Mot_RST();
        }
        else if (PotADC <= SensorADC) 
        {
            Motor_Direction = 'R';
            Mot_RST();
        }
        
        else if((Temperature <= -38) || (Temperature >= 138))
        {                  //if on board temperature is <=-38DegC and >=138DegC stop condition is executed
            Motor_Direction = 'S';                                              
            Mot_RST();
        }
        
        else {
            Motor_Direction = 'S';
            Mot_RST();
        }

        switch (Motor_Direction) 
        {
            case 'F':
                
                Mot_For();
                printf("Forward");
                putU1(0x0a);
                putU1(0x0d);
                printf("PotADC_Low = %.2f", PotADC_Low);
                putU1(0x0a);
                putU1(0x0d);
                printf("PotADC_High = %.2f", PotADC_High);
                putU1(0x0a);
                putU1(0x0d);
                
                if ((SensorADC >= PotADC_Low) && (SensorADC <= PotADC_High)) {

                    Mot_Stop();
                    printf("Greater");
                    putU1(0x0a);
                    putU1(0x0d);
                }
                break;
            case 'R':
                
                Mot_Rev();
                printf("Reverse");
                putU1(0x0a);
                putU1(0x0d);
                printf("PotADC_Low = %.2f", PotADC_Low);
                putU1(0x0a);
                putU1(0x0d);
                printf("PotADC_High = %.2f", PotADC_High);
                putU1(0x0a);
                putU1(0x0d);

                if ((SensorADC >= PotADC_Low) && (SensorADC <= PotADC_High)) {

                    Mot_Stop();
                    printf("Lesser");
                    putU1(0x0a);
                    putU1(0x0d);
                }
                break;
            case 'S':

                Mot_Stop();
                printf("Stop");
                putU1(0x0a);
                putU1(0x0d);
                printf("PotADC_Low = %.2f", PotADC_Low);
                putU1(0x0a);
                putU1(0x0d);
                printf("PotADC_High = %.2f", PotADC_High);
                putU1(0x0a);
                putU1(0x0d);
                break;
            default:

                Mot_Stop();
                printf("Error");
                putU1(0x0a);
                putU1(0x0d);
                break;
        }
    }
    __delay_ms(1000);
    printf("Onboard Temperature Value = %.2f", Temperature);
    putU1(0x0a);
    putU1(0x0d);    
    */
    return 0;
}

Code:
#include "xc.h" 
#include "PWM.h"
#define FCY 7370000/2                                                           //FCY = Fosc / 2
#include <libpic30.h>

                                                                                
                                                                                //Complementary PWM Mode, Independent Duty Cycle and Phase, Fixed Primary Period, Edge-Aligned
void initPWM1(void) {                                                           /* Set PWM Period on Primary Time Base */
PTPER = 368.5;                                                                  // PTPER = Fosc / Fpwm * PWM Input clock prescaler - 20Khz                                                                               /* Set Phase Shift */
PHASE1 = 0;                                                                     /* Set Dead Time Values */
DTR1 = 25;                                                                      //DTR = Fosc *(dead time required / PWM input clock prescale)
ALTDTR1 = 25;
IOCON1 = 0xC000;
/* Set PWM Mode to Complementary */
                                                                                /* Set Primary Time Base, Edge-Aligned Mode and Independent Duty Cycles */
PWMCON1 = 0x0000;                                                               /* Configure Faults */
FCLCON1 = 0x0003;                                                               /* 1:1 Prescaler */
PTCON2 = 0x0000;                                                                /* Disable PWM Module */

}

void initPWM2(void) {                                                           /* Set PWM Period on Primary Time Base */
PTPER = 368.5;                                                                  // PTPER = Fosc / Fpwm * PWM Input clock prescaler                                                                               /* Set Phase Shift */
PHASE2 = 100;                                                                   /* Set Dead Time Values */
DTR2 = 2;                                                                       //DTR = Fosc *(dead time required / PWM input clock prescale)
ALTDTR2 = 2;
IOCON2 = 0xC000;
/* Set PWM Mode to Complementary */

PWMCON2 = 0x0000;                                                               /* Configure Faults */
FCLCON2 = 0x0003;                                                               /* 1:1 Prescaler */
PTCON2 = 0x0000;                                                                /* Enable PWM Module */

}


void PWM1_Duty(void)
{
    /* Set Duty Cycles */
    PDC1 = 55.275;                                                              //PDC = (Fosc/Fpwm * PWM i/p clk prescaler) * desired duty cycle value between 0 and 1 - 15%
}

void PWM2_Duty(void)
{
    /* Set Duty Cycles */
    PDC2 = 0;                                                                   //PDC = (Fosc/Fpwm * PWM i/p clk prescaler) * desired duty cycle value between 0 and 1 - 50%
}

void PWM_EN(void)
{
    /* Disable PWM Module */
    PTCON = 0x8000;
}

void PWM_DIS(void)
{
    /* Disable PWM Module */
    PTCON   = 0x0000;
    PTCON2  = 0x0000;
    PTPER   = 0x0000;
    SEVTCMP = 0x0000;
    MDC     = 0x0000;
    CHOP    = 0x0000;
    PWMKEY  = 0x0000;    
}


void initPWM1_1(void) {                                                         /* Set PWM Period on Primary Time Base */
PTPER = 368.5;                                                                  // PTPER = Fosc / Fpwm * PWM Input clock prescaler - 20Khz                                                                               /* Set Phase Shift */
PHASE1 = 100;                                                                   /* Set Dead Time Values */
DTR1 = 2;                                                                       //DTR = Fosc *(dead time required / PWM input clock prescale)
ALTDTR1 = 2;
IOCON1 = 0xC000;
/* Set PWM Mode to Complementary */
                                                                                /* Set Primary Time Base, Edge-Aligned Mode and Independent Duty Cycles */
PWMCON1 = 0x0000;                                                               
FCLCON1 = 0x0003;                                                               /* Configure Faults */
PTCON2 = 0x0000;                                                                /* 1:1 Prescaler */

}

void initPWM2_1(void) {                                                         /* Set PWM Period on Primary Time Base */
PTPER = 368.5;                                                                  // PTPER = Fosc / Fpwm * PWM Input clock prescaler                                                                               /* Set Phase Shift */
PHASE2 = 0;                                                                     /* Set Dead Time Values */
DTR2 = 25;                                                                       //DTR = Fosc *(dead time required / PWM input clock prescale)
ALTDTR2 = 25;
IOCON2 = 0xC000;
/* Set PWM Mode to Complementary */

PWMCON2 = 0x0000;                                                               
FCLCON2 = 0x0003;                                                               /* Configure Faults */
PTCON2 = 0x0000;                                                                /* 1:1 Prescaler */

}


void PWM1_Duty_1(void)
{
    /* Set Duty Cycles */
    PDC1 = 0;                                                                   //PDC = (Fosc/Fpwm * PWM i/p clk prescaler) * desired duty cycle value between 0 and 1 - 50%
}

void PWM2_Duty_1(void)
{
    /* Set Duty Cycles */
    PDC2 = 55.275;                                                              //PDC = (Fosc/Fpwm * PWM i/p clk prescaler) * desired duty cycle value between 0 and 1 - 15%
}


void initPWM1_2(void) {                                                         /* Set PWM Period on Primary Time Base */
PTPER = 368.5;                                                                  // PTPER = Fosc / Fpwm * PWM Input clock prescaler - 20Khz                                                                               /* Set Phase Shift */
PHASE1 = 100;                                                                   /* Set Dead Time Values */
DTR1 = 2;                                                                       //DTR = Fosc *(dead time required / PWM input clock prescale)
ALTDTR1 = 2;
IOCON1 = 0xC000;
/* Set PWM Mode to Complementary */
                                                                                /* Set Primary Time Base, Edge-Aligned Mode and Independent Duty Cycles */
PWMCON1 = 0x0000;                                                               
FCLCON1 = 0x0003;                                                               /* Configure Faults */
PTCON2 = 0x0000;                                                                /* 1:1 Prescaler */

}

void initPWM2_2(void) {                                                         /* Set PWM Period on Primary Time Base */
PTPER = 368.5;                                                                  // PTPER = Fosc / Fpwm * PWM Input clock prescaler                                                                               /* Set Phase Shift */
PHASE2 = 0;                                                                     /* Set Dead Time Values */
DTR2 = 25;                                                                       //DTR = Fosc *(dead time required / PWM input clock prescale)
ALTDTR2 = 25;
IOCON2 = 0xC000;
/* Set PWM Mode to Complementary */

PWMCON2 = 0x0000;                                                               
FCLCON2 = 0x0003;                                                               /* Configure Faults */
PTCON2 = 0x0000;                                                                /* 1:1 Prescaler */

}


void PWM1_Duty_2(void)
{
    /* Set Duty Cycles */
    PDC1 = 0;                                                                   //PDC = (Fosc/Fpwm * PWM i/p clk prescaler) * desired duty cycle value between 0 and 1 - 50%
}

void PWM2_Duty_2(void)
{
    /* Set Duty Cycles */
    PDC2 = 0;                                                                   //PDC = (Fosc/Fpwm * PWM i/p clk prescaler) * desired duty cycle value between 0 and 1 - 50%
}

void pwm_in(void){
   
    ANSELAbits.ANSA1 = 0;                                                       //Set UART RC0 to digital
    TRISAbits.TRISA1 = 1;
    LATAbits.LATA1 = 1;
    RPINR7bits.IC1R = 17;
    
    IFS0bits.IC1IF = 0;                                                             // Clear the IC1 interrupt status flag
    IEC0bits.IC1IE = 1;                                                         // Enable IC1 interrupts
    IPC0bits.IC1IP = 1;                                                         // Set module interrupt priority as 1
    
    IC1CON1bits.ICSIDL = 0;                                                     // Input capture will continue to operate in CPU idle mode
    IC1CON1bits.ICTSEL = 0;                                                     // T3CLK is the clock source
    IC1CON1bits.ICI = 0;                                                        // Interrupt on every capture event
    IC1CON1bits.ICBNE = 0;                                                      // Input capture is empty
    IC1CON1bits.ICM = 0b011;                                                    // Capture mode; every rising edge (Prescaler Capture mode)
    
    IC1CON2bits.IC32 = 0;                                                       // Cascade module operation is disabled
    IC1CON2bits.ICTRIG = 0;                                                     // Input source used to synchronize the input capture timer of
                                                                                // another module (Synchronization mode)
    IC1CON2bits.TRIGSTAT = 0;                                                   // IC1TMR has not been triggered and is being held clear
    IC1CON2bits.SYNCSEL = 0; 
}

void timer3 (void){
    /*T1CONbits.TON = 0;                                                           // Disable Timer
    T1CONbits.TCS = 0;                                                          // Select internal instruction cycle clock
    T1CONbits.TGATE = 0;                                                        // Disable Gated Timer mode
    T1CONbits.TCKPS = 0b011;                                                    // Select 1:256 Prescaler
    TMR1 = 0x00;                                                                // Clear timer register
    PR1 = 24999;                                                                    // Load the period value
    IPC0bits.T1IP = 0x01;                                                       // Set Timer 1 Interrupt Priority Level
    IFS0bits.T1IF = 0;                                                          // Clear Timer 1 Interrupt Flag
    IEC0bits.T1IE = 1;                                                          // Enable Timer1 interrupt
    T1CONbits.TON = 1;                                                          // Start Timer */
    
    T3CON = 0x8030;                                                             // 1:256 internal clock, start T3.
}






I did my code using the example code below and I got it from microchip website sample code simple input capture
Code:
/**********************************************************************
* ?2007 Microchip Technology Inc.
*
* FileName:        Simple Input Capture.c
* Dependencies:    Header (.h) files if applicable, see below
* Processor:       PIC24Fxxxx
* Compiler:        MPLAB?C30 v3.00 or higher
*
* SOFTWARE LICENSE AGREEMENT:
* Microchip Technology Incorporated ("Microchip") retains all 
* ownership and intellectual property rights in the code accompanying
* this message and in all derivatives hereto.  You may use this code,
* and any derivatives created by any person or entity by or on your 
* behalf, exclusively with Microchip's proprietary products.  Your 
* acceptance and/or use of this code constitutes agreement to the 
* terms and conditions of this notice.
*
* CODE ACCOMPANYING THIS MESSAGE IS SUPPLIED BY MICROCHIP "AS IS". NO 
* WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT 
* NOT LIMITED TO, IMPLIED WARRANTIES OF NON-INFRINGEMENT, 
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS 
* CODE, ITS INTERACTION WITH MICROCHIP'S PRODUCTS, COMBINATION WITH 
* ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. 
*
* YOU ACKNOWLEDGE AND AGREE THAT, IN NO EVENT, SHALL MICROCHIP BE 
* LIABLE, WHETHER IN CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE OR
* BREACH OF STATUTORY DUTY), STRICT LIABILITY, INDEMNITY, 
* CONTRIBUTION, OR OTHERWISE, FOR ANY INDIRECT, SPECIAL, PUNITIVE, 
* EXEMPLARY, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, FOR COST OR 
* EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE CODE, HOWSOEVER 
* CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE
* DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT ALLOWABLE BY LAW, 
* MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS
* CODE, SHALL NOT EXCEED THE PRICE YOU PAID DIRECTLY TO MICROCHIP 
* SPECIFICALLY TO HAVE THIS CODE DEVELOPED.
*
* You agree that you are solely responsible for testing the code and 
* determining its suitability.  Microchip has no obligation to modify,
* test, certify, or support the code.
*
* REVISION HISTORY:
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Author        Date      	Comments on this revision
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Albert Z.		6/9/09		first release
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* ADDITIONAL NOTES:
* 
* Code Tested on:
* 16-bit 28-pin demo board with PIC24FJ64GA002.  
* The Processor starts with the 7.3728MHz External Crystal, Tcy = 69.44uS.
*
**********************************************************************/

#include "p24fxxxx.h"

#ifdef __PIC24FJ64GA002__	//Defined by MPLAB when using 24FJ64GA002 device
	_CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx1) 
	_CONFIG2( FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMOD_HS & FNOSC_PRI & I2C1SEL_SEC & IOL1WAY_ON)
#endif


unsigned short i;
unsigned short capture[4];	// buffer for capture 2 buttons press and release


int main (void)
{
	
// Disable Watch Dog Timer
	RCONbits.SWDTEN = 0;

#ifdef __PIC24FJ64GA002__
	// Unlock Registers
	__builtin_write_OSCCONL(OSCCON & 0xbf);
	// Configure Input Functions **********************
	// IC1 = RP5
	RPINR7bits.IC1R = 5;
	// Lock Registers
	__builtin_write_OSCCONL(OSCCON | 0x40);
#endif
	
	T3CON	= 0x8030;		// 1:256 internal clock, start T3. 
	
// The following code example will set the Input Capture 1 module
// for interrupts on every second capture event, capture on every
// fourth rising edge and select Timer 2 as the time-base.This
// code example clears IC1CON to avoid unexpected interrupts.
	IPC0bits.IC1IP  =  1; 			// Setup Input Capture 1 interrupt for desired priority
	// level (this example assigns level 1 priority)
	IFS0bits.IC1IF 		= 0; 		// Clear the IC1 interrupt status flag
	IEC0bits.IC1IE 		= 1; 		// Enable IC1 interrupts
	IC1CON         		= 0x0000;	// Turn off Input Capture 1 Module
	IC1CONbits.ICSIDL	= 0;		// Input capture module will continue to operate in CPU Idle mode
	IC1CONbits.ICTMR	= 0;		// TMR3 contents are captured on capture event
	IC1CONbits.ICI		= 0;		// Interrupt on every capture event
	IC1CONbits.ICM		= 1;		// Capture mode, every edge (rising and falling)
	
	while (1) {
	    ;
	} 

	return 0;
}


// The following code shows how to read the capture buffer when
// an interrupt is generated. 
// Example code for Input Capture 1 ISR:
void __attribute__ ((__interrupt__, no_auto_psv)) _IC1Interrupt(void)
{
   IFS0bits.IC1IF =  0; 		// Reset respective interrupt flag
   if (i>=4) i = 0; 
   capture[i++]   =  IC1BUF;	// Read and save off the capture entry
   
   // Please watch the capture value, you can get the pulse as capture[1] - capture[0]. 
}
 

Move the IC1 ISR out of the main function - it should be at the top level of your code. I'm surprised that the XC16 compiler didn't flag this as at least a warning.
Don't play with the IPL - the hardware to perfectly capable of doing the right thing with this and you can only get in the way (unless you *really* know what you are doing).
Also (not quite as bad) but I have only ever come across 1 case in my experience where I needed to play with the interrupt priorities - the default is fine, especially in this case.
You set the IE bit for Timer1 (in the strangely named 'Timer3' function) but I can't see an ISR defined. If an interrupt is triggered when no ISR has been written, then the MCU will reset.
Don't bother trying to clear the ICBNE bit - it is read-only. (Check the data sheet and you will see these things clearly specified.)
The IC ISR is set to be triggered on each capture event and you then count use the ISR to save the captures in a 4 element array. Why not set the ISR to be triggered every 4th event and then read all 4 samples from the FIFO.
You use the variable 'i' in the ISR. As it would appear that you only ever use this variable in the ISR then you can get away with not declaring it volatile. However you write to the 'capture' array in the ISR and reference it within the main function. There it must be declared as volatile. If you don't then the compiler will only look at the code in the main function to determine where values are being updated and so is perfectly correct to generate code that reads the from the 'capture' array once, puts the value int a register somewhere and never looks at the array value again. Declaring the array volatile will stop that.
However, I suspect the real problem is that you only ever execute your sequence of print functions (and the 1 second delay) once before you execute your while loop. It could well be that the IC module has not had a chance to detect anything by that time. Try putting the sequence of print instructions inside the while loop
I must say that some of the above are really basic programming design errors and again indicate that you are simply copying code from all over the place without understanding what that code actually does. Slow down, read the data sheets, by all means look at other code but understand how it works and then implement your own code (translated for the actual MCU you are using).
Also use a debugger - it would have shown you immediately that you only ever pass through the print sequence once. You could have set a breakpoint in the IC ISR and looked at the values that were being captured to make sure that this part is working OK.
Susan
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top