|
|
View previous topic :: View next topic |
Author |
Message |
theasus
Joined: 31 May 2009 Posts: 79
|
Frequency meter with Pic 16F877 |
Posted: Tue Jan 05, 2010 11:00 am |
|
|
I want to design a frequency meter. Actually I will count pulses for one minute? Could you propose any method for this operation please? I think RB0 can be usefull but I couldn't determine yet. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
theasus
Joined: 31 May 2009 Posts: 79
|
|
Posted: Sun Jan 10, 2010 3:56 am |
|
|
Ok I found a code for this operation but I couldn't understand some codes as shown below;
Code: |
1-#define BytePtr(var, offset) (char *)((char*)&var + offset)
------------------------------------------------------------------
2-*BytePtr(current_ccp, 2) = timer_ext_copy;
----------------------------------------------------------------------
3-g32_ccp_delta = (current_ccp > old_ccp) ? current_ccp - old_ccp : current_ccp + (0x1000000 - old_ccp);
|
---------------------------------------------------------------------------
-----------------------------------------------------------------------------
Here is my program;
Code: |
#include <16F877.H>
#fuses HS,NOWDT, PUT, BROWNOUT, NOLVP // 20 MHz xtal
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#priority CCP1, TIMER1
#define BytePtr(var, offset) (char *)((char*)&var + offset)
#byte PIR1 = 0xF9E
#bit TMR1IF = PIR1.0
int8 gc_timer1_extension = 0;
int8 gc_capture_flag = FALSE;
int32 g32_ccp_delta;
//------------------------------------------------------
#int_timer1
void timer1_isr(void)
{
gc_timer1_extension++;
}
//------------------------------------------------------
#int_ccp1
void ccp1_isr(void)
{
char timer_ext_copy;
int32 current_ccp;
static int32 old_ccp = 0;
gc_capture_flag = TRUE;
current_ccp = (int32)CCP_1;
timer_ext_copy = gc_timer1_extension;
if(TMR1IF)
{
if(*BytePtr(current_ccp, 1) < 2)
timer_ext_copy++;
gc_timer1_extension++;
TMR1IF = 0;
}
*BytePtr(current_ccp, 2) = timer_ext_copy;
g32_ccp_delta = (current_ccp > old_ccp) ? current_ccp - old_ccp : current_ccp + (0x1000000 - old_ccp);
old_ccp = current_ccp;
}
//=======================
void main()
{
float frequency;
int32 current_ccp_delta;
set_timer1(0);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_ccp1(CCP_CAPTURE_RE);
clear_interrupt(INT_TIMER1);
enable_interrupts(INT_TIMER1);
clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
while(1)
{
if(gc_capture_flag == TRUE)
{
disable_interrupts(GLOBAL);
current_ccp_delta = g32_ccp_delta;;
enable_interrupts(GLOBAL);
frequency = (5000000L / (float)current_ccp_delta);
printf("%4.2f\n\r", frequency);
gc_capture_flag = FALSE;
}
}
}
|
Thanks for considering... |
|
|
lopb
Joined: 09 Dec 2010 Posts: 6
|
|
Posted: Thu Dec 09, 2010 9:26 am |
|
|
Hi, I'm using this code in a 18f452 and measures 30hz instead the real which is 50hz, can you help me? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 09, 2010 2:09 pm |
|
|
The code by Theasus is weird, because he's using a 16F877 but the
register address of PIR1 is for an 18F PIC. That won't work.
Then in your code, you claim to be using an 18F452, but you still quote
code with a 16F877 in the #include line.
Post the true, actual code that you are testing. Also post your compiler
version. Post the high and low voltage levels of your input signal.
Look at the signal with an oscilloscope to see this. |
|
|
lopb
Joined: 09 Dec 2010 Posts: 6
|
|
Posted: Mon Dec 13, 2010 9:33 am |
|
|
PCM programmer wrote: | The code by Theasus is weird, because he's using a 16F877 but the
register address of PIR1 is for an 18F PIC. That won't work.
Then in your code, you claim to be using an 18F452, but you still quote
code with a 16F877 in the #include line.
Post the true, actual code that you are testing. Also post your compiler
version. Post the high and low voltage levels of your input signal.
Look at the signal with an oscilloscope to see this. |
Sorry, there is my code:
Code: | #if defined(__PCH__)
#include <18F452.h>
//////// Fuses: LP,XT,HS,RC,EC,EC_IO,H4,RC_IO,PROTECT,NOPROTECT,OSCSEN
//////// Fuses: NOOSCSEN,NOBROWNOUT,BROWNOUT,WDT1,WDT2,WDT4,WDT8,WDT16,WDT32
//////// Fuses: WDT64,WDT128,WDT,NOWDT,BORV20,BORV27,BORV42,BORV45,PUT,NOPUT
//////// Fuses: CCP2C1,CCP2B3,NOSTVREN,STVREN,NODEBUG,DEBUG,NOLVP,LVP,WRT
//////// Fuses: NOWRT,NOWRTD,WRTD,NOWRTB,WRTB,WRTC,NOWRTC,CPD,NOCPD,CPB
//////// Fuses: NOCPB,EBTR,NOEBTR,EBTRB,NOEBTRB
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES NOOSCSEN
#FUSES NOPUT
#FUSES CCP2C1
#FUSES NOSTVREN
#FUSES NODEBUG
#FUSES NOWRTD
#FUSES NOWRTB
#FUSES NOWRTC
#FUSES NOCPB
#FUSES NOEBTR
#FUSES NOEBTRB
#use delay(clock = 20000000)
#use rs232 (baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8)
#priority CCP1, TIMER1
#define BytePtr(var, offset) (char *)((char*)&var + offset)
#byte PIR1 = 0x0C
#bit TMR1IF = PIR1.0
int8 gc_timer1_extension = 0;
int8 gc_capture_flag = FALSE;
int32 g32_ccp_delta;
//------------------------------------------------------
#int_timer1
void timer1_isr(void)
{
gc_timer1_extension++;
}
//------------------------------------------------------
#int_ccp1
void ccp1_isr(void)
{
char timer_ext_copy;
int32 current_ccp;
static int32 old_ccp = 0;
gc_capture_flag = TRUE;
current_ccp = (int32)CCP_1;
// Get local copy of the timer ext.
timer_ext_copy = gc_timer1_extension;
if(TMR1IF)
{
if(*BytePtr(current_ccp, 1) < 2) // Was CCP captured after Timer1 wrapped?
timer_ext_copy++; // If so, inc the copy of the timer ext.
// Since we know a timer interrupt is pending, let's just
// handle it here and now. That saves a little load off
// the processor.
gc_timer1_extension++; // Increment the real timer extension
TMR1IF = 0; // Then clear the Timer1 interrupt
}
// Insert the timer extension into the proper place in the 32-bit
// CCP value.
// ie., Insert it into location "EE" as follows: 0x00EEnnnn
// (nnnn = the CCP).
*BytePtr(current_ccp, 2) = timer_ext_copy;
g32_ccp_delta = (current_ccp > old_ccp) ? current_ccp - old_ccp : current_ccp + (0x1000000 - old_ccp);
// Save the current ccp value for next time.
old_ccp = current_ccp;
}
//=======================
void main()
{
float frequency;
int32 current_ccp_delta;
set_timer1(0);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_ccp1(CCP_CAPTURE_RE);
// Enable interrupts.
clear_interrupt(INT_TIMER1);
enable_interrupts(INT_TIMER1);
clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
while(1)
{
if(gc_capture_flag == TRUE)
{
disable_interrupts(GLOBAL);
current_ccp_delta = g32_ccp_delta;;
enable_interrupts(GLOBAL);
frequency = (5000000L / (float)current_ccp_delta);
printf("%4.2f\n\r", frequency);
gc_capture_flag = FALSE;
}
else
{
printf("No signal\n\r");
}
delay_ms(500);
}
} |
I'm relatively new on this, can you tell me what should I change in this code written for 16f877 on 18f452?
Right now only says no frequency, and the loop is not working, it says none signal only once.
Thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 13, 2010 2:15 pm |
|
|
Right, but I also asked for your compiler version. If you want me to test
it, I need to install your exact version. |
|
|
lopb
Joined: 09 Dec 2010 Posts: 6
|
|
Posted: Tue Dec 14, 2010 2:55 pm |
|
|
PCM programmer wrote: | Right, but I also asked for your compiler version. If you want me to test
it, I need to install your exact version. |
OK, thank you.
My compiler version is 4.104 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Dec 14, 2010 3:25 pm |
|
|
That code seems to have problems. I don't want to trouble-shoot it.
Use the following code instead. I ran it just now on a 18F452 on a
PicDem2-Plus board, with a B&K Function Generator putting out a 239 Hz
0v to 5v square wave (50% duty cycle), and I got this output in a
TeraTerm window:
Quote: |
239 Hz
239 Hz
239 Hz
239 Hz
239 Hz
239 Hz
239 Hz
239 Hz
239 Hz
239 Hz
|
I tested it with CCS versions 4.104 and 4.114 and it works with both.
Code: |
#include <18F452.h>
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock = 20000000)
#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;
int16 frequency;
set_timer1(0);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_ccp1(CCP_CAPTURE_RE);
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 = (int16)(5000000L / current_ccp_delta);
printf("%lu Hz\n\r", frequency);
delay_ms(500);
}
} |
|
|
|
lopb
Joined: 09 Dec 2010 Posts: 6
|
|
Posted: Wed Dec 15, 2010 7:22 am |
|
|
Is not working PCM
Your code is more clean than the other.
i have a rectified signal from the 50hz of my line (just the positive cycle) with a diode and a zener, this singal is very clear i believe.
The signal must be right, because it was showing 50hz in the 16f877.
i'm getting a constant of 3528hz
Any idea?
thanks again |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Dec 15, 2010 1:03 pm |
|
|
To reduce the lower limit on the frequency range, for the tachometer
program, you can increase the pre-scaler on Timer1. Edit the line in
bold below, and change it to a divisor of 8:
Quote: |
void main()
{
int16 current_ccp_delta;
int16 frequency;
set_timer1(0);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
setup_ccp1(CCP_CAPTURE_RE);
|
Then adjust the frequency equation. Also divide it by 8, as shown in
bold below:
Quote: | while(1)
{
disable_interrupts(GLOBAL);
current_ccp_delta = isr_ccp_delta;
enable_interrupts(GLOBAL);
frequency = (int16)((5000000L/8) / current_ccp_delta);
|
Then the program should work down to approximately 9 Hz. |
|
|
lopb
Joined: 09 Dec 2010 Posts: 6
|
|
Posted: Thu Dec 16, 2010 8:43 am |
|
|
Thank you PCM, it is working now. |
|
|
lopb
Joined: 09 Dec 2010 Posts: 6
|
PCM i was wondering if u have time to check this. |
Posted: Thu Dec 16, 2010 3:16 pm |
|
|
PCM, I should solve this problem. But, I think you are faster than me. If you can, take a look to this: http://dpaste.org/LHoZ/ I am using your code inside a more large program. The problem is that I'm not getting the frequency.
Anyway, if you can, otherwise I will keep working on it.
Thanks again man. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 16, 2010 3:34 pm |
|
|
You have too much code. I don't really want to look at a lot of code.
However, here is a suggestion. Give the INT_CCP1 interrupt the highest
priority. It may help. Add the statement shown in bold below:
Quote: | #include <18F452.h>
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=20000000)
#priority CCP1, TIMER2, RB // Set interrupt priority
|
|
|
|
MAKInnovation
Joined: 16 Nov 2010 Posts: 61
|
|
Posted: Thu Dec 30, 2010 1:12 am |
|
|
how can we print int32 with printf command
& can we get frequency upto 1MHz with this code |
|
|
|
|
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
|