NOLIST ; This file is part of picide, ATA(PI) interface to PIC18 family MCUs. ; Copyright (C) 2004-5 Toby Thain, toby@telegraphics.com.au ; This program is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2 of the License, or ; (at your option) any later version. ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA LIST TITLE picide SUBTITLE "Timers and delays" ;; Version history ;; 16-Oct-2004: 0.1 - started by Toby ;; 23-Feb-2005: 1.0 - public release under GPL ; contents of this module: ; *** all code assumes Fosc 40MHz *** ; various synchronous delays using Timer0 global delay1500ms,delay100us,delay1ms,delay150ms global delay2ms ; uses Timer2 (just to be different) ; setup async timeouts on Timer0 (poll TMR0IF, used by IDE code) global time400ms,time1500ms ; interrupt driven "stopwatch" timer, 3 byte tick count @ 1kHz ; used for benchmark timings global init_tick,start_time,end_time #include "defs.inc" extern tick1khz,decstr,puthex,dec16,putdec16,putch #define TMR_1500MS (65536-58593) ; x 256 = 14999808 = ~1.5 second #define TMR_1SEC (65536-39062) ; x 256 = 9999872 = ~1 second #define TMR_400MS (65536-15625) ; x 256 = 4000000 = ~400ms udata_acs sttime res 2 code init_tick: ; set up 1000Hz heartbeat interrupt on Timer2 ; Fosc/4 = 10,000,000 Hz ; /16 prescale = 625,000 Hz ; /125 period = 5,000 Hz ; /5 postscale = 1,000 Hz movlw b'00100010' ; 1:5 postscale,timer off,1:16 prescale movwf T2CON clrf TMR2 movlw 125 ; period movwf PR2 clrf tick1khz clrf tick1khz+1 clrf tick1khz+2 bcf PIR1,TMR2IF bsf PIE1,TMR2IE ; enable Timer2 match period interrupt bsf T2CON,TMR2ON ; start it! return ; stash stopwatch value at start of timing interval start_time: bcf INTCON,GIEH ; disable interrupts while reading ticks movff tick1khz,sttime movff tick1khz+1,sttime+1 ;movff tick1khz+2,sttime+2 bsf INTCON,GIEH ; re-enable interrupts return ; subtract starting time from 1kHz timer ; and print result in hexadecimal end_time: bcf INTCON,GIEH ; disable interrupts while reading ticks movf sttime,w subwf tick1khz,w movwf dec16 movf sttime+1,w subwfb tick1khz+1,w movwf dec16+1 bsf INTCON,GIEH ; re-enable interrupts call putdec16 _putchar '.' return delay25us: ; set up Timer0 movlw b'01001000' ; disabled,8-bit,timer,low-to-high,not prescaled movwf T0CON movlw -250+11+2 ; 250 cycles = ~25us, less subroutine and call overhead delay: movwf TMR0L delay2: bcf INTCON,TMR0IE ; disable Timer0 interrupt bcf INTCON,TMR0IF ; clear Timer0 overflow bsf T0CON,TMR0ON ; start it! btfss INTCON,TMR0IF ; check for timer overflow bra $-2 return delay100us: ; set up Timer0 movlw b'01000001' ; disabled,8-bit,timer,low-to-high,prescaled 1:4 movwf T0CON movlw -250+(13+2)/4 ; 250x4 cycles = ~100us, less subroutine and call overhead bra delay delay1ms: ; set up Timer0 movlw b'01000101' ; disabled,8-bit,timer,low-to-high,prescaled 1:64 movwf T0CON movlw -156 ; 156x64 cycles = ~998.4us bra delay delay150ms: ; set up Timer0 movlw b'00000100' ; disabled,16 bit,timer,low-to-high,prescaled 1:32 movwf T0CON _tmr 0, 46875 ; x 32 = 1500000 cycles = ~150ms bra delay2 delay1500ms: ; set up Timer0 movlw b'00000111' ; disabled,16 bit,timer,low-to-high,prescaled 1:256 movwf T0CON _tmr 0, TMR_1500MS bra delay2 delay2ms_: ; set up Timer0 movlw b'01000110' ; disabled,8-bit,timer,low-to-high,prescaled 1:128 movwf T0CON movlw -156 ; 156x128 cycles = ~1996.8us bra delay ; alternative version using Timer2 ; Timer2 input = Fosc/4 = 10,000,000 Hz ; divide by 1/16 prescale = 625,000 Hz ; divide by period (125) = 5000 Hz ; divide by 1/10 postscale = 500 Hz = 2ms delay2ms: ; set up Timer2 movlw b'01001010' ; 1:10 postscale,timer off,1:16 prescale movwf T2CON clrf TMR2 movlw 125 movwf PR2 bcf PIR1,TMR2IF bsf T2CON,TMR2ON ; start it! btfss PIR1,TMR2IF ; check for timer overflow bra $-2 return ;--------------------------------------------------------- time1500ms: ; set up Timer0 movlw b'00000111' ; disabled,16 bit,timer,low-to-high,prescaled 1:256 movwf T0CON _tmr 0, TMR_1500MS tmrgo: bcf INTCON,TMR0IE bcf INTCON,TMR0IF bsf T0CON,TMR0ON ; start timer! ; the caller should poll TMR0IF return time400ms: ; set up Timer0 movlw b'00000111' ; disabled,16 bit,timer,low-to-high,prescaled 1:256 movwf T0CON _tmr 0, TMR_400MS bra tmrgo ;--------------------------------------------------------- end