 |
 |
View previous topic :: View next topic |
Author |
Message |
pekka1234
Joined: 28 May 2017 Posts: 92
|
A capacitance meter |
Posted: Sun Jun 15, 2025 10:28 am |
|
|
Hey, I am doing a capacitor counter with a PIC18F2620 and CCS 5.120 compiler.
I have a 555 as an oscillator, with two 1k resitors, 22uF measuring capacitor from pin 2 and 6 to ground.
It gives 21Hz pulses from pin 3 to PIC18's C2.
I am trying to measure the pulse with a CCP1 using rising and falling signals.
All interrupts Timer1 and CCP1 goes well, but the result is too small.
Fall 208 Rise: 191
Pulse width: 17 us
It should give 1/21Hz or 47.6ms/2 = 23.8ms
What am I doing wrong?
Here is the code:
Code: |
#include <18F2620.h>
#FUSES NOWDT, INTRC_IO, NOPROTECT, NOBROWNOUT, NOPUT, NOCPD
#FUSES NODEBUG, NOLVP, NOWRT, NOFCMEN, NOMCLR, BORV21, NOIESO
#use delay(internal=8000000) // 8 MHz
#use rs232(baud=115200, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8, invert)
#byte CCP1CON = 0xFBD
#byte PIR1 = 0xF9E
#byte CCPR1L = 0xFBE
#byte CCPR1H = 0xFBF
volatile unsigned long timer = 0, rise = 0, fall = 0, pulse_width = 0;
volatile int edge_state = 0, new_pulse = 0;
unsigned int16 overflow_count ;
//measure rising-falling time
#int_ccp1
void ccp1_isr() {
unsigned long time = ((unsigned long)timer * 65536UL) + ((CCPR1H << 8) | CCPR1L); // look time CCPR1H <<8 + CPPR1L
if (edge_state == 0) {
rise = time;
CCP1CON = 0x05; //Change to falling edge
edge_state = 1;
} else {
fall = time;
if (fall > rise)// if fall time is longer than rise
pulse_width = fall - rise; // count puse width
new_pulse = 1;
CCP1CON = 0x04; //back to riding rdge
edge_state = 0;
timer=0;
}
PIR1 &= ~0x01; // zero CCP1IF
}
#int_timer1
void timer1_isr() {
timer++; // increase 32-bit timer value by over 65536
overflow_count++;
}
void main() {
set_tris_c(0b00000110); // PIN_C2 (CCP1) ja PIN_C1 (CCP2) input
CCP1CON = 0x04; // CCP1 rising edge
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8); // Timer1, 1 µs per tick
set_timer1(0);
enable_interrupts(INT_CCP1);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
delay_ms(10);
while(TRUE) {
if (overflow_count >= 10) {
printf("Timer1 overflow: %lu\r", timer);
overflow_count = 0;
}
if (new_pulse) {
printf("Fall %lu Rise: %lu\r",fall, rise);
pulse_width==fall-Rise;
printf("Pulse width: %lu us\r", pulse_width); // nyt oikea yksikkö!
new_pulse = 0;
}
}
}
|
|
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19856
|
|
Posted: Sun Jun 15, 2025 2:40 pm |
|
|
First thing. Don't use terms like long.
Use the actual size you want. The problem is that 'long' means an int16 on
the PIC. On chips like the PC, it means an int32. Its is always safer to be
explicit and say what size you actually want.
The big problem comes here, because an unsigned long, is just a 16bit value
so can't hold the result of yorr maths with the timer overflow.... :(
Then you don't need to fiddle around performing the rotation to combine the
two parts of the CCP. The compiler already has CCP_1 defined for you as a
16vit word, that reads both parts in one operation. Look in the header file for
the chip.
Then just use a union to combine the values. Have your overflow word
in the top 16bits of a union, and load the CCP_1 value into the low 16bits,
and you can then read the 32bit value, with no overhead involved in combining
these.
Code: |
unsigned int32 rise=0; fall=0;
union {
unsigned int16 words[2];
unsigned int32 whole;
} timerval = 0;
#int_ccp1
void ccp1_isr(void) {
timerval.words[0]=CCP_1; //load the low 16bits from the CCP
if (edge_state == 0) {
rise = timerval.whole;;
CCP1CON = 0x05; //Change to falling edge
edge_state = 1;
} else {
fall = timerval.whole;;
if (fall > rise)// if fall time is longer than rise
pulse_width = fall - rise; // count puse width
new_pulse = 1;
CCP1CON = 0x04; //back to riding rdge
edge_state = 0;
timer=0;
}
//PIR1 &= ~0x01; // zero CCP1IF //Not needed the compiler clears this
//Unless you specify 'NOCLEAR'
}
#int_timer1
void timer1_isr() {
timerval.word[1]++; //Increment the upper 16vbits of the timer
overflow_count++;
}
|
Then the other thing is that the timer does not count off FOSC. It counts
off FOSC/4. So you need to use T1_DIV_BY_2, not 8. Look at figure 12-1
in the data sheet 'Timer 1 block diagram'. FOSC/4 internal clock...... |
|
 |
|
|
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
|