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

PIC18F PPS on CCP2 not working [SOLVED]

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



Joined: 17 Sep 2003
Posts: 97
Location: Atlanta, GA, USA

View user's profile Send private message

PIC18F PPS on CCP2 not working [SOLVED]
PostPosted: Tue May 17, 2022 12:23 pm     Reply with quote

I am seeking help determining if the PPS not working is a problem with my code, the compiler, or the Microchip silicon.

I'm currently compiling with 5.107 on PIC18F67K40 processors. I have tested with the same results on multiple boards to help ensure it is not a board level hardware related issue. I am measuring a pulse duration using CCP1 & CCP2 very much like CCS's ex_ccpmp.c and in fact I have pulled from that to create my example below. The board has a signal a few hundred microseconds long that is being measured on RG6. The PIC18F67K40's datasheet says CCP1 & 2 can be mapped to port E or G pins, so RG6 should not be a problem.

Also, this software was developed and tested using a PIC18F45K40 and it works. I put it into a 67K40 for production but the CCP2 interrupt never fires.

I have a couple of free port E pins, so I jumpered them to the G6 pin, set the program to look at those pins, and the interrupt works on E pins.

I use multiple compile units - always - and it works. However, for the benefit of the forum, I pulled all the parts and put them into one example program that illustrates the problem:
Code:
// Optimization level (overrides IDE's CL parameters). 0=none 9=max (default). CCS V5.x has problems with math and ISRs not working at opt 5 or higher
#opt 0
#include "18F67K40.h"
#case                           // Tell CCS compiler to be case sensitive
#use delay(clock=32000000)                        // 32 MHz Oscillator

// PIN_G0 => CCP2PPS = 30 but no interrupt (does not work)
// PIN_G3 => CCP2PPS = 33 but no interrupt (does not work)
// PIN_G6 => CCP2PPS = 36 but no interrupt (does not work)
// PIN_E3 => CCP2PPS = 23 interrupts (WORKS)
// PIN_E4 => CCP2PPS = 24 interrupts (WORKS)
#pin_select      CCP1=PIN_G6
#pin_select      CCP2=PIN_G6

#pin_select U1TX=PIN_C6
#pin_select U1RX=PIN_C7
#use rs232(UART1, baud=125000, stream=TERM, parity=N, bits=8, stop=1)

#FUSES NODEBUG                                             // No ICD debugging
#FUSES NOEXTOSC                                          // No external oscillator
#FUSES RSTOSC_HFINTRC_64MHZ                              //
#FUSES NOCLKOUT
#FUSES CKS                                                // CKS/NOCKS - CSWEN bit.  1 = enable clock switching, 0 = disable clock switching.  "CKS" allows setup_oscillator() to be used.
#FUSES NOFCMEN
#FUSES MCLR                                                // Use internal weak pull up MCLR with noise filer, this pin is not used as an input
#FUSES PUT                                                // Use the 66ms Power Up Timer to ensure device startup
#FUSES NOLPBOR
#FUSES NOZCDDIS                                          // Zero Crossing Detect hardware ENABLED
#FUSES NOPPS1WAY
#FUSES NOSTVREN
#FUSES NOXINST
#FUSES NOWRT
#FUSES NOWRTB
#FUSES NOWRTC
#FUSES NOWRTD
#FUSES NOSCANE
#FUSES NOLVP                                             // No Low Voltage Programming
#FUSES NOEBTR
#FUSES NOEBTRB
#FUSES BROWNOUT                                          // Use brown out detection when debugging or not
#FUSES BORV28                                             // Set the brown out detect voltage to 2.85Vtyp (2.7-3.0V)
#FUSES NOWDT                                             // No Watch Dog Timer
#FUSES NOPROTECT
#FUSES NOCPD

#byte CCP_1_CON = getenv("SFR:CCP1CON")
#byte CCP_2_CON = getenv("SFR:CCP2CON")
#byte CCPTMRS0 = getenv("SFR:CCPTMRS0")
#byte CCPTMRS1 = getenv("SFR:CCPTMRS1")
#byte RG6PPS = getenv("SFR:RG6PPS")
#byte RE4PPS = getenv("SFR:RE4PPS")
#byte CCP2PPS = getenv("SFR:CCP2PPS")

unsigned int16 rise,fall,pulse_width;      // For this example, use some global variables

#int_ccp2
void ccp2_isr() {
   rise = get_capture(1);      // CCP_1 is the time the pulse went high
   fall = get_capture(2);      // CCP_2 is the time the pulse went low
   pulse_width = fall - rise;   // pulse_width measured in timer3 counts
   fputc('.',TERM);
}                                 

void main() {
   setup_oscillator(OSC_HFINTRC_32MHZ);      // Use internal oscillator set at 32MHz instead of an external oscillator.
   setup_timer_3(T3_INTERNAL | T3_DIV_BY_4);   // 500ns period for 16 bit timer

   ///// Setup the Capture for rising and falling edges /////
   setup_ccp1(CCP_CAPTURE_RE | CCP_USE_TIMER3_AND_TIMER4);    // Configure CCP1 to capture rise
   setup_ccp2(CCP_CAPTURE_FE | CCP_USE_TIMER3_AND_TIMER4);    // Configure CCP2 to capture fall

   enable_interrupts(INT_CCP2);   // Setup to interrupt on falling edge
   enable_interrupts(GLOBAL);      // Enable interrupts
   
   fprintf(TERM,"\n\rCCP1CON: %02X\n\r",CCP_1_CON);
   fprintf(TERM,"CCP2CON: %02X\n\r",CCP_2_CON);
   fprintf(TERM,"CCPTMRS0: %02X\n\r",CCPTMRS0);
   fprintf(TERM,"CCPTMRS1: %02X\n\r",CCPTMRS1);
   fprintf(TERM,"CCP2PPS: %02X\n\r",CCP2PPS);

   while(1) {
      delay_ms(1000);
      fprintf(TERM,"%lu\n\r",pulse_width);
   }
}

As you can see, I have the program printing a few of the SFR registers just to be sure they are mapped correctly. The biggest one I questioned was CCP2PPS, but I believe CCS is mapping it correctly. I get
PIN_G0 => CCP2PPS = 30 but no interrupt (does not work)
PIN_G3 => CCP2PPS = 33 but no interrupt (does not work)
PIN_G6 => CCP2PPS = 36 but no interrupt (does not work)
PIN_E3 => CCP2PPS = 23 interrupts (WORKS)
PIN_E4 => CCP2PPS = 24 interrupts (WORKS)
as noted in the code.

To see if the interrupt is working, I have the interrupt print a period to the terminal.

When I put the signal into any G pin and setup the PPS to match I never get an interrupt, and never get a period:
Quote:
CCP2PPS: 36
23680
23680
23680
23680
23680
23680

When I choose any E pin and change the PPS it works:
Quote:
CCP2PPS: 23
...............................................................1033
...............................................................1033
...............................................................1034
...............................................................1034
...............................................................1034


Is the problem is with the silicon, the compiler, or my code?


Last edited by kda406 on Wed May 18, 2022 6:47 am; edited 1 time in total
E_Blue



Joined: 13 Apr 2011
Posts: 403

View user's profile Send private message

PostPosted: Tue May 17, 2022 2:02 pm     Reply with quote

Did you put an oscilloscope in those G Port pins to see the voltage levels?
Check if those pins doesn't have any other configuration.
Sometimes some pins start in analog mode.

Also, you can capture high and low with one CCP by changing the CCP configuration every edge.
_________________
Electric Blue
kda406



Joined: 17 Sep 2003
Posts: 97
Location: Atlanta, GA, USA

View user's profile Send private message

PostPosted: Tue May 17, 2022 2:26 pm     Reply with quote

Yes, I checked the receive signal on the pin itself, at the top, ensuring the signal is making it into the chip. I made sure the signal is not received while testing (closing the gap on an unsoldered pin). I also tested this on multiple PCBs with the same results.

Yes, I turned off analog inputs. The real program where this is used is 73 compile units, and I missed getting that line into the example program earlier. Here is the revised program with analogs disabled which has the same results:
Code:
// Optimization level (overrides IDE's CL parameters). 0=none 9=max (default). CCS V5.x has problems with math and ISRs not working at opt 5 or higher
#opt 0
#include "18F67K40.h"
#case                                                            // Tell CCS compiler to be case sensitive
#use delay(clock=32000000)                        // 32 MHz Oscillator

// PIN_G0 => CCP2PPS = 30 but no interrupt (does not work)
// PIN_G3 => CCP2PPS = 33 but no interrupt (does not work)
// PIN_G6 => CCP2PPS = 36 but no interrupt (does not work)
// PIN_E3 => CCP2PPS = 23 interrupts (WORKS)
// PIN_E4 => CCP2PPS = 24 interrupts (WORKS)
#pin_select      CCP1=PIN_G6
#pin_select      CCP2=PIN_G6

#pin_select U1TX=PIN_C6
#pin_select U1RX=PIN_C7
#use rs232(UART1, baud=125000, stream=TERM, parity=N, bits=8, stop=1)

#FUSES NODEBUG                                             // No ICD debugging
#FUSES NOEXTOSC                                          // No external oscillator
#FUSES RSTOSC_HFINTRC_64MHZ                              //
#FUSES NOCLKOUT
#FUSES CKS                                                // CKS/NOCKS - CSWEN bit.  1 = enable clock switching, 0 = disable clock switching.  "CKS" allows setup_oscillator() to be used.
#FUSES NOFCMEN
#FUSES MCLR                                                // Use internal weak pull up MCLR with noise filer, this pin is not used as an input
#FUSES PUT                                                // Use the 66ms Power Up Timer to ensure device startup
#FUSES NOLPBOR
#FUSES NOZCDDIS                                          // Zero Crossing Detect hardware ENABLED
#FUSES NOPPS1WAY
#FUSES NOSTVREN
#FUSES NOXINST
#FUSES NOWRT
#FUSES NOWRTB
#FUSES NOWRTC
#FUSES NOWRTD
#FUSES NOSCANE
#FUSES NOLVP                                             // No Low Voltage Programming
#FUSES NOEBTR
#FUSES NOEBTRB
#FUSES BROWNOUT                                          // Use brown out detection when debugging or not
#FUSES BORV28                                             // Set the brown out detect voltage to 2.85Vtyp (2.7-3.0V)
#FUSES NOWDT                                             // No Watch Dog Timer
#FUSES NOPROTECT
#FUSES NOCPD

#byte CCP_1_CON = getenv("SFR:CCP1CON")
#byte CCP_2_CON = getenv("SFR:CCP2CON")
#byte CCPTMRS0 = getenv("SFR:CCPTMRS0")
#byte CCPTMRS1 = getenv("SFR:CCPTMRS1")
#byte RG6PPS = getenv("SFR:RG6PPS")
#byte RE4PPS = getenv("SFR:RE4PPS")
#byte CCP2PPS = getenv("SFR:CCP2PPS")

unsigned int16 rise,fall,pulse_width;      // For this example, use some global variables

#int_ccp2
void ccp2_isr() {
   rise = get_capture(1);      // CCP_1 is the time the pulse went high
   fall = get_capture(2);      // CCP_2 is the time the pulse went low
   pulse_width = fall - rise;   // pulse_width measured in timer3 counts
   fputc('.',TERM);
}                                 

void main() {
   setup_oscillator(OSC_HFINTRC_32MHZ);      // Use internal oscillator set at 32MHz instead of an external oscillator.
   setup_timer_3(T3_INTERNAL | T3_DIV_BY_4);   // 500ns period for 16 bit timer

   setup_adc_ports(NO_ANALOGS,NO_ANALOGS_P2);                  // No A/D ports

   ///// Setup the Capture for rising and falling edges /////
   setup_ccp1(CCP_CAPTURE_RE | CCP_USE_TIMER3_AND_TIMER4);    // Configure CCP1 to capture rise
   setup_ccp2(CCP_CAPTURE_FE | CCP_USE_TIMER3_AND_TIMER4);    // Configure CCP2 to capture fall

   enable_interrupts(INT_CCP2);                                 // Setup to interrupt on falling edge
   enable_interrupts(GLOBAL);                                    // Enable interrupts
   
   fprintf(TERM,"\n\rCCP1CON: %02X\n\r",CCP_1_CON);
   fprintf(TERM,"CCP2CON: %02X\n\r",CCP_2_CON);
   fprintf(TERM,"CCPTMRS0: %02X\n\r",CCPTMRS0);
   fprintf(TERM,"CCPTMRS1: %02X\n\r",CCPTMRS1);
   fprintf(TERM,"CCP2PPS: %02X\n\r",CCP2PPS);

   while(1) {
      delay_ms(1000);
      fprintf(TERM,"%lu\n\r",pulse_width);
   }
}


The pic cannot use a single pin to capture both edges and also do the other jobs it is tasked with. Even so, CCP1 does not work on port G either. So I couldn't switch it to another capture method since I cannot remap the CCP1 to the supported port either.

But THANK YOU for your thoughtful input.
E_Blue



Joined: 13 Apr 2011
Posts: 403

View user's profile Send private message

PostPosted: Tue May 17, 2022 3:00 pm     Reply with quote

I'm reading the PDF 40001841D and in page 330 it says that CCP1, 2 and 3 only works in PORTC and E.

CCP4 and CCP5 works in PORTE and G.

https://ww1.microchip.com/downloads/en/DeviceDoc/PIC18%28L%29F67K40%20Data%20Sheet%2040001841D.pdf
_________________
Electric Blue
gaugeguy



Joined: 05 Apr 2011
Posts: 286

View user's profile Send private message

PostPosted: Tue May 17, 2022 3:13 pm     Reply with quote

When I look at the data sheet for the PIC18F67K40, Table 17- shows PPS for CCP1, CCP2, and CCP3 are only available on port C and E.
CCP4 and CCP5 are available on port E and G.
E_Blue



Joined: 13 Apr 2011
Posts: 403

View user's profile Send private message

PostPosted: Tue May 17, 2022 3:30 pm     Reply with quote

Quote:
The pic cannot use a single pin to capture both edges...


Yes, you can, I did it on an old 16F627 that only has ONE CCP to read a 7kHz signal.
The timer is only one, so when one edge triggers the interrupt the timer is still counting, change the CCP to the opposite edge saves the current timer and in the next edge make a simple

oldCapture-currentCapture=currentPeriod

, and that's it.

You are wasting resources and drowning in a glass.
_________________
Electric Blue
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Wed May 18, 2022 6:26 am     Reply with quote

This is one of those 'read the data sheet' problems.

Technically CCP2PPS, can be set to G0. So the compiler does not refuse
it. However internally the chip only allows the input to actually be 'routed'
from port C or E.
In the data sheet 'PORT From Which Input Is Available'
What has happened is that MicroChip have not implemented connections
from all the ports.

So it won't work.
kda406



Joined: 17 Sep 2003
Posts: 97
Location: Atlanta, GA, USA

View user's profile Send private message

PostPosted: Wed May 18, 2022 6:47 am     Reply with quote

You missed the most important part when quoting.
Quote:
... and also do the other jobs it is tasked with.
I'm so happy you were able to read a 7kHz signal. However, this product is servicing 3 networks, a user interface, a separate display, synchronous stepper motor, several fractional and multi-HP motors, dozens of sensors (analog, 1W, digital), etc. It cannot do all the tasks at the prescribed timing if it is wasting time reconfiguring the interrupt needlessly. I need the PIC to do its job, using two capture ports to capture the different edges as CCS suggests.

The pic cannot use a single pin to capture both edges and also do the other jobs it is tasked with.

Despite your condescending and presumptive remarks, you have indeed located the problem. I'm using the datasheet DS40001841C that we have used for countless products in the market. Page 226 states the PPS mapping:
CCP1 E G
CCP2 E G
CCP3 C E
CCP4 C E
CCP5 C E
Hence, the use of CCP1 & CCP2 for G. We've been sending products to market for years using this datasheet and I was unaware of a D revision. DS40001841D remapped the pins:
CCP1 C E
CCP2 C E
CCP3 C E
CCP4 E G
CCP5 E G

The only reason for using 1&2 was because the desired pins were on port G. The great news in my eyes is that I can simply switch to using CCP4 & CCP5 and no rewiring will be required for this one to get unit into production too.

Thanks.
kda406



Joined: 17 Sep 2003
Posts: 97
Location: Atlanta, GA, USA

View user's profile Send private message

PostPosted: Wed May 18, 2022 9:33 am     Reply with quote

CCS 5.107 will not let me assign CCP4 & CCP5 to port G. It seems they built from the same datasheet I used, which (now incorrectly) says only CCP1 and CCP2 can be assigned to port G for this device.
Code:
#pin_select      CCP4=PIN_G6
#pin_select      CCP5=PIN_G6

Quote:
Error#7 Invalid Pre-Processor directive Invalid Pin: PIN_G6 can not be assigned to CCP4:
Error#7 Invalid Pre-Processor directive Invalid Pin: PIN_G6 can not be assigned to CCP5:
2 Errors, 0 Warnings.


Now that the datasheet has changed in rev D, CCS will need to update the device. I'll open a ticket with them for correction, but want the thread to be recorded correctly for posterity.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Wed May 18, 2022 10:13 am     Reply with quote

The only problem then comes if you are using an old version chip.
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