Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Why this PIC18F45K22 based frequency counter not working?

Status
Not open for further replies.

milan.rajik

Banned
Joined
Apr 1, 2013
Messages
2,524
Helped
540
Reputation
1,078
Reaction score
524
Trophy points
1,393
Activity points
0
Why this PIC18F45K22 based frequency counter not working?

I am using PIC18F45K22 and 20 MHz crystal. I am testing in Proteus and also hardware but in Proteus it gives 216 Hz for 1500 Hz and in hardware it is not at all working. I am using T0CKI pin to read the input pulses. I think all registers are configured properly. I also lit an LED in hardware to see if WDT is resetting but no, WDT is not resetting. So, problem is something else. Please help me to solve the problem. I am attaching complete mikroC PRO PIC project files. I am feeding CCP1 to RA4/T0CKI. I have set PWM freq to 1500 Hz.

This is the code.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
sbit Data7219 at LATD0_bit;
sbit Load7219 at LATD1_bit ;
sbit Clk7219 at LATD2_bit;
 
sbit Data7219_Direction at TRISD0_bit;
sbit Load7219_Direction at TRISD1_bit;
sbit Clk7219_Direction at TRISD2_bit;
 
const unsigned char Font_B[16] = {0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,
                                  0x7f,0x7b,0x77,0x1f,0x4e,0x3d,0x4f,0x47
};
 
void Send7219 (char,char);
void Send7219byte(char);
void MAX7219init();
void Display(unsigned long);
 
char freq[17];
unsigned long frequency = 0;
char start = 0;
char counter = 0, done_ = 0;
 
//Timer1
//Prescaler 1:8; TMR1 Preload = 3036; Actual Interrupt Time : 100 ms
 
//Place/Copy this part in declaration section
 
void interrupt() {
 
    if(TMR0IF_bit) {
         TMR0IF_bit = 0;
         ++frequency;                
    }
    
    if(TMR1IF_bit) {
        TMR1IF_bit = 0;
        TMR1H = 0x0B;
        TMR1L = 0xDC;
        //Enter your code here
        if(++counter == 10) {        
               TMR0ON_bit = 0;
               TMR0IE_bit = 0;
               TMR1IE_bit = 0;
               counter = 0;
               done_ = 1;
        }
    }   
}
 
void MAX7219init() {
    Data7219_Direction = 0;
    Load7219_Direction = 0;
    Clk7219_Direction = 0;
    Data7219 = 0;
    Load7219 = 0;
    Clk7219 = 0;
    Send7219(0x09, 0x00); //Decode Mode
    Send7219(0x0A, 0x05); //Brightness
    Send7219(0x0B, 0x07); //Scan limit
    Send7219(0x0C, 0x01);
    Send7219(0x0F, 0x00);
}
 
void Send7219(char Digit,char Data) {
    Send7219byte(Digit);
    Send7219byte(Data);
    Data7219 = 0;
    Load7219 = 1;
    Delay_us(20);
    Load7219 = 0;
}
 
void Send7219byte(char byte) {
 
    unsigned char i;
 
    for(i = 0; i < 8; i++)
    {
        if(byte & 0x80)
                Data7219 = 1;
        else
                Data7219 = 0;
 
        Clk7219 = 1;
        Delay_us(50);
        Clk7219 = 0;
 
        byte <<= 1;
    }
}
 
void Display(unsigned long myUInt) {
 
        unsigned char dispskip;         // add 1 if "." found within string
        unsigned char i, str[30];
 
        LongToStr(myUInt, str);     //Convert float value to string
        Ltrim(str);                     //remove spaces padded to left of string
        dispskip = strlen(str) - 1;
 
        if(dispskip >= 8)dispskip = 7;
 
        i = 0;
        
        while(i <= dispskip) {
 
                if((str[dispskip-i] >= 0x30) && (str[dispskip - i] <= 0x39)) {
                      Send7219(i+1, (Font_B[str[dispskip-i] - 0x30]));//0-9
                }               
 
                i++;
        }
 
        
        /*while(i <= 8) {
              Send7219(i, 0);
              i++;
        }*/
}
 
void main() {
 
    CM1CON0 = 0x00;
    CM2CON0 = 0x00;
    
    ANSELA = 0x00;
    ANSELB = 0x00;
    ANSELC = 0x00;
    ANSELD = 0x00;
    ANSELE = 0x00;
       
    TRISA = 0xF0;
    TRISB = 0x00;
    TRISC = 0x00;
    TRISD = 0x00;
    TRISE = 0x08;
 
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x08;
    
    LATA = 0x00;
    LATB = 0x00;
    LATC = 0x00;
    LATD = 0x00;
    LATE = 0x00;  
    
    MAX7219init();
    Display(frequency);
    
    PWM1_Init(1500);
    PWM1_Set_Duty(127);
    PWM1_Start();
    
    Delay_ms(2000);
        
    while(1) {
 
       if(start == 0) {
            TMR0H = 0;
            TMR0L = 0;       
            T1CON = 0x31;
            INTCON = 0xC0;
            T0CON = 0b10101000;
            TMR1IF_bit = 0;
            TMR0IF_bit = 0;
            TMR1H = 0x0B;
            TMR1L = 0xDC;
            TMR0IE_bit = 1;   
            TMR1IE_bit = 1;         
    
            start = 1;            
       }
       
       if(done_) {
            frequency = (frequency * 65536) + ((TMR0H << 8) + TMR0L);
            Display(frequency);            
            frequency = 0;
            done_ = 0;
            start = 0;
       }
       
       LATD.F7 = 1;
    }
}



- - - Updated - - -

I made PIC16F877A based Frequency Counter and Tachometer and it gives exact values. In Proteus simulation use Clock model to feed clock pulses. I have also implemented code for CCP1 to generate 1500 Hz PWM, 50% duty. You can also feed that and check. It gives 1495 instead of 1500 Hz. I tested it both in Proteus and hardware and I get the same values in both. It is the problem of mikroC PRO PIC PWM library. It generated 1495 Hz for 1500 Hz. I fed 10 KHz from seeedstudio's DSO Quad to hardware PIC and it gave exact 10000 Hz without any fluctuations in reading. I have attached Proteus 8.1 SP1 format files. I will soon post code and video. My Camera battery is charging. I will improve the code to make a 60 Mhz frequency counter.

- - - Updated - - -

Edit:

videos attached. Shows testing in hardware (PIC16F877A). DSO Quad is feeding 100 KHz and I get 100000, 100006 and 100007 Hz readings in hardware. Maybe it is problem of DSO Quad. I don't have better frequency generator and counter to check if DSO Quad output is stable or not. Also simulation video attached. It shows values for different input values.

@FvM

Is this precision enough ?

I will make another project which uses Timer1 prescalar in counter mode and make it measure 50 MHz.
 

Attachments

  • PIC18F45K22 based Freq Counter.rar
    105.7 KB · Views: 89
  • PIC16F877A + MAX7219 Frequency Counter.rar
    24.7 KB · Views: 82
  • PIC16F877A + MAX7219 Tachometer.rar
    24.7 KB · Views: 77
  • video.rar
    6.1 MB · Views: 88
Last edited:

I use a different compiler so I can't use your code directly but I can't see why you are using the variable 'frequency' as you do. As you increment it at each interrupt from TMR0 you are effectively dividing your reading by 256. I am assuming the frequency you are measuring is fed to the TMR0 clock input. It would seem more sensible not to divide it but to alter the measurement window instead. At the moment, because you divide by 256 you restrict your accuracy to multiples of 256 counts.

If you used bit names and comments it would be a lot easier to follow what you are doing. I'm afraid I'm not prepared to spend time looking through the data sheet to see what each bit in the hex values repesents.

Brian.
 

Ok. This is related to PIC18F45K22 code in port #1.

@betwixt


Code C - [expand]
1
2
3
4
if(TMR0IF_bit) {
         TMR0IF_bit = 0;
         ++frequency;                
    }



frequency is a unsigned long type and Timer0 is configured as 16 bit counter. So, when counter overflows then var frequency is incremented. If freq was 65537 then for 65536 the frequency var would hold 1 and I would get (1 * 65536) + ((TMR0H << 8) + TMR0L). If TMR0H and TMR0L were 1 then I would get 65537 Hz as result.


about T0CON = 0b10101000;

it is

bit 7 TMR0ON: Timer0 On/Off Control bit
1 = Enables Timer0
0 = Stops Timer0
bit 6 T08BIT: Timer0 8-bit/16-bit Control bit
1 = Timer0 is configured as an 8-bit timer/counter
0 = Timer0 is configured as a 16-bit timer/counter
bit 5 T0CS: Timer0 Clock Source Select bit
1 = Transition on T0CKI pin
0 = Internal instruction cycle clock (CLKOUT)
bit 4 T0SE: Timer0 Source Edge Select bit
1 = Increment on high-to-low transition on T0CKI pin
0 = Increment on low-to-high transition on T0CKI pin
bit 3 PSA: Timer0 Prescaler Assignment bit
1 = TImer0 prescaler is NOT assigned. Timer0 clock input bypasses prescaler.
0 = Timer0 prescaler is assigned. Timer0 clock input comes from prescaler output.
bit 2-0 T0PS<2:0>: Timer0 Prescaler Select bits
111 = 1:256 prescale value
110 = 1:128 prescale value
101 = 1:64 prescale value
100 = 1:32 prescale value
011 = 1:16 prescale value
010 = 1:8 prescale value
001 = 1:4 prescale value
000 = 1:2 prescale value





Edit


And this is the result (video) of testing in hardware with a 10 KHz clock pulse. PWM1 of 1500 Hz if fed to DSO Quad. I see that it is not exact 1500 Hz.

For 10 KHz I get 10000 and 10001 Hz fluctuating. Maybe again it is problem of DSO Quad signal generator.
 
Last edited by a moderator:

hello,

For 10 KHz I get 10000 and 10001 Hz fluctuating.

it could be normal.. because measuring round value, so +- 1 digit => +-1 Hz
and also temperature shift => Quartz FOSC shift

for lower frequency , less than 2000Hz, i wrote a programe to generate a frequency at +- 0,05Hz of resolution, ( NOT the ACCURACY !)
with a DDS generator.. so the target is made by a flotating point value..
I checked it with an oscilloscope and Lissajoux figure ..
and also with a tektronic Scope to get freq value.. same as my target +- 0,05Hz.
used in my DDS generator

and for low Frequency measure, i used CCP capture to measure the periode, not direct the frequency.
CCPx capture is not adapted for high frequency measure.


It is very difficult to check EXACT value without a good reference.. some radio emiter ?
 

@paulfjujo

Can you post your project ?

I have ordered DDS signal generator. Once I get it I will test with it and will update here. I also need a good frequency counter for doing calibration.

- - - Updated - - -

Edit:

Fixed the code. I had done a mistake. A function definition contained double as arg and the function prototype had unsigned long instead of double. Now the value doesn't fluctuate. It is stable. See video. New .hex file and Proteus files attached.
 
Last edited by a moderator:

Please see the attached videos. I made PIC18F45K22 Frequency Counter using T1CKI and 1:8 Prescalar. I tested it in hardware. The videos show the Frequency Counter (FC) displaying 50Kz, 100KHz, 200KHz, 500KHz, 1MHz, 2MHz, 4 MHz, 6 MHz and 8 MHz fed from DSO Quad. Are the values I am getting Ok ?

I also tried Gate Control method but it didn't work and so I disabled Gate Control configuration and tested. Here is my code. Please tell me how to use Gate Control to make a FC which can measure 50 MHz.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
#include "float2ascii.h"
 
sbit MAX7219_DATA at RD0_bit;
sbit MAX7219_CS at RD1_bit ;
sbit MAX7219_CLK at RD2_bit;
 
sbit MAX7219_DATA_Direction at TRISD0_bit;
sbit MAX7219_CS_Direction at TRISD1_bit;
sbit MAX7219_CLK_Direction at TRISD2_bit;
 
const unsigned char Font_B[16] = {0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,0x7f,0x7b,0x77,0x1f,0x4e,0x3d,0x4f,0x47};
char myFlags = 0;
unsigned long iFrequency = 0;
double fFrequency = 0.0;
 
sbit freqC_or_tacho at myFlags.B0;
 
void MAX7219_Send_Byte(char);
void MAX7219_Send(char, char);
void MAX7219_Init();
void MAX7219_Display(double);
 
void interrupt() {
    if(TMR1IF_bit) {
         TMR1IF_bit = 0;
         ++iFrequency;                
    }
    
    if(INT0IF_bit) {
         INT0IF_bit = 0;
         freqC_or_tacho = ~freqC_or_tacho;    
    }       
}
 
void MAX7219_Init() {
    MAX7219_DATA_Direction = 0;
    MAX7219_CS_Direction = 0;
    MAX7219_CLK_Direction = 0;
    MAX7219_DATA = 0;
    MAX7219_CS = 0;
    MAX7219_CLK = 0;
    MAX7219_Send(0x09, 0x00); //Decode Mode
    MAX7219_Send(0x0A, 0x05); //Brightness
    MAX7219_Send(0x0B, 0x07); //Scan limit
    MAX7219_Send(0x0C, 0x01);
    MAX7219_Send(0x0F, 0x00);
}
 
void MAX7219_Send(char digit, char data_) {
    MAX7219_Send_Byte(digit);
    MAX7219_Send_Byte(data_);
    MAX7219_DATA = 0;
    MAX7219_CS = 1;
    Delay_us(20);
    MAX7219_CS = 0;
}
 
void MAX7219_Send_Byte(char byte) {
    unsigned char i;
 
    for(i = 0; i < 8; i++, byte <<= 1)
    {
        if(byte & 0x80)
                MAX7219_DATA = 1;
        else
                MAX7219_DATA = 0;
 
        MAX7219_CLK = 1;
        Delay_us(50);
        MAX7219_CLK = 0;        
    }
}
 
void MAX7219_Display(double myFlt) {
 
        unsigned char dispskip;         
        unsigned char i, dp, str[30];
 
        float2ascii(myFlt, str, 1);     
        Ltrim(str);                    
        dispskip = strlen(str) - 1;
 
        if(dispskip >= 8)dispskip = 7;
 
        i = 0;
        dp = 0;
        while(i <= dispskip) {
 
                if((str[dispskip-i] >= 0x30) && (str[dispskip - i] <= 0x39) && (dp == 0)) {
                      MAX7219_Send(i+1, (Font_B[str[dispskip-i] - 0x30]));//0-9
                }
 
                if((str[dispskip-i] >= 0x30) && (str[dispskip - i] <= 0x39) && (dp)) {
                      MAX7219_Send(i, (Font_B[str[dispskip-i] - 0x30]));//0-9
                }
 
                if(str[dispskip-i] == '.') {
                       MAX7219_Send(i+1, (Font_B[str[dispskip-(i+1)] - 0x30]) | 0x80);//
                       i++;
                       dp = 1;
                }
 
                i++;
        }
 
        while(i <= 8) {
              MAX7219_Send(i, 0);
              i++;
        }
}
 
void main() {
    
    CM1CON0 = 0x00;
    CM2CON0 = 0x00;
        
    ANSELA = 0x00;
    ANSELB = 0x00;
    ANSELC = 0x00;
    ANSELD = 0x00;
    ANSELE = 0x00;
        
    TRISA = 0xF0;
    TRISB = 0x01;
    TRISC = 0x01;
    TRISD = 0x00;
    TRISE = 0x08;
    
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;
        
    LATA = 0x00;
    LATB = 0x00;
    LATC = 0x00;
    LATD = 0x00;
    LATE = 0x00;  
        
    MAX7219_Init();
    MAX7219_Display(iFrequency);
    
    /*        
    PWM1_Init(50000);
    PWM1_Set_Duty(127);
    PWM1_Start();
    */
        
    INTEDG0_bit = 1;
    INT0IF_bit = 0;
    INT0IE_bit = 1;
        
    while(1) {
 
            /*
            TMRxCS<1:0>: Timer1/3/5 Clock Source Select bits
            11 =Reserved. Do not use.
            10 =Timer1/3/5 clock source is pin or oscillator:
            If TxSOSCEN = 0:
            External clock from TxCKI pin (on the rising edge)
            If TxSOSCEN = 1:
            Crystal oscillator on SOSCI/SOSCO pins
            01 =Timer1/3/5 clock source is system clock (F OSC )
            00 =Timer1/3/5 clock source is instruction clock (F OSC /4)
            bit 5-4 TxCKPS<1:0>: Timer1/3/5 Input Clock Prescale Select bits
            11 = 1:8 Prescale value
            10 = 1:4 Prescale value
            01 = 1:2 Prescale value
            00 = 1:1 Prescale value
            bit 3 TxSOSCEN: Secondary Oscillator Enable Control bit
            1 = Dedicated Secondary oscillator circuit enabled
            0 = Dedicated Secondary oscillator circuit disabled
            bit 2 TxSYNC: Timer1/3/5 External Clock Input Synchronization Control bit
            TMRxCS<1:0> = 1X
            1 = Do not synchronize external clock input
            0 = Synchronize external clock input with system clock (F OSC )
            TMRxCS<1:0> = 0X
            This bit is ignored. Timer1/3/5 uses the internal clock when TMRxCS<1:0> = 1X.
            bit 1 TxRD16: 16-Bit Read/Write Mode Enable bit
            1 = Enables register read/write of Timer1/3/5 in one 16-bit operation
            0 = Enables register read/write of Timer1/3/5 in two 8-bit operation
            bit 0 TMRxON: Timer1/3/5 On bit
            1 = Enables Timer1/3/5
            0 = Stops Timer1/3/5
            Clears Timer1/3/5 Gate flip-flop
            */
            
            TMR1IF_bit = 0;
            TMR1H = 0;
            TMR1L = 0;
            TMR1CS1_bit = 1;
            TMR1CS0_bit = 0;
            T1CKPS1_bit = 1;
            T1CKPS0_bit = 1;
            T1SOSCEN_bit = 0;
            T1SYNC_bit = 0;
            T1RD16_bit = 0;
            
            /*
            TMRxGE: Timer1/3/5 Gate Enable bit
            If TMRxON = 0:
            This bit is ignored
            If TMRxON = 1:
            1 = Timer1/3/5 counting is controlled by the Timer1/3/5 gate function
            0 = Timer1/3/5 counts regardless of Timer1/3/5 gate function
            bit 6 TxGPOL: Timer1/3/5 Gate Polarity bit
            1 = Timer1/3/5 gate is active-high (Timer1/3/5 counts when gate is high)
            0 = Timer1/3/5 gate is active-low (Timer1/3/5 counts when gate is low)
            bit 5 TxGTM: Timer1/3/5 Gate Toggle Mode bit
            1 = Timer1/3/5 Gate Toggle mode is enabled
            0 = Timer1/3/5 Gate Toggle mode is disabled and toggle flip-flop is cleared
            Timer1/3/5 gate flip-flop toggles on every rising edge.
            bit 4 TxGSPM: Timer1/3/5 Gate Single-Pulse Mode bit
            1 = Timer1/3/5 gate Single-Pulse mode is enabled and is controlling Timer1/3/5 gate
            0 = Timer1/3/5 gate Single-Pulse mode is disabled
            bit 3 TxGGO/DONE: Timer1/3/5 Gate Single-Pulse Acquisition Status bit
            1 = Timer1/3/5 gate single-pulse acquisition is ready, waiting for an edge
            0 = Timer1/3/5 gate single-pulse acquisition has completed or has not been started
            This bit is automatically cleared when TxGSPM is cleared.
            bit 2 TxGVAL: Timer1/3/5 Gate Current State bit
            Indicates the current state of the Timer1/3/5 gate that could be provided to TMRxH:TMRxL.
            Unaffected by Timer1/3/5 Gate Enable (TMRxGE).
            bit 1-0 TxGSS<1:0>: Timer1/3/5 Gate Source Select bits
            00 = Timer1/3/5 Gate pin
            01 = Timer2/4/6 Match PR2/4/6 output (See Table 12-6 for proper timer match selection)
            10 = Comparator 1 optionally synchronized output (sync_C1OUT)
            11 = Comparator 2 optionally synchronized output (sync_C2OUT)
            */
            
            TMR1GE_bit = 0;  //1
            /*T1GPOL_bit = 1;
            T1GTM_bit = 0;
            T1GSPM_bit = 1;
            T1GGO_bit = 1;
            T1GSS1_bit = 0;
            T1GSS0_bit = 0;*/
            
            TMR1IE_bit = 1;           
            PEIE_bit = 1;
            GIE_bit = 1;
            
            TMR1ON_bit = 1;
            Delay_ms(1000);
            TMR1ON_bit = 0;
            
            if(!freqC_or_tacho)
                  iFrequency = ((iFrequency * 65536) + ((TMR1H << 8) + TMR1L)) << 3;
            else if(freqC_or_tacho)
                  iFrequency = (((iFrequency * 65536) + ((TMR1H << 8) + TMR1L))) * 480;
             
            fFrequency = (double)(iFrequency);
            MAX7219_Display(fFrequency);            
            iFrequency = 0;       
    }
}

 

Attachments

  • PIC18F45K22 + MAX7219 Frequency Counter.rar
    105.1 KB · Views: 86
Last edited by a moderator:

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top