CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

[Solved] CCP Capture not capturing timer value

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
mob1182



Joined: 03 Mar 2016
Posts: 28

View user's profile Send private message

[Solved] CCP Capture not capturing timer value
PostPosted: Thu Dec 22, 2016 8:03 am     Reply with quote

Ok I'm really racking my brain here and need some help. I've been looking at this for 2 days now and can't figure out what I'm missing. For some reason I can't get the CCP_2 to capture the timer 1 value. This code does work on a PIC18F4685(minus the pin select) but I need to use it on the PIC18F47K40. I got most of the code from PCM Programmer in the forums so credit to him for the working parts.
PCWH 5.066

header
Code:

#include <18F47K40.h>
#device ADC=10

#FUSES NOEXTOSC                  //External Oscillator not enabled
#FUSES CLKOUT                    //Clockout on Pin 14
#FUSES NOMCLR                    //Master Clear pin used for I/O
#FUSES NOBROWNOUT                //No brownout reset
#FUSES NOLVP                     //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWDT                     //No Watchdog
#FUSES NOPROTECT
#FUSES PUT

#use delay(internal=8MHz, clock_out)

#PIN_SELECT U1RX=PIN_C7
#PIN_SELECT U1TX=PIN_C6
#USE RS232(BAUD=9600, UART1, PARITY=N, BITS=8, STREAM=PC, ERRORS)

//#use fast_io(C)
#DEFINE TABLE_SIZE   200

main()
Code:

void main() {
   setup_oscillator(OSC_HFINTRC_8MHZ);
   //SET_TRIS_C(0X8F);
   delay_ms(10);
   userprompt();
}

ccp code
Code:

#DEVICE HIGH_INTS=TRUE;
#pin_select CCP2=PIN_C1

int rising_edge_captured; //remove when works
int capture_rising_edge;
int capture_second_rising_edge;
int got_pulse_width;
long ccp_delta;
long t1_rising_edge;
long t1_falling_edge;
long t1_second_rising_edge;
long timer1_rising;

//-----------------------------------------------------------------------------
/*we want as less overhead as possible since we are only using 1 ccp module, if the
pulse is less than the overhead time of switching the ccp state, it will not be detected*/
#int_ccp2 FAST //Fast to reduce the dead zone created by instruction overhead
 void ccp2_isr(void) {
   //static long t1_rising_edge;
   
   //Step 3. Rising Edge of second Pulse (Duty Cycle)
   if (capture_second_rising_edge)  {
      capture_second_rising_edge = FALSE;    //Skip this "if" on next INT
      capture_rising_edge = TRUE;            //Go to step 1 on next ISR
      t1_second_rising_edge = CCP_2;         //Timer value when the pulse return high for second pulse
      got_pulse_width = TRUE;                //Operation complete
   }
   //Step 1. Rising Edge of pulse
   else if (capture_rising_edge) {
      timer1_rising = get_timer1(); //remove when works
      setup_ccp2(CCP_CAPTURE_FE);            //Setup to interrupt on falling edge
      capture_rising_edge = FALSE;           //Go to step 2 on next ISR
      t1_rising_edge = CCP_2;                //Timer value when the pulse went high
      rising_edge_captured = TRUE;  //remove when works
   }
   //Step 2. Falling Edge of Pulse
   else  {
      setup_ccp2(CCP_CAPTURE_RE);            //Setup to interrupt on rising edge
      capture_second_rising_edge = TRUE;     //Go to step 3 on next ISR
      t1_falling_edge = CCP_2;               //Timer value when the pulse went low
      ccp_delta = CCP_2 - t1_rising_edge;    //fall - rise = on time
      rising_edge_captured = FALSE;  //remove when works
   }
}
//-----------------------------------------------------------------------------
long read_pulse() {
   int pulse_rec = 0, no_pulse_counter=0, pulse_time_limit=30;
   long long t_on;               //long long for multiplication by 4098 below
   long t_off, pos;
   long pulse_width;
   //Initialize BOOLS for ISR--------------------------
   got_pulse_width = FALSE;
   capture_rising_edge = TRUE;
   capture_second_rising_edge = FALSE;
   rising_edge_captured = FALSE;
   //Initialize CCP Module for 1st use-----------------
   setup_ccp2(CCP_CAPTURE_RE|CCP_USE_TIMER1_AND_TIMER2);
         #byte CCP2PPS=getenv("sfr:CCP2PPS");
         fprintf(PC, "CCP2PPS = %x\r\n", CCP2PPS);
         #byte CCP2CON=getenv("sfr:CCP2CON");
         fprintf(PC, "CCP2CON = %x\r\n", CCP2CON);
         #byte CCPTMRS=getenv("sfr:CCPTMRS");
         fprintf(PC, "CCPTMRS = %x\r\n", CCPTMRS);
         #byte CCP2CAP=getenv("sfr:CCP2CAP");
         fprintf(PC, "CCP2CAP = %x\r\n", CCP2CAP);
   
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);      //32.768 ms overflow with 8mHz clock
         #byte T1CON=getenv("sfr:T1CON");
         fprintf(PC, "T1CON = %x\r\n", T1CON);
         #byte T1GCON=getenv("sfr:T1GCON");
         fprintf(PC, "T1GCON = %x\r\n", T1GCON);
         #byte T1CLK=getenv("sfr:T1CLK");
         fprintf(PC, "T1CLK = %x\r\n", T1CLK);
   
   clear_interrupt(INT_CCP2);                   //Make sure flag is cleared
   //--------------------------------------------------
   enable_interrupts(INT_CCP2);
   enable_interrupts(GLOBAL);

   do {
               if (rising_edge_captured)  {     //remove when works
                  disable_interrupts(GLOBAL);
                  disable_interrupts(INT_CCP2);
                  #byte CCPR2H=getenv("sfr:CCPR2H");
                  #byte CCPR2L=getenv("sfr:CCPR2L");
                  fprintf(PC, "CCPR2H = %x\r\n", CCPR2H);
                  fprintf(PC, "CCPR2L = %x\r\n", CCPR2L);     
                  enable_interrupts(INT_CCP2);
                  enable_interrupts(GLOBAL);
                }
   
      if (got_pulse_width) {
         disable_interrupts(GLOBAL);
         disable_interrupts(INT_CCP2);
               fprintf(PC, "t1_rising_edge: %lu\r\n", t1_rising_edge);
               fprintf(PC, "timer1_rising: %lu\r\n", timer1_rising);
               fprintf(PC, "t1_falling_edge: %lu\r\n", t1_falling_edge);
         t_on = ccp_delta;
         t_off = t1_second_rising_edge - t1_falling_edge;
         pulse_width = t1_second_rising_edge - t1_rising_edge;
         pos = ((t_on * 4098) / (t_on + t_off)) - 1;                      //pulse position in duty cycle
         pulse_rec++;
      }
      no_pulse_counter++;
      delay_ms(1);
   } while (pulse_rec < 1 && no_pulse_counter < pulse_time_limit);
   
   if(no_pulse_counter >= pulse_time_limit) {
      fprintf(PC, "no pulse detected\r\n");
      return 1;
   }
   
   //-----------------------------------------------------------------           
   if (pulse_width < 9000 && pos < 4083)  {  //Only if width was not larger than duty cycle
      return pos;
   }
   else  {
      fprintf(PC, "PW: %lu\r\n", pulse_width);
      fprintf(PC, "T_ON: %lu\r\n", t_on);
      fprintf(PC, "T_OFF: %lu\r\n", t_off);
      fprintf(PC, "POS: %lu\r\n", pos);
      return 1;
   }
}


terminal results
Code:

CCP2PPS = 11
CCP2CON = 85
CCPTMRS = 55
CCP2CAP = 00
T1CON = 07
T1GCON = 00
T1CLK = 01
CCPR2H = ff
CCPR2L = 00
t1_rising_edge: 65280
timer1_rising: 17710
t1_falling_edge: 65280
PW: 0
T_ON: 0
T_OFF: 0
POS: 65535


You can see with timer1_rising that the timer is running. I know this won't be the exact capture value though. But t1_rising_edge and t1_falling_edge show the same exact incorrect value. And CCPR2H_L show the 65280. I'm using getenv to read the registers. I've never used getenv before so please let me know if I'm misunderstanding how that works.

My duty cycle is 240hz (4.17ms)
I can vary my pulse anywhere but I have it set to half the duty cycle.


Last edited by mob1182 on Fri Dec 23, 2016 1:50 pm; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Dec 22, 2016 9:54 pm     Reply with quote

The compiler database for the 18F47K40 in vs. 5.066 appears to be
screwed up. It generates the code below. The registers are incorrect.
It's stuffing things into the timer control and capture input selection
registers and that's not correct.
Quote:
.................... temp = CCP_1_LOW;
00A52: MOVFF CCP1CAP,temp
.................... temp = CCP_1_HIGH;
00A56: MOVFF CCPTMRS,temp
.................... temp16 = CCP_1;
00A5A: MOVFF CCP1CAP,temp16
....................
.................... temp = CCP_2_LOW;
00A5E: MOVFF CCP2CAP,temp
.................... temp = CCP_2_HIGH;
00A62: MOVFF CCPR1L,temp
.................... temp16 = CCP_2;
00A66: MOVFF CCP2CAP,temp16


You can fix it by adding the following lines above main().
They tell the compiler to use the correct register addresses:
Code:

#word   CCP_1       = 0xFAA                   
#byte   CCP_1_LOW   = 0xFAA
#byte   CCP_1_HIGH  = 0xFAB
#word   CCP_2       = 0xFA6                   
#byte   CCP_2_LOW   = 0xFA6                   
#byte   CCP_2_HIGH  = 0xFA7

You'll get warnings of duplicate #locate lines, but it will still substitute
the correct register addresses in the code.

After we do that, then everything matches:
Code:

.................... temp = CCP_1_LOW;   
00A52:  MOVFF  CCPR1L,temp
.................... temp = CCP_1_HIGH;   
00A56:  MOVFF  CCPR1H,temp
.................... temp16 = CCP_1;     
00A5A:  MOVFF  CCPR1L,temp16
.................... 
.................... temp = CCP_2_LOW;
00A5E:  MOVFF  CCPR2L,temp
.................... temp = CCP_2_HIGH; 
00A62:  MOVFF  CCPR2H,temp
.................... temp16 =  CCP_2;
00A66:  MOVFF  CCPR2L,temp16
....................

I didn't check any other aspects of CCP use. I didn't check if CCS did the
functions correctly. I'd rather you test it first and see if this makes it work.
mob1182



Joined: 03 Mar 2016
Posts: 28

View user's profile Send private message

PostPosted: Fri Dec 23, 2016 1:48 pm     Reply with quote

Wow thanks a lot PCM. Very interesting. This seems to be working. I'm not too strong when it comes to assembly language. Something I will need to improve on. I'm going to have to expand on the code and use CCP1 as well, so hopefully I can learn from this and get it all working. Thanks for the help!
mob1182



Joined: 03 Mar 2016
Posts: 28

View user's profile Send private message

PostPosted: Wed Jan 25, 2017 7:01 am     Reply with quote

Just an FYI, compiler update 5.067 came out today and fixed this.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group