- 13th December 2007, 15:56 #1
picbasic pro timer
I would like to ask, how to utilize the timer function in the microcontroller to get the difference between start time and stop time and then display it at LCD. E.g, switch pressed once to start timer, press again to stop timer, then the difference between start time and stop time is calculated and displayed on LCD. I am doing the programming using PicBasic Pro.
May I ask can this be done? I am a total newbie in using microcontroller, hope can help. Thanks in advance to all the experts.
- 13th December 2007, 17:25 #2
timers in pic16f877a
Of course it can be done.
Depending on how much code you need to run, you can choose an interrupt approach or a polling approach.
For polling, you just monitor an input pin and when it changes state, you start the timer. Then monitor the pin again and stop the timer when the state of the pin changes back. The timer contents are the time you need.
Of course, with this approach you wil lose a few instruction cycles, but running at 20MHz your instruction cycle is 200ns. So if you lose 5 cycles, you lose only 1us.
If this is a problem, then you can try using the CCP in the PIC16F877A.
Set it up to capture every rising edge. So the contents of the timer will get latched when the rising edge occurs. At the same time, you get an interrupt and read the latched timer contents and save them. On the next edge the new timer contents will be latched and you get an interrupt. Subtract the two latched values and you get the exact time between the events, because all is now done in HW, you do not lose any cycles.
It all depends on your actual requirements.
- 13th December 2007, 17:45 #3
pic 16f877a counter
Timing precision is very critical for my project, thus, I think the best method is the method that will not lose any cycles.
However, I will first start with polling method to get used to the codes as I am totally new. How to declare the timer function to be used and monitor the pin changes? How to stored the timing difference in a variable and the display it to the LCD? Can you please guide me further in this matter? I am coding using PicBasic Pro.
Very much thanks!
- 13th December 2007, 17:45
using pic16f877a timer
The most precise is indeed the one using the CCP, but even that has some limitations, in terms of resolution. I think the best resolution you can get is 0.2us, when the oscillator is running at 20MHz.
- Join Date
- Mar 2005
- 8 / 8
pin functions of pic16f877a
Thank for the reply VVV and BobK. I have found an example project (Olympic Timer) which is very similar to what I need for me project in the forum suggested.
However, I am facing a problem which, I need the timer to count in the interval of 1ms. What I can obtain and learn is 10ms interval.
The expert in that forum suggested me to change the preset Timer1 register value to suit the 1ms interval. But I do not know how to get it, no matter what value I change, the timer gets even slower compare to 10ms interval. Can anyone teach me how to calculate the actual preset value for Timer1 register, so that I can get 1ms timer interval instead of 10ms? I am using 16F877A and 4Mhz clock, and I am coding in PicBasic Pro.
Please see here. http://www.picbasic.co.uk/forum/showthread.php?t=7729
Or is there any better solution to get 1ms timing interval?
1ms interval is very important for my project. Please help.
why tmr1 value change
I am sorry, I do not understand the requirements anymore: do you need a resolution of 1ms or do you need to measure time intervals in the 1ms range with the best possible resolution?
For 1ms resolution you can simply use polling, even at 4MHz.
If you need better resolution, then again I suggest you use the CCP, which will allow you to measure with a resolution of 1us at 4MHz.
I cannot help with PICBasic, I am an assembler guy.
- 29th December 2007, 01:32
pic16f877 timer calculation
I am sorry for making the requirement unclear. Actually, I need to timer to count in 1ms resolution. Meaning that, the timer will count in 1ms increment value and display in LCD. E.g. If I press start button, the timer will start counting in 1ms increment, until I press stop button, the counted value will be displayed on the LCD.
The TIMER1 function I know how to use, the problem is I do no know how to set the TIMER1 register value so that it can be in 1ms resolution and display it on the LCD.
Perhaps coding in assembly will help?
1us in seconds
OK, now I understand.
You can use TMR1 to generate interrupts every 1ms.
To do that, preload the timer with a qantity that will make it overflow in 1ms.
For example: assume the oscillator is 4MHz. Then the TMR1 clock is 1MHz. That means you need 1000 counts for 1ms. So preload the timer with 65536-1000=64536.
It will then generate an iterrupt every 1ms. In the ISR, increment a pair of registers (or more) which will be your ms counter. These registers get cleared when the first rising edge is detected and read on the second rising edge. That is the time in ms between the edges, which is what you need.
Note that you need to do the debouncing in hardware.
So the code might look like this:
Code:#define BUTTON PORTB,0 ORG 0x00 ;reset vector goto main ; ORG 0x04 ;Interrupt vector movwf W_temp ;save W swapf STATUS,W ;save status reg movwf STATUS_temp ; clrf STATUS ;make sure we are in bank 0, although we do not switch banks here bcf PIR1, T1IF ;clear interrupt flag bcf INTCON,T1ON ;stop the timer movlw high (.65536-.1000) ;reload timer; the value may need to be adjusted slightly, to get exactly 1ms movwf TMR1H ; movlw low (.65536-.1000) ; movwf TMR1L ; incfsz Counter,F ;increment the 16 bit ms counter incf Counter+1,F ; swapf STATUS_temp,W ;restore registers movwf STATUS ; swapf W_temp,F ; swapf W_temp,W ; retfie ;return main: ;main code ;put all your initializations here clrf Counter ;clear the 16-bit counter clrf Counter+1 ; movlw B'10000000' ;enable interrupts in general movwf INTCON ; Wait_h: btfss BUTTON ;wait here until button pressed goto Wait_h ; movlw high (.65536-.1000) ;preload timer; value can be changed, so the first interrupt occurs exactly after 1ms movwf TMR1H ; movlw low (.65536-.1000) ; movwf TMR1L ; bsf T1CON,TMR1ON ;turn on TMR1 bcf PIR1,T1IF ;clear TMR1 interrupt flag, just in case bsf INTCON,PIEI ;enable peripherals interrupts (TMR1 is a peripheral) Wait_l: btfsc BUTTON ;wait for button to be released goto Wait_l ; Wait_r: btfss BUTTON ;wait for the rising edge here goto Wait_r ; bcf T1CON ;stop TMR1 bcf INTCON,PIEI ;disable peripheral interrupts call DISPLAY ;call the routine that displays the time on the LCD clrf Counter ;clear the 16-bit counter clrf Counter+1 ; Wait_f: btfsc BUTTON ;now wait here for a falling edge goto Wait_f ; goto Wait_h ;re-start the cycle
function of pic 16f877a
I refer to the Assembly Codes provided by Mr.VVV, I manage to get the clock to have in very near to 1ms interval. But, I the timer seems to be slightly out of the actual timing when I compare the timer to a watch.
e.g, watch seconds ticked 1.5x ~ 2x faster than the timer programmed in the uController.
I tried to change the value to load into the TIMER1 registers, even to Highbyte=$FF, LowByte=$FF, but it seems that still unable to get as accurate as in the watch, although it is very near to it.
And, my device cannot run when I change to 20MHz crystal. But it works just fine in 4Mhz, may I know what is wrong? Tried to change the configuration bits from XT to HS in MPLAB 8.00, but when I recompile, the bit change back to XT.
I attach the codes I wrote using PicBasic Pro, can any experts correct my mistakes to get the desired interval?
Help is very much appreciated.
- Join Date
- Sep 2006
- Toronto, Canada
- 178 / 178
fosc/4 pic 16f877a
* Use a crystal that divides perfectly with binary into seconds
* Don't run the timers asynchronously (don't clear or set them let them free run)
* Use the CCP module (Compare mode)
For 1ms timing 1/100th of a second a 6.5536MHz crystal would be perfect.
- Join Date
- Nov 2007
- 0 / 0
PICbasic probably is a lot harder to be achieved than assembly language.
- Join Date
- Sep 2006
- Toronto, Canada
- 178 / 178
assembly pic16f877a variable definition
Very true. Who knows what sort of code the BASIC generates.Originally Posted by IamnotJunk
how to load value into timer1 of pic16f877
Thanks for the hints, I will try on it now. Still need to study how to use CCP first.:D
Added after 4 hours 14 minutes:
Ok. I redo the program to make the Timer1 free run timer. Before timer start, it is loaded with with 0000h in the timer1 register. The timer starts when I press START.
When I press stop, I get the value from TMR1H and TMR1L into 2 separate variables which I define as BYTE. After that, I get the actual result by:
So, it that mean, the total RESULT * 1us = the total timing in seconds I obtained from the event? Not really sure about the calculation of the timer, but as far as I understand, using 4Mhz clock, it will be:
4Mhz/4 = 1Mhz (Fosc/4 from T1CON.1=0, internal clock)
T=1/1M=1us (per instruction cycle)
thus, Result*1us = total time in second.
Please correct me if I am wrong, really not very sure about the Timer1 calculation.
Thanks in advance!
timer example in pic16f877a
Yes, that is correct. With a prescaler of 1:1 the timer increments every 1us, so the result is in microseconds.
1 members found this post helpful.