Hi, Since this is more about pic itself than about jal, I wll ask here. While playing (educating myself) with timers, I tried to build a frequency counter. The one where time period of counting pulses would change depending on pulse rate, that is, frequency. At first I used tmr0 and tmr1, then rebuilt using tmr1 and tmr2, but still can not get exactly what I was looking for. I have spent many late evenings trying, probably somebody from a side can spot my error. Basically, TIMER2 is used to make a time frame when pulses must be counted, but TIMER1 is the one that counts pulses. Both have interrupts enabled, and interrupt routine just adds 1 to a variable, which is then dealt with in main code. No prescalers or postscalers are used. In main code, when a time frame counter or a pulse counter exceeds pre-defined values, both timers are stopped, their values added to respective variables, and both variables just sent via serial link to my PC. The problem is: When TIMER1 (pulse counter) is fed from internal clock, I get correct value= s: Finish TMR: 5000307 Finish CNT: 5000306 20MHz crystal is used, so 5MHz instruction clock, and one tick of a timer is 0.2us, so this gives frequency : F=3D(CNT * 5000000) / TMR =3D 4999999.0 Hz. That error of 1 pulse can be eliminated by changing timer start/stop order. These are about the same, which is correct, since both timers advance at the same speed. That made me think that program works correctly. The only pulse source with predictable frequency I have, is an quartz oscillator, marked as 1.8432MHz. Another frequency counter shows it's frequency as 1843150Hz. When I change T1CON_TMR1CS to 1, and feed pulses from the oscillator, I get results like this : Finish TMR: 5000304 Finish CNT: 1843100 which gives F=3D1842987.94 Hz - which shows I am missing several hundred pulses, or my time frame was several hundred pulses too long. 5000000 TMR pulses is one second, so it is more-than-enough time period to count this frequency. So, I tried to move all the stuff around, changed start and stop sequences, checked datasheets, got a bit different results, but did not get better precision. Enabling or disabling T1SYNC did not change anything, since the frequency I'm trying to measure is quite low. It's not like this circuit is mission-critical or something, I just want to understand what I'm doing wrong. And I want a good frequency counter. Where are my pulses?! :) How can it be, it's working perfectly with internal clock, but runs wrong with external one. Code is in Jal2, with jallibs, and it looks like this: include 16f886 -- target PICmicro pragma target clock 20_000_000 -- oscillator frequency pragma target OSC HS -- HS crystal or resonator pragma target WDT disabled -- no watchdog pragma target LVP disabled -- no Low Voltage Programming pragma target MCLR internal -- reset externally -- enable_digital_io() ---------------------------------------------------------------------------= --------------------- include delay include print -- UART const serial_hw_baudrate =3D 115200 include serial_hardware serial_hw_init() alias serial_write is serial_hw_write alias serial_read is serial_hw_read alias serial_data is serial_hw_data alias serial_data_available is serial_hw_data_available -- print start print_crlf(serial_hw_data) print_crlf(serial_hw_data) const byte starttmrmsg[] =3D "Startup" print_string(serial_hw_data, starttmrmsg) print_crlf(serial_hw_data) -- time frame is made using timer2 var byte tmrupd var dword tmrcnt var byte running const dword tmrmax =3D 5000000 T2CON =3D 0 T2CON_T2CKPS =3D 0 -- prescaler=3D1:1 T2CON_TOUTPS =3D 0 -- postscaler=3D1:1 T2CON_TMR2ON =3D 0 -- tmr2 off TMR2 =3D 0 -- tmr2, pre, post scalers clear PIR1_TMR2IF =3D 0 -- int flag clear PIE1_TMR2IE =3D 0 -- int off -- pulse counter is done using timer1 var byte cntupd var dword cntcnt const dword cntmax =3D 5000000 T1CON =3D 0 T1CON_TMR1CS =3D 1 -- use input from T1CKI ;T1CON_TMR1CS =3D 0 -- use input from internal clock ;T1CON_T1GINV =3D 0 -- gate active=3Dlow T1CON_TMR1GE =3D 0 -- tmr0 gate not used ;T1CON_T1OSCEN =3D 0 -- tmr1 osc not used T1CON_NT1SYNC =3D 1 -- do not synchronize sgnal to clock (inverted lo= gic) T1CON_T1CKPS =3D 0 -- set prscaler (0:1, 1:2, 2:4, 3:8) T1CON_TMR1ON =3D 0 -- tmr1 off TMR1 =3D 0 -- clear timer PIR1_TMR1IF =3D 0 -- clear int flag PIE1_TMR1IE =3D 0 -- int off const byte tmrmsg0[] =3D "Start TMR: " const byte tmrmsg1[] =3D "Update TMR: " const byte tmrmsg2[] =3D "Finish TMR: " const byte cntmsg0[] =3D "Start CNT: " const byte cntmsg1[] =3D "Update CNT: " const byte cntmsg2[] =3D "Finish CNT: " const byte freqmsg0[] =3D "Freq: " INTCON_GIE =3D 1 -- enables all unmasked interrupts INTCON_PEIE =3D 1 -- enables all unmasked peripheral interrupts portA_direction =3D all_output portB_direction =3D all_output portC_direction =3D all_output alias led is pin_C3 pin_C3_direction =3D output pin_C0_direction =3D input var dword freq ---------------------------------------------------------------------------= --------------------- forever loop running =3D 0 cntcnt=3D0 cntupd=3D0 tmrcnt=3D0 tmrupd=3D0 ;print_string(serial_hw_data, tmrmsg0) ;print_dword_dec(serial_hw_data, tmrcnt) ;print_crlf(serial_hw_data) ;print_string(serial_hw_data, cntmsg0) ;print_dword_dec(serial_hw_data, cntcnt) ;print_crlf(serial_hw_data) TMR1 =3D 0 TMR2 =3D 0 ;while (pin_C0) loop end loop ;while (! pin_C0) loop end loop T1CON_TMR1ON =3D 1 -- tmr2 on T2CON_TMR2ON =3D 1 -- tmr2 on PIR1_TMR2IF =3D 0 -- int flag clear PIE1_TMR2IE =3D 1 -- int on PIR1_TMR1IF =3D 0 -- int flag clear PIE1_TMR1IE =3D 1 -- int on running =3D 1 led =3D on while (running =3D=3D 1) loop if (cntupd > 0) then cntcnt =3D cntcnt + 65536 cntupd =3D cntupd - 1 ; print_string(serial_hw_data, cntmsg1) ; print_dword_dec(serial_hw_data, cntcnt) ; print_crlf(serial_hw_data) end if if (tmrupd > 0) then tmrcnt =3D tmrcnt + 256 tmrupd =3D tmrupd - 1 ; print_string(serial_hw_data, tmrmsg1) ; print_dword_dec(serial_hw_data, tmrcnt) ; print_crlf(serial_hw_data) end if if (tmrcnt > tmrmax) then T1CON_TMR1ON =3D 0 -- tmr1 off T2CON_TMR2ON =3D 0 -- tmr2 off running =3D 0 elsif (cntcnt > cntmax) then T1CON_TMR1ON =3D 0 -- tmr1 off T2CON_TMR2ON =3D 0 -- tmr2 off running =3D 0 end if end loop led =3D off cntcnt =3D cntcnt + TMR1 tmrcnt =3D tmrcnt + TMR2 print_string(serial_hw_data, tmrmsg2) print_dword_dec(serial_hw_data, tmrcnt) print_crlf(serial_hw_data) print_string(serial_hw_data, cntmsg2) print_dword_dec(serial_hw_data, cntcnt) print_crlf(serial_hw_data) delay_1s(3) -- some delay print_crlf(serial_hw_data) end loop ---------------------------------------------------------------------------= --------------------- procedure ISR() is ; pragma interrupt fast pragma interrupt if PIR1_TMR2IF =3D=3D true then -- timeframe timer overflowed tmrupd =3D tmrupd+1 PIR1_TMR2IF =3D 0 end if if PIR1_TMR1IF =3D=3D true then -- pulse counter overflowed cntupd =3D cntupd+1 PIR1_TMR1IF =3D 0 end if end procedure --=20 KPL --=20 http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist .