![]() |
![]() |
![]() |
|
|
|||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
|
|
Thread Tools | Display Modes |
|
|
(permalink) |
|
Hi I have this program which turns ON & OFF a led with a calculated time.
I want to calculate what’s the exact led ON time & led OFF time using a simulator or any other method. I don’t know in what rate this led turns on & off. My Oscillator = 4 MHz Please help me to calculate this. Code:
List p=16F628A include <P16F628A.inc> errorlevel -302 __config 3F18h cblock 20h W_Temp,S_Temp,TIME endc #define LED PORTB,0 org 0000h goto Start ;*********** ;ISR routine ;*********** org 0004h bcf INTCON,GIE movwf W_Temp swapf STATUS,W movwf S_Temp btfss INTCON,T0IF goto Away bcf INTCON,T0IF movlw .6 addwf TMR0,F incf TIME,F movf TIME,W andlw 7fh xorlw .125 btfss STATUS,Z goto Away btfss TIME,7 goto $+4 clrf TIME bcf LED ;turn OFF led goto Away clrf TIME bsf TIME,7 bsf LED ;turn ON led Away swapf S_Temp,W movwf STATUS swapf W_Temp,F swapf W_Temp,W bsf INTCON,GIE retfie ;******************************* ;Initialisation -setup the ports ;******************************* Start bsf STATUS,RP0 clrf TRISB movlw b'00000011' ;set prescaller to 16 movwf OPTION_REG bsf INTCON,T0IE bsf INTCON,GIE bcf STATUS,RP0 clrf PORTB Hang nop goto Hang end |
|
|
|
|
|
|
(permalink) |
|
You are adding 6 to Timer 0 every interrupt, you have the prescaler set to 16 and so you will get an interrupt every (256-6)*16 = 4000 cycles. You then count to 125 before toggling your LED, therefore your LED changes state every 4000*125 cycles or every ½ second.
If you use the simulator in MPLAB and set breakpoints on each write to the LED, you can then use the stopwatch to time the on/off times. BTW, your delay is not exact as when you write to TMR0 it resets the prescaler and throws the count out slightly. Mike. |
|
|
|
|
|
|
(permalink) | ||
|
Oh I see now I got it.1usX16X250X125 = 500ms.
Quote:
Quote:
Thanks Mike |
|||
|
|
|
|
|
(permalink) |
|
The simulator runs at about half speed on my machine. So, for 10 mins you will have to wait about 20 mins. In reality you don't need to wait 10 mins because if your ½ second ISR is accurate then all other times will be.
If you are going to make a clock then this code is not good. A better way is to use timer 2 and set PR2 to 249. Mike. |
|
|
|
|
|
|
(permalink) |
|
Ok thanks mike. I’ll try to add TMR2 & check.
For the time being do I have to adjust something in this coding? |
|
|
|
|
|
|
(permalink) |
|
Here is your code modified to use Timer 2. This will be very accurate as a clock. I'll let you work through the data sheet to work out what it's doing. Note that you don't need to touch GIE in the ISR.
Mike. Code:
List p=16F628A include <P16F628A.inc> errorlevel -302 __config 3F18h cblock 20h W_Temp,S_Temp,TIME endc #define LED PORTB,0 org 0000h goto Start ;*********** ;ISR routine ;*********** org 0004h ; bcf INTCON,GIE <-----Not needed movwf W_Temp swapf STATUS,W movwf S_Temp btfss PIR1,TMR2IF goto Away bcf PIR1,TMR2IF incf TIME,F movf TIME,W andlw 7fh xorlw .125 btfss STATUS,Z goto Away btfss TIME,7 goto $+4 clrf TIME bcf LED ;turn OFF led goto Away clrf TIME bsf TIME,7 bsf LED ;turn ON led Away swapf S_Temp,W movwf STATUS swapf W_Temp,F swapf W_Temp,W ; bsf INTCON,GIE <-----Not needed retfie ;******************************* ;Initialisation -setup the ports ;******************************* Start bsf STATUS,RP0 clrf TRISB movlw b'0000011' ;set prescaller to 16 movwf OPTION_REG bsf INTCON,GIE bcf STATUS,RP0 clrf PORTB movlw b'00000110' ;prescaler = 16 movwf T2CON bsf STATUS,RP0 bsf PIE1,TMR2IE movlw .249 movwf PR2 bcf STATUS,RP0 bsf INTCON,PEIE Hang nop goto Hang end |
|
|
|
|
|
|
(permalink) |
|
Oh my god you have done a great part. For sure I’m going to add your coding.
Plenty things to learn.And your previous codings worked well.Didn't give any problem. Thank you very much mike if you are not here I’ll lost. |
|
|
|
|
|
|
(permalink) |
|
Building a clock without drift will be difficult I imagine, due to not having precise timing. I may be wrong, but you may be better off trying to interface with a RTC. There was a thread about that not too long ago. For short time periods it would work fine, but I imagine the drift would be noticeable after a few hours.
|
|
|
|
|
|
|
(permalink) |
|
It should be accurate to a couple of seconds per day - worst case. For better accuracy a 32k watch crystal on timer1 should be as accurate as a RTC module. To implement a RTC using timer1 is simple and Microchip even supply the code in the 16F88 data sheet.
Mike. |
|
|
|
|
|
|
(permalink) |
|
It's relatively easy to implement a soft trim routine in the ISR to adjust the 1 second "heartbeat" with 1 Tcy (1 instruction cycle) resolution. This mechanism has provided accuracy to within about 1/2 second per month using standard 50 ppm (16/20 MHz) crystals in normal room temperatures on several of my projects.
Code:
;
; ISR_Trim routine is used to adjust the RTC 1-second period to
; within plus or minus 200-nsecs to make up for a crystal which
; may be slightly off frequency. The routine adds or subtracts
; one 200-nsec count (1 Tcy) from Timer 2 for the first 'CCTR'
; number of 1-msec interrupts each second. Theoretical accuracy
; to within 6.3 secs/year, not including temperature drift and
; crystal aging.
;
; variables: CCNT, correction count from EEPROM [00 to FF]
; CVAL, correction value from EEPROM [FF or 01]
; CCTR, correction counter reloaded from 'CCNT'
; variable each 1-second period
;
; range: ±255 200-nsec counts/second (±51.0 usecs/sec)
;
ISR_Trim
movf CCTR,W ; correction counter 0? |B0
bz ISR_Sw_Input ; yes, branch, else |B0
decf CCTR,f ; decrement counter |B0
movf CVAL,W ; get correction value FF or 01 |B0
addwf TMR2,f ; apply 1 Tcy timer correction |B0
Code:
;
; reload timer Trim correction counter (once per second)
;
movf CCNT,W ; reload correction counter var |B0
movwf CCTR ; |B0
;
Last edited by Mike, K8LH; 3rd October 2007 at 02:47 AM. |
|
|
|
|
|
|
(permalink) |
|
Hi thanks for the very useful replies.I'll make note on that.
I applied Mikes (Pommie) coding it worked very well. I have a small problem to ask.In the ISR I can write only 4000 cycles. If it exceeds 4000 cycles it will generate an interrupt. For example if my multiplexing (SSD) routine exceeds 4000 cycles it will generate an interrupt & goes to begining of the ISR routine so it will not show the balance remaing digits. Is this true? If I place the multiplex routine in the main menu also same thing will be happens.because its exceeding 4000 cycles. any idea. |
|
|
|
|
|
|
(permalink) |
|
You shouldn't put any delays in your ISR. If you want to multiplex displays then update 1 display per interrupt.
For example, say you have 5 displays and you want to refresh at 50Hz, you would interrupt at 250Hz (4000 cycle - that was lucky Mike. Your code at Away would be something like, Code:
Away incf Digit,F ;inc digit counter movfw Digit ;fetch it xorlw .5 ;reached 5? btfsc STATUS,Z ;skip if not=5 clrf Digit ;yes, clear it movfw Digit ;get value again addlw 0xff ;add -1 btfsc STATUS,Z ;reached Zero yet goto DoDigit0 ;yes, display this one. addlw 0xff ;add -1 btfsc STATUS,Z goto DoDigit1 addlw 0xff btfsc STATUS,Z goto DoDigit2 addlw 0xff btfsc STATUS,Z goto DoDigit3 addlw 0xff btfsc STATUS,Z goto DoDigit4 DoneDigits swapf S_Temp,W You can use indirect addressing to do this but it's probably simpler to do it this way at your stage. Last edited by Pommie; 3rd October 2007 at 04:16 AM. |
|
|
|
|
|
|
(permalink) |
|
Hi Mike give me time to look into your display routine it will take some days.
BTW I’m going to use TIMER2 settings to generate the 1 sec time base as earlier suggested. But when I was making experiments with TMR0 I wrote a new coding. In the simulator it gives me better accuracy than my first post coding in this thread. Note that I’m not using this code I’m going to use TIMER2 coding. I just want to know whether this is good or not? Code:
#include <P16F628A.inc> errorlevel -302 __config 3F18h cblock 70h W_Temp,S_Temp,COUNT endc org 0x0000 goto Start org 0x0004 interrupt movwf W_Temp ;2latent +1 =3 swapf STATUS,W ;+1 =4 movwf S_Temp ;+1 =5 bcf STATUS,RP0 ;+1 =6 bcf STATUS,RP1 ;+1 =7 movlw 100h-d'78' ;+1 =8 goto $+1 ;+2 =10 goto $+1 ;+2 =14 nop ;+1 =15 movwf TMR0 ;+1 =16 + 78*128 = 10,000 bcf INTCON,T0IF ;reset int flag decfsz COUNT,F goto $+3 movlw .100 movwf COUNT movf COUNT,W sublw .50 btfsc STATUS,C bsf PORTB,0 btfss STATUS,C bcf PORTB,0 swapf S_Temp,W movwf STATUS swapf W_Temp,F ;swap to file swapf W_Temp,W ;swap to work retfie Start bsf STATUS,RP0 clrf TRISB movlw b'00000110' ;set prescaler to 128 movwf OPTION_REG movlw 0a0h ;enable timer interupt movwf INTCON bcf STATUS,RP0 movlw .100 movwf COUNT clrf PORTB hang goto hang end |
|
|
|
|
|
|
(permalink) |
|
That is a better way to use Timer0 but will still be inaccurate due to the 2 cycle instructions in the main code causing the interrupt to execute 1 cycle later. That code looks very familiar, in fact so familiar I think it maybe from an earlier post of mine. Where did you find it?
You can implement a completely accurate timer with Timer0. The secret is to never write to the TMR0 register and therefore never reset the internal prescaler. I'll leave you to try and work out how. Mike. |
|
|
|
|
|
|
(permalink) |
|
Yes I gathered some codings from one of your earlier post I studied them & I never throw them away. They are always in my mind.
The above code also writes to TMR0 so it will also reset the Pre Scaller isn’t it? This is the maximum accuracy that I can get with TMR0.You mean the goto hang code causing the interrupt routine. |
|
|
|
|
| Bookmarks |
| Thread Tools | |
| Display Modes | |
|
|
|
|
||||
| Thread | Thread Starter | Forum | Replies | Latest |
| Using Oscilloscopes | mechie | Electronic Theory | 9 | 29th November 2007 09:48 PM |
| Pic16F7XX transmission interrupt problem | Tzvik | Micro Controllers | 1 | 27th January 2006 01:00 AM |
| HANDLING THE INTERRUPT. | alamy | Micro Controllers | 6 | 26th March 2005 03:37 PM |
| HELP!! INTERRUPT PROBLEM | aidantmurphy | Micro Controllers | 3 | 26th January 2005 06:52 PM |
| Interrupt on GP Change problem | Dan East | Micro Controllers | 2 | 22nd May 2004 05:12 PM |