|
|
View previous topic :: View next topic |
Author |
Message |
mob1182
Joined: 03 Mar 2016 Posts: 28
|
[Solved] CCP Capture not capturing timer value |
Posted: Thu Dec 22, 2016 8:03 am |
|
|
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
|
|
Posted: Thu Dec 22, 2016 9:54 pm |
|
|
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
|
|
Posted: Fri Dec 23, 2016 1:48 pm |
|
|
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
|
|
Posted: Wed Jan 25, 2017 7:01 am |
|
|
Just an FYI, compiler update 5.067 came out today and fixed this. |
|
|
|
|
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
|