Pic32MX input capture

General discussion on mikroC PRO for PIC32.
Post Reply
Author
Message
ColinI
Posts: 42
Joined: 29 Mar 2017 21:19

Pic32MX input capture

#1 Post by ColinI » 27 Sep 2021 10:18

Hi All,
After much searching and reading of data sheets I have been having a lot of trouble getting input capture to work. This is on the fusion V7 board with a pic32mx795F512L using RD8 (ic1). The actual input signal that will be used is a 30KHz 25% duty cycle square wave but everything from 1 Hz to 150 KHz has been tried. The timers have been tested from 1us to 25 ms with no success. Attempts have been made with both a ISR procedure and simply identifying the interrupt flag and acting upon it. The last attempt was to combine timer2 and 3 for a 32 bit timer and setup the capture to use that but it did not work either. Running the timers without the interrupt enabled was tried but no go.
There are commented procedures which were left in to show some of the testing that has been done.

At the moment it seems the ISR procedure constantly triggers and it's showing small numbers on the screen that do not vary with the input signal. The code is based on many examples found around the net but it seems that something is missing or configured incorrectly and I'm at a loss.

Any help or suggestions are appreciated greatly.
Thanks,
Colin

Code: Select all

/*
 * Project name:
     CaptureTest.mcp32
 * Generated by:
     Visual TFT
 * Date of creation
     2021-09-23
 * Test configuration:
     MCU:             P32MX795F512L
                      http://www.microchip.com/wwwproducts/Devices.aspx?product=PIC32MX795F512L
     Dev.Board:       EasyPIC_Fusion_v7_for_PIC32_9A
     Oscillator:      80000000 Hz
     SW:              mikroC PRO for PIC32
                      http://www.mikroe.com/mikroc/pic32/
 */

#include "CaptureTest_objects.h"

int cap_flag = 0;
unsigned long data1, data2, t3count, t2count;
char txt1[12];
char txt2[12];

//Timer2
//Prescaler 1:16; PR2 Preload = 50000; Actual Interrupt Time = 10 ms
void InitTimer2(){
  T2CON	         = 0x8040;
  //T2CONbits.T32  = 1;
  T2IP0_bit	 = 1;
  T2IP1_bit	 = 1;
  T2IP2_bit	 = 1;
  T2IF_bit	 = 0;
  T2IE_bit	 = 1;
  PR2		 = 50000;
  TMR2		 = 0;
}

void Timer2_interrupt() iv IVT_TIMER_2 ilevel 7 ics ICS_SRS {
  T2IF_bit         = 0;
  t2count++;
  if (t2count == 100) {
     PORTGINV = 0b0000000001000000; // heartbeat on pin G6
     t2count = 0;
  }
}

//Timer3
//Prescaler 1:16; PR3 Preload = 50000; Actual Interrupt Time = 10 ms
void InitTimer3(){
  T3CON	         = 0x8040;
  T3IP0_bit	 = 1;
  T3IP1_bit	 = 1;
  T3IP2_bit	 = 1;
  T3IF_bit	 = 0;
  T3IE_bit	 = 1; //=0; tried both
  PR3		 = 50000;
  TMR3		 = 0;
}

void Timer3_interrupt() iv IVT_TIMER_3 ilevel 7 ics ICS_SRS {
  T3IF_bit         = 0;
  /*t3count++;
  if (t3count == 100) {
     PORTGINV = 0b0000000001000000; // heartbeat on pin G6
     t3count = 0;
  }*/
}

void Init_Capture() { // pin RD8 injecting 30 KHz 3V square wave 25% duty cycle offset 2V

  //IC1CON = 0x8364; // 0b00000000000000001000001101100100; ON/1, 14/0, SIDL/0, 12-10/0, FEDGE/1, C32/1, ICTMR/0, ICI<1:0>/11, ICOV/0, ICBNE/0, ICM<2:0>/100

  IC1CONbits.ICTMR = 0;      // use timer 3
  //IC1CONbits.C32 = 1;
  IC1CONbits.ICM0  = 1;      // capture every 4th rising edge
  IC1CONbits.ICM1  = 0;
  IC1CONbits.ICM2  = 0;
  IC1CONbits.FEDGE = 1;      // capture rising edge
  IC1CONbits.ICI0  = 1;      // interrupt every 4th capture event
  IC1CONbits.ICI1  = 1;
  IEC0bits.IC1IE   = 1;      // enable IC1 interrupt
  IC1CONbits.ON = 1;          // turn IC1 on

}

/*void IMU_interrupt() iv IVT_INPUT_CAPTURE_1 ilevel 7 ics ICS_SRS { // ICS_OFF {

  PORTGINV = 0b0000000010000000;
  cap_flag = 1;
  //IFS0bits.IC1IF = 0;       // clear interrupt flag
  IFS0.IC1IF = 0;
}*/

void main() {

  AD1PCFG = 1;    // digital mode
  
  //CM1CON = 0; // disable Compare module 1
  //CM2CON = 0; // disable Compare module 2

  TRISD = 0b0000000100000000;             // PORTD8 as input
  TRISG = 0b0000000000000000;             // PORTG as output
  LATG = 0b0000000000000000;              // PORTG off
  

  InitTimer2();                       // timers init
  InitTimer3();
  Init_Capture();                    // capture init
  EnableInterrupts();                // Enable interrupts

  Start_TP();

  while (1) {
    //Check_TP();

    while(!IFS0.IC1IF);      // wait for interrupt 

    if(!(!ICBNE_bit))     // if capture buffer is not empty
     {
        IFS0.IC1IF = 0;       // clear interrupt flag
        //PORTGINV = 0b0000000010000000; // some indication on g7 led
        data1 = IC1BUF;            // read value from IC1BUF
     }


    while(!IFS0.IC1IF); //
     if(!(!ICBNE_bit)) //
     {
        IFS0.IC1IF = 0; //
        //PORTGINV = 0b0000000010000000; // some indication on g7 led
        data2 = IC1BUF;
     }

    /*if (cap_flag = 2) {  // alternate method, used with interrupt procedure
      data2 = IC1BUF;
      cap_flag = 0;
    }

    if (cap_flag = 1) {
      data1 = IC1BUF;
      cap_flag = 2;
    }*/

    LongToStr(data1,txt1);
    LongToStr(data2,txt2);
    strcpy(Button1.caption, ltrim(txt1));
    strcpy(Button2.caption, ltrim(txt2));
    DrawButton(&Button1);
    DrawButton(&Button2);
    delay_ms(50);
  }
}
Attachments
CaptureTest.zip
(394.21 KiB) Downloaded 40 times
Windows 7 & 10 64 bit
PIC Clicker, PIC32MX Clicker
EasyPIC Pro v7 with PIC18F87J60, PIC18F87K22
EasyPIC Fusion v7 with PIC32MZ2048EFH144, PIC32MX795F512L, P33FJ256GP710A
Flip & Click with P32MZ2048EFH100
Easy TFT, GLCD, 7" TFT
MikroC

hexreader
Posts: 1784
Joined: 27 Jun 2010 12:07
Location: England

Re: Pic32MX input capture

#2 Post by hexreader » 27 Sep 2021 12:55

The first thing that you should fix is the labels on the two buttons.

Change the caption text on both buttons from a single digit to xxxxxxxxxxxx (twelve x's).

LongToStr requires at least 12 bytes for destination array, you have only reserved one byte, plus terminating zero.

Does not cause a problem for current non-working code, since your results 0 and 3 happen to be single digit.
Bad things will happen once you get multi-digit results.

Someone else will need to help with capture - I have never used it.
Start every day with a smile...... (get it over with) :)

ColinI
Posts: 42
Joined: 29 Mar 2017 21:19

Re: Pic32MX input capture

#3 Post by ColinI » 27 Sep 2021 17:26

HI hexreader,
I had missed that, you're very right, weird stuff does happen if those are set incorrectly.
Thanks for the tip,
Colin
Windows 7 & 10 64 bit
PIC Clicker, PIC32MX Clicker
EasyPIC Pro v7 with PIC18F87J60, PIC18F87K22
EasyPIC Fusion v7 with PIC32MZ2048EFH144, PIC32MX795F512L, P33FJ256GP710A
Flip & Click with P32MZ2048EFH100
Easy TFT, GLCD, 7" TFT
MikroC

ColinI
Posts: 42
Joined: 29 Mar 2017 21:19

Re: Pic32MX input capture

#4 Post by ColinI » 05 Oct 2021 09:48

Hi All,
Some progress on this issue but there is still an interrupt problem. It's been changed to a 32 bit timer with PR2 & 3 maxed out and interrupt disabled. IC1BUF now returns values that look appropriate. The issue seems to be the interrupt is constantly triggered. This happens whether or not there is a square wave on it or not. It does the same with a pull down resistor on D8 (D11 for IC4). To show the issue data1,2 & 3 are placed at different points and can be un-commented to show their values for debugging. The interrupt service routine does not appear to function at all regardless of the wave source whether from the onboard pwm or a function generator setup with an appropriate offset. It has been tested on IC4 as well as a couple other fusion boards with different MX795F512L chips to be certain it's not hardware. It's getting closer but the interrupt is important, any help is appreciated.
Thanks much,
Colin

New main.c:

Code: Select all

/*
 * Project name:
     CaptureTest.mcp32
 * Generated by:
     Visual TFT
 * Date of creation
     2021-10-04
 * Test configuration:
     MCU:             P32MX795F512L
                      http://www.microchip.com/wwwproducts/Devices.aspx?product=PIC32MX795F512L
     Dev.Board:       EasyPIC_Fusion_v7_for_PIC32_9A
     Oscillator:      80000000 Hz
     SW:              mikroC PRO for PIC32
                      http://www.mikroe.com/mikroc/pic32/
 */

#include "CaptureTest_objects.h"

unsigned long long data1, data2, data3;
char txt1[22], txt2[22], txt3[22];

//Timer2/3
//Prescaler 1:1; PR3 Preload = 122; PR2 Preload = 4608; Actual Interrupt Time = 100 ms
void InitTimer2_3(){
  T2CON              = 0x0008; //0x8008; leave timer disabled but configured
  T3CON              = 0x0;
  TMR2               = 0;
  TMR3               = 0;
  T3IP0_bit          = 1;
  T3IP1_bit          = 1;
  T3IP2_bit          = 1;
  T3IF_bit           = 0;
  T3IE_bit           = 0;
  PR2                = 0xFFFFFFFF; //4608;
  PR3                = 0xFFFFFFFF; //122;
}

/*void Timer2_3Interrupt() iv IVT_TIMER_3 ilevel 7 ics ICS_SRS{
  T3IF_bit                 = 0;
  //Enter your code here
}*/

void Init_Capture() { // pin RD8 injecting 30 KHz 3V square wave 25% duty cycle offset 2V

  SIDL_IC1CON_bit    = 0;      // Stop in Idle 0 = continue
  IC1CONCLR          = 1;
  FEDGE_bit          = 1;      // capture rising edge
  C32_bit            = 1;      // 32 bit timer 1 = 32 bit
  //ICTMR_bit          = 0;      // use timer 3
  ICI1_bit           = 0;      // capture every rising edge
  ICI0_bit           = 0;      // Interrupt Control bits 11 = 4th, 10 = 3rd, 01 = 2nd, 00 = every
  //ICOV_bit                     // Input Capture Overflow Status Flag bit (read-only) 1 is positive indication
  //ICBNE_bit                    // Input Capture Buffer Not Empty Status bit (read-only) 0 = buffer empty, 1 = buffer not empty, one more capture possible
  ICM2_bit           = 1;      // Input Capture Mode Select bits 111 = Interrupt-Only mode, 110 = Simple Capture Event mode – every edge, 101 = every sixteenth rising edge
  ICM1_bit           = 1;      // 100 = every fourth rising edge, 011 every rising edge, 010 = every falling edge, 001 = every edge (rising and falling), 000 = Input Capture is disabled
  ICM0_bit           = 0;      // simple - every rising edge
  IC1IE_bit          = 1;      // enable IC1 interrupt
  ON__IC1CON_bit     = 1;      // turn IC1 on

  ON__T2CON_bit      = 1;      // start timer 2
}

void Input_Capture_1Interrupt() iv IVT_INPUT_CAPTURE_1 ilevel 7 ics ICS_SOFT { // Does not seem to trigger
  PORTGINV = 0b0000000001000000; // display some indication of activity
  IC1IF_bit = 0;
}

void main() {

  AD1PCFG            = 1;          // Digital mode
  ON__ETHCON1_bit    = 0;          // Disable Ethernet
  RTCCON             = 0;          // Disable RTCC
  C1CON              = 0;          // Disable CAN1
  C2CON              = 0;          // Disable CAN2
  ON__IC1CON_bit     = 0;          // disable IC1 (reset)

  TRISD = 0b0000000100000000;            // PORTD11 as input
  //LATD = 0b0000000000000000;           // PORTD off
  TRISG = 0b0000000000000000;            // PORTG as output
  //LATG = 0b0000000000000000;           // PORTG off

  InitTimer2_3();
  Init_Capture();                        // capture init
  EnableInterrupts();                    // Enable interrupts
  IC1IF_bit = 0;                         // clear interrupt flag
  Start_TP();

  while (1) {
    //Check_TP();

    //while(!IC1IF_bit);                 // wait for interrupt

    if(IC1IF_bit) {

      if(ICBNE_bit) {                 // if capture buffer is not empty read it and display info

          //data2 = IC1IF_bit;          // display in Button2 if uncommented reads 85899345921

          //data3 = ICBNE_bit;          // display in Button3 if uncommented reads 85899345921
          
          data1 = IC1BUF;             // display in Button1

          data2 = IC1IF_bit;          // display in Button2 reads 1 constantly in this position

          data3 = ICBNE_bit;          // display in Button3 reads 0 in this position

          LongLongUnsignedToStr(data1,txt1);
          LongLongUnsignedToStr(data2,txt2);
          LongLongUnsignedToStr(data3,txt3);
          strcpy(Button1.caption, txt1);
          strcpy(Button2.caption, txt2);
          strcpy(Button3.caption, txt3);
          DrawButton(&Button1);
          DrawButton(&Button2);
          DrawButton(&Button3);

          ON__IC1CON_bit     = 0;          // turn IC1 off
          
          IC1IF_bit = 0;                   // clear interrupt flag
       }

       ON__IC1CON_bit     = 1;             // turn IC1 on
     }
    //delay_ms(100);
  }
}
Windows 7 & 10 64 bit
PIC Clicker, PIC32MX Clicker
EasyPIC Pro v7 with PIC18F87J60, PIC18F87K22
EasyPIC Fusion v7 with PIC32MZ2048EFH144, PIC32MX795F512L, P33FJ256GP710A
Flip & Click with P32MZ2048EFH100
Easy TFT, GLCD, 7" TFT
MikroC

Post Reply

Return to “mikroC PRO for PIC32 General”