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

Internal Prescaler EX_FREQ.C
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
maria100



Joined: 01 Feb 2012
Posts: 63

View user's profile Send private message

Internal Prescaler EX_FREQ.C
PostPosted: Sat Feb 04, 2012 1:57 pm     Reply with quote

Hello, I`m trying to implement a frequency meter based on EX_FREQC.C ( the example source included in CCS package) ..but i encountered two problems:
-If i change the EXternal 20 Mhz crystal with the 8 Mhz internal OSC built in 16f88 , what other adjustments i need to make to the code to work with the new MCU frequency right? how do i do to make it read at 100 ms , not at 1000 ms as now..?
-could i use the
Code:
 setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
as prescaler to have the capability to read even bigger freq? Thank you
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Sat Feb 04, 2012 2:46 pm     Reply with quote

Read bigger frequency YES - but with WORSE resolution......

A prescalar is NOT your friend if you want "single count" resolution, in your design.

For instance - if you have a prescalar of /8 - you can not resolve BETTER than 64 HZ at the input rate. In simplest terms - at say 1024 hz input
you can't tell the difference between 1024 hz and 1087 hz - they will both count as 160 in your timer registers, since you CAN'T READ the PRESCALAR count at all.
maria100



Joined: 01 Feb 2012
Posts: 63

View user's profile Send private message

PostPosted: Sat Feb 04, 2012 2:49 pm     Reply with quote

i dont know for real if i need a prescaler or not...i need only up to 7 Mhz measurements...but dont know if the code in that sample will go that high with a 8 Mhz OSC tune...any ideea?
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Sat Feb 04, 2012 3:07 pm     Reply with quote

What you have now is a MATH problem
not a programming issue IMHO.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

7MHz frequency counter
PostPosted: Sun Feb 05, 2012 9:11 am     Reply with quote

We are now all assuming that you really want to count to 7MHz NOT 7mHz.

You need to stand back from the problem and work out what you are trying to do.

SherpaDoug has already told you that the hardware can handle your 8MHz input frequency.

asmboy has outlined the problem in using T1's prescaler.

You want to use a 100ms gate period and achieve 100Hz accuracy.

Think about your problem BEFORE you start coding, you may have to do some crude maths, and play at being a computer.

(1) Timing from the internal RC oscillator will make ACCURACY 1% at best. At 8MHz that's +/- 80kHz!
(2) Do you want accuracy or resolution?
(3) Using interrupts could lead to timing and contention issues.
(4) Feeding 8MHz straight into T1 will cause T1 to overflow every 8.192ms.
(5) With your 100ms gate, T1 overflows ~12 times with no prescale.
(6) The CCS example uses overflow to make T1 effectively a 17 bit counter.
(7) You could externally gate your input signal to the external inputs of both T0 and T1.
(8) Get the PIC to control the external gate.
(9) Use the divide by 8 prescale for T1.
(10) Use divide by 1 prescale for T0.
(11) The three LSB's of T0 hold T1's prescale value.
(12) You may now get 20 bit resolution!

Mike


Last edited by Mike Walne on Sun Feb 05, 2012 3:34 pm; edited 1 time in total
maria100



Joined: 01 Feb 2012
Posts: 63

View user's profile Send private message

PostPosted: Sun Feb 05, 2012 9:32 am     Reply with quote

Thank you Mike and ASMBOY, I will test your ideas and post after.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

More thoughts on gating.
PostPosted: Tue Feb 07, 2012 5:29 pm     Reply with quote

I can forsee a possible problem with the simple external gate suggestion. There's a remote possibility that the first (and/or the last) pulse into your PIC is not quite wide enough to operate both counters T0 & T1 correctly. The effect would be that one or other of the counters could receive two more pulses than the other. The worst case would be the situation where T1 prescaler either misses or generates an extra overflow and leads to an eight count error. One solution would be gate hardware which preconditions the input pulses so that all pulses reaching the PIC have a guaranteed period. Or you could say that the possiblity is so remote that it can be ignored.

There are several ways you might avoid using an external gate to your frequency counter, and rely on software gating.

(1) Use T1 only without prescaler. When T1 overflows generate an interrupt. The T1 interrupt routine increments an overflow counter. During this T1 interrupt, the main() timer stops, you will then have to correct for this. The real problem occurs if the overflow happens towards the end of the gate period. Correcting for this situation could be more difficult, but may be possible.

(2) Use T1 as in (1) but use T2 as a timer to create an interrupt driven software gate. This avoids having to correct for the main() software timer stopping on T1 interrupt, but still leaves the issue of both counters overflowing close together at the end of the gate period.

(3) Use T0 and T1 as outlined previously. The problem is that the two counters can't be started and stopped sychronously (hence the external gate suggestion). However the starting and stopping delays are well defined, it should be possible to correct for the effects of the delays. Bear in mind that T0 5 MSB's should agree with T1 5 LSB's. Any discrepancy will need to be dealt with.

Mike
maria100



Joined: 01 Feb 2012
Posts: 63

View user's profile Send private message

PostPosted: Fri Feb 10, 2012 9:40 am     Reply with quote

Ok, so i have problems with this freq counter (the EX_FREQ.C SAMPLE). I get garbage data in the terminal...not the " Hz " that is set in the code. I changed the include line to 18f25k22 and it compiles fine. I set the oscillator as HSH in the config. The delay 20000000. What could be the problem ? I'm running on 20 MHz. Why is this happening ?
Also I was trying PCM PROGRAMMER'S other freq meter code:
Code:

#include <18F452.h>
#fuses H4,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=40M)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

int16 isr_ccp_delta;

#int_ccp1
void ccp1_isr(void)
{
int16 current_ccp;
static int16 old_ccp = 0;

current_ccp = CCP_1;   

isr_ccp_delta = current_ccp - old_ccp;

old_ccp = current_ccp;
}

//=======================
void main()
{
int16 current_ccp_delta;
int32 frequency;

set_timer1(0);           
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_ccp1(CCP_CAPTURE_DIV_16);   

clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);

while(1)
  {
   disable_interrupts(GLOBAL);
   current_ccp_delta = isr_ccp_delta;
   enable_interrupts(GLOBAL);
   
   frequency = (int32)(160000000L / current_ccp_delta);

   printf("%lu Hz\n\r", frequency);

   delay_ms(500);
  }

}

I have replaced his original 40 mhz delay with 20 , so i will got half the frequency it is right? but it doesent..I have tried to measure a known 4.155.000 freq but i get about 2.400.000 hz...not the half as should be...~2.077.000...why is this happening?.. trying for one whole week to make a frequency counter work right... Embarassed ..ermm
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Feb 10, 2012 2:28 pm     Reply with quote

The CCP interrupt method shown in that code is not suitable for higher
frequencies. That's because it takes about 50 instruction cycles just for
the overhead to process the interrupt. The #int_ccp user code takes 13
more cycles. That's 63. At 40MHz, the PIC does 10 instructions per usec.
So it takes about 6.3 usec to handle the CCP interrupt.

But your input frequency is 4.155 MHz. Divide that by the CCP Div_16
prescaler to get about 260 KHz for the CCP input. The period is about
3.9 usec. So your input period for the CCP is shorter than the interrupt
overhead. That's a problem.

There might be some clever way to handle single captures (with two
sequential CCP positive edges), by clearing the CCP interrupt at the
beginning of the #int_ccp routine. Then use a mini-state machine to do
only two captures, and then disable interrupts. But you want it to work
up to 7 MHz. It's possible that a much shorter interrupt routine could be
done with #int_global. The problem is that you're a newbie and you're
not going to do it. You want a pre-made solution instead of theory.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

Latest Version
PostPosted: Fri Feb 10, 2012 6:28 pm     Reply with quote

I'm confused. You post code then say "Oh by the way I've change this, that and the other".

So; are you using a 40MHz or a 20MHz clock? An 18F452 or an 18F25K22?

Why set up so that the displayed frequency differs from the real one by a factor of two?

It would help me if you explained how you expect your current version to work.

Into which port are you feeding your external signal? How are you deriving your gating period?

PCM programmer can see what you're doing, but I don't care to have to work it out for myself, I design power electronics, I'm not a software expert.

I have compiled your code. I get no results because I don't have enough information. I don't propose wasting any more time without input from you.


Like I said before, you need to work out CLEARLY what you're doing BEFORE coding. Think at the block diagram (pseudo-code) level.

Your code has no helpful comments.

What are you trying to achieve? 100Hz resolution? 100ms update rate? What?

Mike
maria100



Joined: 01 Feb 2012
Posts: 63

View user's profile Send private message

PostPosted: Fri Feb 10, 2012 7:32 pm     Reply with quote

Sorry Mike for my lack of proper explication. Last thing i want is to waste people time for nothing. I will try to be very obiective from now one:

1. My post was about two frequency meters designs. (one the EX_FREQ.C that CCS PROVIDES,and the other one is the one posted by PCM PROGRAMMER - the one that i posted the code ).

2. All the designs I'm running is in a 18f25k22 development board, but i have posted the original designs ( that has other pic), but when i compile i change the apropriate include file with my 18f25k22.

3. PROBLEMS with the meters: The EX_Freq.c isn't working at all. I get only garbage data to the hyperterminal. The other one (pcm programmer) works, but very strange. When I turn power on it is saying that i have allready a random relative small frequency (~ 3000-6000 hz) every time (even if is nothing on the input pin), and when i apply the clk is doesn't show the value right. My guess is that my frequency that I`m trying to measure ( 4155000 HZ) ~4.1 MHZ, is too big.

4. MY final Goal: to complete a freq meter that could read up to 6 MHz, and update the frequency every 100 ms.

5. As oscillator I use a external 20 Mhz, with the apropriate HSH fuse set.

I thank all the people who answered my threads for their patience.
maria100



Joined: 01 Feb 2012
Posts: 63

View user's profile Send private message

PostPosted: Sat Feb 11, 2012 10:56 am     Reply with quote

I finally done it, using the FREQ.C source file, however i have a little problem, I cannot run with external oscillator ( 20 M). It doesn't show anything in the terminal. Pure blank. Is only running with the 16 MHZ internal one. Here is the code and fuses for the external one:
Code:

#include <18F25K22.h>
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES ECH                      //External clock with CLKOUT(PIC18), high power
#FUSES NOPLLEN                  //4X HW PLL disabled, 4X PLL enabled in software
#FUSES NOBROWNOUT               //No brownout reset
#FUSES WDT_NOSLEEP              //Watch Dog Timer, disabled during SLEEP
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(clock=20000000)    //one instruction=0.2us
#use rs232(baud=9600, UART1)

//#bit t1_overflow=0x0C.0
#bit t1_overflow=0xF9E.0  //(PIC18, Reminder)

void main() {
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_timer_4(T4_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
 //  setup_oscillator(OSC_16MHZ|OSC_NORMAL|OSC_31250|OSC_PLL_ON);

   int cycles8, cycles;
   int32 freq;
   long freqc_high;
   long freqc_low;

   while (TRUE) {
      cycles8=0;
      cycles=0;
      freqc_high=0;
      t1_overflow=0;
      set_timer1(0);
      setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
/* ___ wait one second ___  */
      while (cycles!=0xFF) { //true=3, false=4
       cycles8=0; //1 cycle
       //start inner loop
       while (cycles8!=0xFF) { //true=3, false=4
         if (t1_overflow)//true=2,false=3             //----|
            {t1_overflow=0;freqc_high++;}//6 cycles   //    |
         else                                         //    |-- 8 cycles
            {delay_cycles(5);}                        //----|
         delay_cycles(62); //x
         cycles8++; //1
 ///2 cycles to jump to top
 //math: end inner loop
 //math: total inner loop=((3+8+x+1+2)*255 + 4)*255
 //math: if x=62.87781 then inner loops takes 5mil instructions
 //math: if x=62 then inner loop takes 4942920, have to fill 57080 cycles
  }
 delay_cycles(216);      //y
 cycles++;          ///1 cycle
 ///2 cylces to jump to top
 //math: outer=(3+1+y+1+2)*255+4=57080
 //math: y=(57080-4)/255)-(3+1+0+0+1+2)
 //math: if y=216.827450980392156862745098039216 then outer loop cylces is 57080
 //math: if y=216 then outer loop cycles is off by 211 cycles.  z=211
}
      delay_cycles(211);   //z
/* ___ end waiting 1 second ___ */
      setup_timer_1(T1_DISABLED);   //turn of counter to prevent corruption while grabbing value
      if (t1_overflow)            //check one last time for overflow
          freqc_high++;
      freqc_low=get_timer1();      //get timer1 value as the least sign. 16bits of freq counter
      freq=make32(freqc_high,freqc_low);   //use new make32 function to join lsb and msb
      printf("%LU Hz\r\n",freq);      //and print frequency
   }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19503

View user's profile Send private message

PostPosted: Sat Feb 11, 2012 11:13 am     Reply with quote

Are you trying to run an external _oscillator_ (complete module that develops the clock), or an external _crystal_. Big difference. The ECH fuse is for an external hardware oscillator module, not a crystal.

Best Wishes
maria100



Joined: 01 Feb 2012
Posts: 63

View user's profile Send private message

PostPosted: Sat Feb 11, 2012 8:01 pm     Reply with quote

Still doesn't work. Here is my config:
Code:

#include<18f25k22.h>
#device adc=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HSH                      //High speed Osc, high power 16MHz-25MHz
#FUSES NOPLLEN                  //4X HW PLL disabled, 4X PLL enabled in software
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES NOBROWNOUT               //No brownout reset
#FUSES WDT_NOSLEEP              //Watch Dog Timer, disabled during SLEEP
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#use delay(clock=64000000)
#use rs232(baud=9600, UART1)

I even changed the crystal with a other one ( 64 Mhz). I keep getting garbage data in the terminal. The baud rate is set up as it should. Using 18pf capacitors for the crystal. What could be the problem? No error on pcb. Checked twice. The internal one works just fine, but have a little bad precision.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sun Feb 12, 2012 4:38 am     Reply with quote

Quote:

I even changed the crystal with a other one ( 64 Mhz). I keep getting garbage data in the terminal. The baud rate is set up as it should. Using 18pf capacitors for the crystal. What could be the problem? No error on pcb. Checked twice.


Have you checked with an oscilloscope that the 64MHz clock is running correctly?

Have you checked with a simple LED flasher program that the system is running at the correct rate?

Quote:

The internal one works just fine, but have a little bad precision.


What do you mean?

(1) Are your readings drifting by a fractions of percent?
(2) Have you allowed for the your gate period being based on a 20MHz clock but your actual clock is ~3.2 times faster?

Mike
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
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