|
|
View previous topic :: View next topic |
Author |
Message |
kda406
Joined: 17 Sep 2003 Posts: 97 Location: Atlanta, GA, USA
|
PIC18F PPS on CCP2 not working [SOLVED] |
Posted: Tue May 17, 2022 12:23 pm |
|
|
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: 417
|
|
Posted: Tue May 17, 2022 2:02 pm |
|
|
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
|
|
Posted: Tue May 17, 2022 2:26 pm |
|
|
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: 417
|
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Tue May 17, 2022 3:13 pm |
|
|
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: 417
|
|
Posted: Tue May 17, 2022 3:30 pm |
|
|
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: 19504
|
|
Posted: Wed May 18, 2022 6:26 am |
|
|
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
|
|
Posted: Wed May 18, 2022 6:47 am |
|
|
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
|
|
Posted: Wed May 18, 2022 9:33 am |
|
|
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: 19504
|
|
Posted: Wed May 18, 2022 10:13 am |
|
|
The only problem then comes if you are using an old version chip. |
|
|
|
|
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
|