Hot!Frequency Counter Using PIC18F4550

Author
BAGHEDOUD
New Member
  • Total Posts : 5
  • Reward points : 0
  • Joined: 2018/05/11 04:02:17
  • Location: 0
  • Status: offline
2018/05/15 04:38:51 (permalink)
0

Frequency Counter Using PIC18F4550

Hi everyone,
 
I'm kinda ne to PIC programming so I'm trying to make a frequency Counter with PIC18F45550, the problem is when i start the simulation on proteus i got only 200K Hz as the highest Frequency that I can read correctely. here is my Code on MikroC, I'm using 8Mhz Crys, 
 
Thank you,
 
//////////////////////////////////////////////////////////////////////////
// LCD module connections
sbit LCD_RS at RD2_bit;
sbit LCD_EN at RD3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// End LCD module connections
 
 
unsigned int Freq;
unsigned char Freq_Display[]="4294960000007295",txt[]="000";
char flag;
unsigned int Cw=0;

void interrupt(){
if(PIR1.CCP1IF==1){
PIR1.CCP1IF=0;
Cw=Cw+1;
PORTE.RE0=~PORTE.RE0;
}
else PORTE.RE0=0;
}
void main(){
Lcd_Init();
Lcd_Cmd(_LCD_CURSOR_OFF);
ADCON1=0x07;
CMCON=0x07;
TRISA=0x00;
PORTA = 0;
PORTB = 0;
PORTC = 0;
PORTD = 0;
TRISC = 0b00000100;
TRISD = 0b00000000;
T1CON = 0b00110001;
CCP1CON = 0b00000101;
INTCON = 0b11000000;
PIE1.CCP1IE=1;
TRISE=0;
while(1){
LongToStr(Cw,Freq_Display);
Lcd_Out(1,1,Freq_Display);
}
}
#1

9 Replies Related Threads

    jack@kksound
    code tags!
    • Total Posts : 2503
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: online
    Re: Frequency Counter Using PIC18F4550 2018/05/15 11:14:58 (permalink)
    +2 (2)
    From your program code:
    You are using the CCP1 module to detect the rising edge of your signal to measure, this causes an interrupt.
    In the ISR you increment your Cw counter.
    Your CCP1 module is using timer1 as the timer source and timer1 counts the Fosc/4 signal (8Mhz/4 = 2Mhz) with a prescaler setting of 8:1 so your timer1 increments at (2Mhz/8 = 250 Khz).
    Because the CCP1 is interrupting on the rising edge of your input signal I fail to see how you get a frequency by simply incrementing the Cw var. And your setting of the timer1 prescaler seemsunused. Also you are not using the values captured from timer1 by the CCP1 module (on every interrupt). And you never reset the value of Cw, it simply increments forever.
    Is this your actual code?
     
    #2
    BAGHEDOUD
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2018/05/11 04:02:17
    • Location: 0
    • Status: offline
    Re: Frequency Counter Using PIC18F4550 2018/05/16 08:00:57 (permalink)
    0
    Hi 

     
    Thank you for your reply, you are right the code is incomplete, because i wanna just the counter that can count more than 200K in one second, and i guess you make it clear for me now , thank you, the other part of my code is that i ue Timer0 as a timer to count 1Sec then i get the coutned value by timer1 and then i got the frequency of my signal, here is the full Code :
    /////////////////////////////////////////////
    // LCD module connections
    sbit LCD_RS at RD2_bit;
    sbit LCD_EN at RD3_bit;
    sbit LCD_D4 at RD4_bit;
    sbit LCD_D5 at RD5_bit;
    sbit LCD_D6 at RD6_bit;
    sbit LCD_D7 at RD7_bit;
    sbit LCD_RS_Direction at TRISD2_bit;
    sbit LCD_EN_Direction at TRISD3_bit;
    sbit LCD_D4_Direction at TRISD4_bit;
    sbit LCD_D5_Direction at TRISD5_bit;
    sbit LCD_D6_Direction at TRISD6_bit;
    sbit LCD_D7_Direction at TRISD7_bit;
    // End LCD module connections
     
     
    unsigned int Freq;
    unsigned char Freq_Display[]="4294960000007295",txt[]="000";
    char flag;
    unsigned int Time;
    unsigned int Cw=0;

    void interrupt(){
    if(INTCON.TMR0IF){
    INTCON.TMR0IF=0;
    if(Time==1000){
    Time=0;
    flag=1;
    INTCON.INT0IE=0;
    }
    else{
    Time++;
    TMR0L=0x17;
    TMR0H=0xFC;
    T0CON.TMR0ON=1;

    }
    if(PIR1.CCP1IF==1){
    PIR1.CCP1IF=0;
    Cw=Cw+1;
    }
    } }
    void main(){
    Lcd_Init();
    Lcd_Cmd(_LCD_CURSOR_OFF);
    ADCON1=0x07;
    CMCON=0x07;
    TRISA=0x00;
    PORTA = 0;
    PORTB = 0;
    PORTC = 0;
    PORTD = 0;
    TRISC = 0b00000100;
    TRISD = 0b00000000;
    T1CON = 0b00110001;
    CCP1CON = 0b00000101;
    INTCON = 0b11000000;
    PIE1.CCP1IE=1;
    INTCON.TMR0IE=1; //enable Timer0
    INTCON.TMR0IF=0; //get timer0's floag low
    TMR1L=0;
    TMR1H=0;
    PIR1.CCP1IF=0; //get capture mode's flag low
    PIR1.TMR1IF=0; //get timer1 flag low
    INTCON.GIE=1; //enable global interrupts
    INTCON.INT0IE=1; //enable external interupts interrupts
    IPR1.CCP1IP=0; //give low priority to CCP that counts egdes
    INTCON2.TMR0IP=1; //give high priority to Timer0 to count one second for frequency

    while(1){
    if(flag){
    flag=0;
    LongToStr(Cw,Freq_Display);
    Lcd_Out(1,1,Freq_Display);
    Cw=0;
    }
     
    }}
    #3
    jack@kksound
    code tags!
    • Total Posts : 2503
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: online
    Re: Frequency Counter Using PIC18F4550 2018/05/16 10:55:45 (permalink)
    +1 (1)
    To use interrupt priorities you must set the IPEN bit in the RCON register. Also you will then need two ISR functions, one for low and one for high priority.
    #4
    BAGHEDOUD
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2018/05/11 04:02:17
    • Location: 0
    • Status: offline
    Re: Frequency Counter Using PIC18F4550 2018/05/17 03:34:03 (permalink)
    0
    Hi, thanks for your reply, so what i can understand now is that the pic cant count more than 12Mhz as maximum, with a 48Mhz crystal, plus when i made 2 functions low and high in interrupt, i got no interrupt at all , even the counts that i was getting before is no more interrupting.
     
     
    /////////////////////////////////////////////////////////////////
    sbit LCD_RS at RD2_bit;
    sbit LCD_EN at RD3_bit;
    sbit LCD_D4 at RD4_bit;
    sbit LCD_D5 at RD5_bit;
    sbit LCD_D6 at RD6_bit;
    sbit LCD_D7 at RD7_bit;
    sbit LCD_RS_Direction at TRISD2_bit;
    sbit LCD_EN_Direction at TRISD3_bit;
    sbit LCD_D4_Direction at TRISD4_bit;
    sbit LCD_D5_Direction at TRISD5_bit;
    sbit LCD_D6_Direction at TRISD6_bit;
    sbit LCD_D7_Direction at TRISD7_bit;
    // End LCD module connections
     
    unsigned char Freq_Display[]="0123456789ABCDEF";
    char flag;
    unsigned int Time;
    unsigned int Freq=0;
    void interrupt_high(){
    if(INTCON.TMR0IF){
    INTCON.TMR0IF=0;
    if(Time==1000){
    Time=0;
    flag=1;
    INTCON.INT0IE=0;
    }
    else{
    Time++;
    TMR0L=0x17;
    TMR0H=0xFC;
    T0CON.TMR0ON=1;
    }
    }
    }
    void interrupt_low(){
    if(PIR1.CCP1IF==1){
    PIR1.CCP1IF=0;
    Freq=Freq+1;
    }
    }
     

    void main(){
    Lcd_Init();
    Lcd_Cmd(_LCD_CURSOR_OFF);
    RCON.IPEN=1;
    ADCON1=0x07;
    CMCON=0x07;
    TRISC = 0b00000100;
    T1CON = 0b00110001;
    CCP1CON = 0b00000101;
    INTCON = 0b11000000;
    PIE1.CCP1IE=1;
    INTCON.TMR0IE=1; //enable Timer0
    INTCON.TMR0IF=0; //get timer0's floag low
    PIR1.CCP1IF=0; //get capture mode's flag low
    PIR1.TMR1IF=0; //get timer1 flag low
    INTCON.GIE=1; //enable global interrupts
    INTCON.INT0IE=1; //enable external interupts interrupts
    IPR1.CCP1IP=0; //give low priority to CCP that counts egdes
    INTCON2.TMR0IP=1; //give high priority to Timer0 to count one second for frequency
    Lcd_Out(1,1,"Frequence:");
    Lcd_Out(2,15,"Hz");
    while(1){
    if(flag){
    flag=0;
    IntToStr(Freq,Freq_Display);
    Lcd_Out(2,1,Freq_Display);
    Freq=0;
    }
    }
    }
    #5
    jack@kksound
    code tags!
    • Total Posts : 2503
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: online
    Re: Frequency Counter Using PIC18F4550 2018/05/18 09:19:21 (permalink)
    +1 (1)
    Two things (at least):
    When using priority interrupts (as you are) this:
    INTCON.GIE=1; //enable global interrupts

    is more correctly written as:
    INTCON.GIEH=1; // enable HIGH priority interrupts

    and you must add:
    INTCON.GIEL=1;//enable LOW priority interrupts

    Also ALLWAYS completely set-up ALL aspects of the interrupts before you set the global enables, you are not doing that in your code.
    #6
    BAGHEDOUD
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2018/05/11 04:02:17
    • Location: 0
    • Status: offline
    Re: Frequency Counter Using PIC18F4550 2018/05/19 16:02:30 (permalink)
    0
    Hi thank you for your reply, sorry but i didnt get the  last thing u said, because i did everything but it didnt work somehow, 
     
    //////////////////////////////////////////////////////
    sbit LCD_RS at RD2_bit;
    sbit LCD_EN at RD3_bit;
    sbit LCD_D4 at RD4_bit;
    sbit LCD_D5 at RD5_bit;
    sbit LCD_D6 at RD6_bit;
    sbit LCD_D7 at RD7_bit;
    sbit LCD_RS_Direction at TRISD2_bit;
    sbit LCD_EN_Direction at TRISD3_bit;
    sbit LCD_D4_Direction at TRISD4_bit;
    sbit LCD_D5_Direction at TRISD5_bit;
    sbit LCD_D6_Direction at TRISD6_bit;
    sbit LCD_D7_Direction at TRISD7_bit;
    // End LCD module connections
    unsigned char Freq_Display[]="0123456789ABCDEF";
    char flag;
    unsigned int Time;
    unsigned int Freq=0;
    void interrupt_high(){
    if(INTCON.TMR0IF){
    INTCON.TMR0IF=0;
    if(Time==1000){
    Time=0;
    flag=1;
    INTCON.INT0IE=0;
    }
    else{
    Time++;
    TMR0L=0x17;
    TMR0H=0xFC;
    T0CON.TMR0ON=1;
    }
    }
    }
    void interrupt_low(){
    if(PIR1.CCP1IF==1){
    PIR1.CCP1IF=0;
    Freq=Freq+1;
    }
    }

    void main(){
    Lcd_Init();
    Lcd_Cmd(_LCD_CURSOR_OFF);
    RCON.IPEN=1;
    ADCON1=0x07;
    CMCON=0x07;
    TRISC = 0b00000100;
    T1CON = 0b00110001;
    CCP1CON = 0b00000101;
    INTCON = 0b11110000;
    PIE1.CCP1IE=1;
    INTCON.TMR0IE=1; //enable Timer0
    INTCON.TMR0IF=0; //get timer0's floag low
    PIR1.CCP1IF=0; //get capture mode's flag low
    PIR1.TMR1IF=0; //get timer1 flag low
    INTCON.INT0IE=1; //enable external interupts interrupts
    IPR1.CCP1IP=0; //give low priority to CCP that counts egdes
    INTCON2.TMR0IP=1; //give high priority to Timer0 to count one second for frequency
    Lcd_Out(1,1,"Frequence:");
    Lcd_Out(2,15,"Hz");
    INTCON.GIEH=1; //enable global interrupts
    INTCON.GIEL=1; //enable global interrupts
    while(1){
    if(flag){
    flag=0;
    IntToStr(Freq,Freq_Display);
    Lcd_Out(2,1,Freq_Display);
    Freq=0;
    }
    }
    }
    /////////////////////////////////////
     
    here is what i got in proteus :
     

    Attached Image(s)

    #7
    NorthGuy
    Super Member
    • Total Posts : 4853
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: Frequency Counter Using PIC18F4550 2018/05/19 20:48:38 (permalink)
    +1 (1)
    If you want to count higher frequencies, do not use CCP. Instead, use a timer connected to an external pin (where the frequency to be counted comes in). Read the timer at regular intervals. Say, if you read 1000 times a second, the difference between consecutive counts will give you frequency in kHz.
     
    You can use pre-scaler on the counting timer. With pre-scaler, most PICs can go up to 50MHz (don't know about yours, it's too old, see the datasheet).
     
    #8
    1and0
    Access is Denied
    • Total Posts : 7852
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Frequency Counter Using PIC18F4550 2018/05/19 21:39:27 (permalink)
    +2 (2)
    NorthGuy
    You can use pre-scaler on the counting timer. With pre-scaler, most PICs can go up to 50MHz (don't know about yours, it's too old, see the datasheet).

    Timer0 on most, if not all, 8-bit PIC devices can read up to 50 MHz with the prescaler.
    #9
    BAGHEDOUD
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2018/05/11 04:02:17
    • Location: 0
    • Status: offline
    Re: Frequency Counter Using PIC18F4550 2018/05/20 06:27:52 (permalink)
    +1 (1)
    thank you for your replies, i'll try this solution for now , because i want to counter a frequency up to 35Mhz or 40Mhz. 
    #10
    Jump to:
    © 2018 APG vNext Trial Version 4.5