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

Trying to use to sample frequency counter on 16F688
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
masterat



Joined: 17 Jul 2010
Posts: 26

View user's profile Send private message

Trying to use to sample frequency counter on 16F688
PostPosted: Wed Jul 21, 2010 3:53 am     Reply with quote

Let say hi to all I'm a newbie.
I try to learning frequency counter from ccs sample code, but I don't understand about timer math calculation when I change cpu osc from 20Mhz to 8 MHz. Please advise.

code is:
Code:

#include <16F688.H>
#fuses INTRC_IO,NOWDT,PUT,NOPROTECT,BROWNOUT,NOMCLR
#use delay (clock=8000000) // 8MHz clock
 
#define LCD_DB4   PIN_C0
#define LCD_DB5   PIN_C1
#define LCD_DB6   PIN_C2
#define LCD_DB7   PIN_C5

#define LCD_E     PIN_A1
#define LCD_RS    PIN_A0
#define LCD_RW    PIN_A2

#bit t1_overflow=0x0A.5

#include <flex_lcd.c>

void main() {
   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

      lcd_gotoxy(0,1);
      printf(lcd_putc,"Frequency  Count");
      lcd_gotoxy(0,2);
      printf(lcd_putc,"%LU Hz",freq);      //and print frequency


   }
}
 
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jul 21, 2010 9:40 pm     Reply with quote

I don't think anyone wants to look at code where CCS believes they
have accuracy to 30 decimal places.

Instead, try using the count() function shown in this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=41877
masterat



Joined: 17 Jul 2010
Posts: 26

View user's profile Send private message

PostPosted: Wed Jul 21, 2010 11:22 pm     Reply with quote

Thank you PCM PROGRAMMER for quick reply.
I try to learning count.c code on 16F688A use internal osc at 8Mhz pin RA5 for input maximum count is only 44Khz. How to count to 50Mhz as ccs had claim?

http://www.ccsinfo.com/devices.php?page=exlist
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Thu Jul 22, 2010 6:48 am     Reply with quote

Where does it say it can count to 50Mhz?
masterat



Joined: 17 Jul 2010
Posts: 26

View user's profile Send private message

PostPosted: Thu Jul 22, 2010 8:38 am     Reply with quote

"A 50 mhz frequency counter " is say at this page http://www.ccsinfo.com/devices.php?page=exlist
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jul 22, 2010 1:19 pm     Reply with quote

I don't see how they can get 50 MHz operation. They're using Timer1
as a counter with an external asynchronous clock. The Electrical Specs
section of the 16F877 (and 16F688) data sheet shows the minimum clock
period in this mode is 60 ns. That means a maximum input frequency of
16.66 MHz.
masterat



Joined: 17 Jul 2010
Posts: 26

View user's profile Send private message

PostPosted: Sun Jul 25, 2010 8:12 pm     Reply with quote

Today I test CCS 50 MHz frequency counter program again and found that when Overflow, the value of variable of "freqc_high++" in this procedure no working. That mean T1_overflow never True. Whats wrong on my code? Please help.
Code:

#include <16F688.H>
#device adc=10

#fuses INTRC_IO,NOWDT,PUT,PROTECT,BROWNOUT,NOMCLR,CPD
#use delay (clock=8000000) // 8MHz clock      .5us instruction
#rom  0xfff={0x3444}

#define pushSW PIN_A3

#define LCD_DB4   PIN_C0
#define LCD_DB5   PIN_C1
#define LCD_DB6   PIN_C2
#define LCD_DB7   PIN_C5

#define LCD_E     PIN_A1
#define LCD_RS    PIN_A0
#define LCD_RW    PIN_A2

#bit t1_overflow=0x0A.5

#include <flex_lcd.c>
#include <Button.c>

void CPU_SETUP(void);

byte i;
unsigned int16 resultA,resultB;

int8 acon=1;
int8 A3 = 0;

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

 float resA,resB;
   
//==========================
void main()
 {
      CPU_SETUP();
      lcd_init();       // Always call this first.

     freqc_high=0;
   
   while(TRUE)
      {
       

      if(button(PushSW, 0, 50, 10, A3, 1))  //  button(pin, DownState, Delay, Rate, BVar, Action)
       {
       acon++;
       printf(lcd_putc, "\f"); // clear lcd after push botton
       delay_ms(100);
        }     
          if (acon==1)           // open On.
       
           {
              lcd_gotoxy(5,1);
              printf(lcd_putc,"MasterAT");
              lcd_gotoxy(0,2);
             printf(lcd_putc,"----------------");

           }
           else    if (acon==2)           // read VDC
           {
             resA=0;
             resultA=0;
             for (i=0;i<20;i++)
             {
                 set_adc_channel(3);
                 delay_ms(1);
                 resultA=resultA+read_adc();
              }
               
             resB=0;
             resultB=0;
             for (i=0;i<20;i++)
             {
                 set_adc_channel(7);
                 delay_ms(1);
                 resultB=resultB+read_adc();
              }

                 resultA=resultA/20;
                 resultB=resultB/20;
         
                  //result = 0x3fe;                           
             
               resA=(float)resultA*30/1023;   
               resB=(float)resultB*5/1023;   

               lcd_gotoxy(3,1);
               printf(lcd_putc,"Volt Monitor");

               lcd_gotoxy(0,2);
           
               if (resA>=10)
               printf(lcd_putc, "%4.2fV",resA);
               else
               printf(lcd_putc, "%5.2fV",resA);     

               lcd_gotoxy(7,2);
               printf(lcd_putc,"    ");
         
               lcd_gotoxy(11,2);
           
               if (resB>=10)
               printf(lcd_putc, "%4.2fV",resB);
               else
               printf(lcd_putc, "%5.2fV",resB);     
   
               delay_ms(300);         

            }
           else if (acon==3)      //run frequency counter           
           {
             cycles8=0;
             cycles=0;
           //  freqc_high=0;
             t1_overflow=FALSE;

                  set_timer1(0);
                  setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
                 
                  /* ___ wait one second ___  */
                 while (cycles!=0xFF)       
                 {       
                  cycles8=0;                 
                                                       
                  while (cycles8!=0xFF)     
                     {
                        if (t1_overflow)         
                        {
                        t1_overflow=0;
                        freqc_high++;         
                         }
                        else                                       
                        {
                         delay_cycles(2);                       
                         }
                    delay_cycles(19);
                    cycles8++;         
                        }
                      delay_cycles(86);      
                      cycles++;          
                     
                   }
                  delay_cycles(86);   //z 216
                    /* ___ 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);
                      freq=freqc_high+freqc_low;         
                       //use new make32 function to join lsb and msb
   
            lcd_gotoxy(0,1);
            printf(lcd_putc,"%LU Hz",freq);
            lcd_gotoxy(0,2);
            printf(lcd_putc,"%LU  %LU",freqc_low,freqc_high);      //and print frequency
 
           }
                 
           else
          acon=1;

      }
}

//---------------------------------------------------------------------

void CPU_SETUP()
{
   
   setup_comparator(NC_NC_NC_NC);   // not use comparator module
   setup_adc_ports( sAN3|sAN7 | VSS_VDD);  //set AN3,AN7 to Analog vref=VSS to VDD
   setup_adc(ADC_CLOCK_DIV_64);     //origin is 64

}


Last edited by masterat on Mon Jul 26, 2010 12:19 am; edited 1 time in total
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Mon Jul 26, 2010 12:17 am     Reply with quote

Code:
#bit t1_overflow=0x0A.5
Where did this line come from?
Have you modified it? Else, what is your compiler version number?

In my compiler (4.077) the line is correct:
Code:
#bit t1_overflow=0x0C.0


Edit: removed a erroneous statement where I mixed up Mega and Giga.


Last edited by ckielstra on Mon Jul 26, 2010 12:41 am; edited 1 time in total
masterat



Joined: 17 Jul 2010
Posts: 26

View user's profile Send private message

PostPosted: Mon Jul 26, 2010 12:35 am     Reply with quote

Code:
#bit t1_overflow=0x0C.0

Yes this line modify from original 16F877 input pin C0 to 16F688 pin A5.
My compiler is 4.109.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Mon Jul 26, 2010 12:56 am     Reply with quote

1 line, 2 errors.

The key to understanding the example code is that CCS are using the hardware Timer1 module as a counter for counting the external frequency. This hardware is physically connected to pin T1CKI, which is pin A5 in both the PIC16F877 and PIC16F688. You can not connect your signal to C0 and expect it to work.

The second problem is that the #bit instruction is not assigning the pin number but is used for mapping the t1_overflow variable to the address of the T1 Overflow Flag. Again, an address you can not change.
masterat



Joined: 17 Jul 2010
Posts: 26

View user's profile Send private message

PostPosted: Mon Jul 26, 2010 1:30 am     Reply with quote

Thank you for quick reply.


Code:
The key to understanding the example code is that CCS are using the hardware Timer1 module as a counter for counting the external frequency. This hardware is physically connected to pin T1CKI, which is pin A5 in both the PIC16F877 and PIC16F688. You can not connect your signal to C0 and expect it to work.

On my hardware 16F688 I use Pin A5 for counter frequency input and PIN_C0 assign to LCD_DB4 .When I input signel gen 80 KHz to pin A5 count display is approx 14460 seem equal 65536+14460=80Khz .

Code:
The second problem is that the #bit instruction is not assigning the pin number but is used for mapping the t1_overflow variable to the address of the T1 Overflow Flag. Again, an address you can not change.

May you give me an example code?
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Mon Jul 26, 2010 5:20 am     Reply with quote

masterat wrote:
When I input signel gen 80 KHz to pin A5 count display is approx 14460 seem equal 65536+14460=80Khz .
Yes, because when I look into your posted code I see:
Code:
         //            freq=make32(freqc_high,freqc_low);
                      freq=freqc_high+freqc_low;         
Here you (again) changed working code into something that fails.
I have no clue as to why you made this change, but it is wrong. Study the manual about what make32 does and how it is different from your implementation.

Quote:
May you give me an example code?
The example code provided by CCS is working. Use this code without modifications to the hardware or software. Then when you have seen this is working as expected you can make small changes. One change at a time. By doing it like this you will know that when the system is no longer working it was because of your last change.
masterat



Joined: 17 Jul 2010
Posts: 26

View user's profile Send private message

PostPosted: Mon Jul 26, 2010 6:04 am     Reply with quote

Thank you again for quick post reply.
Quote:
freq=make32(freqc_high,freqc_low);

I just understood on make32 function it very useful.

Now I have only one problem why timer1 overflow not fire ?
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Mon Jul 26, 2010 3:14 pm     Reply with quote

I spotted at least one new problem, but you know what? It is again one of these things were you have modified the original example program. Rolling Eyes
I don't mind helping people, but here I get the feeling you are doing it on purpose. You received a good working program and then it stopped working because you made at least three bad modifications. So far I've fixed two of your created bugs. I leave it to you to find the third one yourself.
Compare your code to the original and you will find the problem.

As hint for these type of problems:
Make a backup copy of your current program and remove everything that has nothing to do with the frequency counter. By removing as much as possible you will get get a tiny program, helping you to focus on the real problem at hand.
masterat



Joined: 17 Jul 2010
Posts: 26

View user's profile Send private message

PostPosted: Tue Jul 27, 2010 12:06 am     Reply with quote

I try to do as your hint. This is last code.
Code:
#include <16F688.h>
#fuses INTRC_IO,NOWDT,PUT,NOPROTECT,NOBROWNOUT
#use delay(clock=8000000)    //one instruction=0.5us
#rom  0xfff={0x3444}

#define LCD_DB4   PIN_C0
#define LCD_DB5   PIN_C1
#define LCD_DB6   PIN_C2
#define LCD_DB7   PIN_C5

#define LCD_E       PIN_A1
#define LCD_RS     PIN_A0
#define LCD_RW    PIN_A2


#include <flex_lcd.c>
#bit t1_overflow=0x0A.5

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

void main() {
   int cycles8, cycles;
   int32 freq;
   long freqc_high;
   long freqc_low;
   lcd_init();       // Always call this first.

   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(2);}                        //----|
         delay_cycles(19); //x
         cycles8++; //1
  }
 delay_cycles(204);      //y
 cycles++;          ///1 cycle
}
      delay_cycles(90);   //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
            lcd_gotoxy(0,1);
            printf(lcd_putc,"%LU Hz",freq);
            lcd_gotoxy(0,2);
            printf(lcd_putc,"%LU  %LU",freqc_low,freqc_high);   

   }
}

Timer1 overflow still not fire. I try to change #Fuses, look at cpu data sheet, find in ccs c manual. But I still blind.
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  Next
Page 1 of 2

 
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