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 CCS Technical Support

A capacitance meter

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



Joined: 28 May 2017
Posts: 92

View user's profile Send private message

A capacitance meter
PostPosted: Sun Jun 15, 2025 10:28 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Jun 15, 2025 2:40 pm     Reply with quote

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......
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