|
|
View previous topic :: View next topic |
Author |
Message |
masterat
Joined: 17 Jul 2010 Posts: 26
|
Trying to use to sample frequency counter on 16F688 |
Posted: Wed Jul 21, 2010 3:53 am |
|
|
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
|
|
|
masterat
Joined: 17 Jul 2010 Posts: 26
|
|
Posted: Wed Jul 21, 2010 11:22 pm |
|
|
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
|
|
Posted: Thu Jul 22, 2010 6:48 am |
|
|
Where does it say it can count to 50Mhz? |
|
|
masterat
Joined: 17 Jul 2010 Posts: 26
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 22, 2010 1:19 pm |
|
|
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
|
|
Posted: Sun Jul 25, 2010 8:12 pm |
|
|
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
|
|
Posted: Mon Jul 26, 2010 12:17 am |
|
|
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
|
|
Posted: Mon Jul 26, 2010 12:35 am |
|
|
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
|
|
Posted: Mon Jul 26, 2010 12:56 am |
|
|
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
|
|
Posted: Mon Jul 26, 2010 1:30 am |
|
|
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
|
|
Posted: Mon Jul 26, 2010 5:20 am |
|
|
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
|
|
Posted: Mon Jul 26, 2010 6:04 am |
|
|
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
|
|
Posted: Mon Jul 26, 2010 3:14 pm |
|
|
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.
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
|
|
Posted: Tue Jul 27, 2010 12:06 am |
|
|
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. |
|
|
|
|
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
|