Problem with ASM IRQ using FSR0 on PIC18F252


Results 1 to 11 of 11

Threaded View

  1. #4
    mytekcontrols's Avatar
    mytekcontrols Guest


    Did you find this post helpful? Yes | No

    Smile It works like a charm!

    Darrel your solution worked great! Thank you for your great wisdom and speedy answers.

    The glitch problem was caused by the fact that I am also running a low priority interrupt service routine which is using the same FSR. Neither of the routines was doing a proper context save of the FSR.

    Here is the completed 6 digit up/down counter w/prescaler source code incorporating your suggestions (hopefully this is all accurate, since I cut and pasted it together out of several include files). The counter's signal source is a rotary encoder connected to 2 pins on PORTC.

    Code:
    '************************************************
    '*  Name    : mod_ENCDRdisp.BAS 
    '*  Author  : Michael St. Pierre
    '*  Notice  : Copyright (c) 2005 Mytek Controls
    '*          : Free For All To Use 
    '*  Date    : 06/14/2005
    '*  Version : 1.0
    '*  Notes   : MEL PicBasic Pro Rotary Encoder Display Routine
    '*          : Includes 8-bit Prescaler 
    '************************************************
    
    DEFINE OSC 40
    DEFINE INTHAND myint
    ' Device = PIC18Fxxx
    
    '================================================
    ' Equates
    '================================================
    
    ENCA var PORTC.x	' use any 2 schmidt trigger inputs with 10K pull-ups
    ENCB var PORTC.x
    encoder var byte
    auxenc var byte
    Ecount var byte[6] bankA
    prescale var byte
    psvalue var byte
    direnc var bit
    loopcount var byte
    periodH con $FE
    periodL con $0B
    ascii var byte
    
    'Variables for saving state in interrupt handler
    fsave	var word bankA system	      ' Saves FSR0
    
    Goto Start	' Jump past interrupt routine
    
    '================================================
    ' Interrupt Handler (High Priority)
    ' Rotary Encoder w/precaler and 6 digit up/down counter 
    '================================================
    asm
    myint
    	
    ; save the FSR value because it gets changed below
        movf    FSR0L, W
        movwf   fsave
        movf    FSR0H, W
        movwf   fsave+1
    
    ; Main Interrupt routine begins here
    
    ; Timer1 set-up as 20 Khz counter (.00005 sec period)
        bcf     _TMR1ON         ; turn OFF Timer1 for counter load
        movlw   _periodH
        movwf   TMR1H           ; load high byte of period counter
        movlw   _periodL
        movwf   TMR1L           ; load low byte of period counter
        bcf     _TMR1IF         ; clear Timer1 IRQ Flag
        bsf     _TMR1ON         ; turn Timer1 back ON
    
    ;check rotary encoder inputs (@20 Khz rate)
    chk_encoder
        clrf    _auxenc
        btfsc   _ENCA
        bsf     _auxenc,0
        btfsc   _ENCB
        bsf     _auxenc,1
    
        movf    _auxenc, W
        xorwf   _encoder, F
    
        rrf     _auxenc, F
        rlf     _encoder, F
        rrf     _auxenc, F
        rlf     _encoder, F
    
        btfsc   _encoder,2
        goto    encoder_up
    chk_down
        btfsc   _encoder,3
        goto    encoder_down
        goto    restore
                
    encoder_up
        btfss   _encoder,3
        bsf     _direnc
        btfsc   _encoder,3
        goto    chk_down
        goto    countup
    
    encoder_down
        btfss   _encoder,2
        bcf     _direnc
        btfsc   _encoder,2
        goto    restore
        goto    countdown
    
    ;Encoder 6 Digit Counter w/PreScaler - Count Up
    countup
    ;prescaler
        movf    _psvalue, W     ; retrieve prescaler value and...
        subwf   _prescale, W    ; compare to prescale count
        btfsc   STATUS, Z       ; Have we finished prescaling?
        goto    preupdone       ; Yes! Go begin actual count
        incf    _prescale, F    ; Else keep incrementing prescale count and
        goto    restore         ; Leave!
    preupdone
        clrf    _prescale       ; Set-up for next prescale event
        clrf    _loopcount
        LFSR    FSR0, _Ecount   ; set counter base address
    
    inc_loop
        movlw   d'9'
        subwf   INDF0, W
        btfsc   STATUS, Z       ; Have we hit top for this digit?
        goto    nextdigit       ; Yes, go to next! 
        incf    INDF0, F        ; else keep incrementing it, and...
        goto    enc_exit        ; Leave!
    nextdigit
        clrf    POSTINC0        ; (clear INDF and increment FSR)
        incf    _loopcount, F
        movlw   d'6'
        subwf   _loopcount,W
        btfss   STATUS, Z       ; Have we checked all 6 digits?
        goto    inc_loop        ; No go to next!
        goto    enc_exit
    
    ;Encoder 6 Digit Counter w/PreScaler - Count Down
    countdown
    ;prescaler
        movf    _prescale, W    ; retrieve prescaler value
        btfsc   STATUS, Z       ; Have we finished prescaling?
        goto    predowndone     ; Yes! Go begin actual count
        decf    _prescale, F    ; Else keep decrementing prescale count and
        goto    restore         ; Leave!
    predowndone
        movf    _psvalue, W
        movwf   _prescale       ; Set-up for next prescale event
        clrf    _loopcount
        LFSR    FSR0, _Ecount   ; set counter base address
    
    dec_loop
        movf    INDF0, W        ; retrieve digit[x]
        bnz     dec_digit       ; Are we at the bottom for this digit?    
        movlw   d'9'            ; Yes, roll it over!
        movwf   POSTINC0        ; (move w = 9 to INDF and increment FSR)
        incf    _loopcount, F
        movlw   d'6'
        subwf   _loopcount, W
        btfss   STATUS, Z       ; Have we checked all 6 digits?
        goto    dec_loop        ; No go to next!
        goto    enc_exit    
    dec_digit
        decf    INDF0, F        ; Not at bottom, keep decrementing it, and...
        goto    enc_exit        ; leave!    
    
    enc_exit
        bsf     _AUTOdispNEW    ; flag that encoder value has changed
    
    ;restore registers
    restore
        movf	fsave, W
        movwf	FSR0L
        movf	fsave+1, W
        movwf	FSR0H
        retfie  FAST
    endasm
    
    '================================================
    ' Program Start
    '================================================
    Start:
            Clear
    
    ' Set-up Interrupts and Timers
    	TMR1H = periodH         ' Pre-load Timer1 High Byte  
    	TMR1L = periodL         ' Pre-load Timer1 Low Byte 
    	T1CON = %000001         ' Set Timer1: IntCLK SRC,Pre 1:1, - Timer ON
    	TMR1IF = 0              ' Clear Timer1 IRQ Overflow Flag
    	TMR1IE = 1              ' Enable Timer1 IRQ on Overflow
    	TMR1IP = 1              ' Timer 1 set as high priority interrupt
    	IPEN = 1                ' Enable priority levels on interrupts
    	INTCON = %11000000      ' Enable all interrupts!
    
    	Pause 100
    	Gosub reset_enc         ' initialize encoder
    
    	psvalue = 0		      ' initialize prescaler
    			
    	' psvalue = 0  - no prescaling -
    	' psvalue = 1  divide by 2
    	' psvalue = 2  divide by 3
    	' psvalue = 99 divide by 100
    
    ' Main Program Loop Begins Here
    
    mainloop
    	If AUTOdispNEW = 1 Then Gosub ENCDRdisp
    
    '--------------------------------------------
    ' your mainloop code goes here
    '--------------------------------------------
    
    	Goto	mainloop
    
    ENCDRdisp:
    ' display direction indicator
    	If direnc = 1 Then
    	ascii = "+"             'direction = UP
    	Else
    	ascii = "-"             'direction = down
    	Endif
    	Gosub	printascii
    
    ' display distance
    	For x = 5 To 0 Step-1
    	ascii = (Ecount DIG x) + $30
    	Gosub	printascii
    	Next x
    	Return
    
    ' Reset "ZERO" Encoder Display
    reset_enc:
    	AUTOdispNEW = 1
    	prescale = 0
    	For x = 0 To 5
    	Ecount[x] = 0
    	Next x
    	Return
    
    ' Print ascii characters
    printascii:
    	' your ascii print/display routine goes here
    	Return
    
    End
    Please excuse the lack of comments on the chk_encoder part of the routine. It was a public domain example that I pasted into my code ( I wish I could remember the author).

    One last question:
    I implemented the following as you suggested
    Code:
        LFSR    FSR0, _Ecount   ; set counter base address
    Can you explain how it works? What is LFSR?

    Thanks,
    Last edited by mytekcontrols; - 14th June 2005 at 21:27.

Similar Threads

  1. Instant Interrupts - Revisited
    By Darrel Taylor in forum Code Examples
    Replies: 772
    Last Post: - 17th February 2016, 23:14
  2. PBP, ASM and LST files
    By HenrikOlsson in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 12th January 2010, 14:43
  3. Problem using ASM instruction
    By ewandeur in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 3rd April 2008, 16:26
  4. pic18f252 hserout problem
    By edysan in forum Serial
    Replies: 4
    Last Post: - 16th June 2006, 21:46
  5. problem with asm interrupt
    By servo260 in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 20th December 2004, 18:02

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts