Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Getting out of an interrupt service Routine

Status
Not open for further replies.
Some PIC assembly fragments of code to do PLL based mains sync and 255-level output phase control.
I wrote this for a 16C73 about 20 years ago.. Most later stuff is in C rather than assembly.
[Using a 20MHz clock; timing based on that].

All main product and customer-specific code removed..



Put the control value in "outphase".

You need a few other memory locations like "clockref", "phase", "mainsref", "stat_temp" etc.

The timing reference input looks to have been a direct pickup from AC via a resistor to a port A pin (hz).
It uses each transition either way and compares against the last input state at each interrupt.
You need to change the mains00 / main10 parts if you use a different type of sync input, eg. trigger on the negative [high to low] transition only and bypass the routine [exitint] (but still set the image flag high) on low to high, with the full-wave opto setup.

mainsref,7 is the bit that the normal program loop monitors to count cycles & do low speed timing, read it and reset when seen in that.
(Also used by the PLL phase comparison, so be careful if you change that).


PORTB,s_oe is the triac trigger ouput.
PORTB,mref is a spare pin to monitor the program zero detection.

[Edit - typos & clarification].

Some initialisation stuff..

Code:
;
; PAGE 0 Register setup ***
;
                bcf     STATUS,RP0      ; Select page 0
                movlw   000             ; Set port B to
                movwf   PORTB           ; $00 = all o/p off.
                movlw   D'001'          ; Init. timer
                movwf   TMR0            ; to avoid w/d
;
; Clear workspace
;
                movlw   021             ; Clear RAM
                movwf   FSR             ; Set indirect ptr
                movlw   05E             ; Byte Count
                movwf   iomode          ; Save Count
;
begin2          clrf    INDF            ; Clear ram via indirect
                incf    FSR,f           ; next addr
                decfsz  iomode,f        ; Loop till done
                goto    begin2          ;
                clrf    iomode            ;
;
; All ram clear.
;
; Set o/p on phase
; (Higher value = shorter firing pulse)
;
                movlw    d'160'            ; Triac firing pulses turned off
                movwf    outphase        ; at ??/256 from end of each half cycle.
;
; Set master Timer value
;
                movlw    D'050'            ; 256 - 50 = 200 Cycles
                movwf    clockref        ;
                movwf    TMR0            ; Reset Timer
                bcf        INTCON,2        ; Reset int flag.
;
; Enable Interrupts.
;
                bsf     INTCON,T0IE     ; Enable timer int
                bsf     INTCON,GIE      ; & global int.


The interrupt routine that does all the work:

Code:
;
;
; Interrupt driven routines
;
; Executed at interval of (200nS * 200) = approx. 40uS
;
intrpt          movwf   w_temp          ; Save W
                swapf   STATUS,w        ; Save context
                bcf     STATUS,5        ; Bank 0
                movwf   stat_temp       ;
                movf    PCLATH,w        ; Get latch
                movwf   pcl_temp        ; save it
;
;Timer counts UP, Int at rollover 255->0
;
                movf    clockref,w      ; Get timer value
                movwf   TMR0            ; reload timer
                bcf     INTCON,2        ; reset ctr int flg
;
; Shift Phase counter
;
                decf    phase,f            ; Next step
;
; Do Phase Control outputs
;
outangle        movf    phase,w            ; Get Phase
                subwf    outphase,w        ; Compare to o/p value
                btfsc    STATUS,C        ; Negative result?
                goto    out_off            ; No, turn OFF
out_on            bcf        PORTB,s_oe        ; Yes, turn ON
                goto    endphase        ;
out_off            bsf        PORTB,s_oe        ; Set outputs OFF
;
; Do mains Zero-Crossing detection        ;
;
;endphase        movf    phase,w            ; Look at phase
;                subwf    D'64'            ; 3/4 way through?
;                btfsc    STATUS,Z        ;
;                bsf        mainsref,7        ; Show zero crossing occurred for async. program.
;
endphase        btfsc    mainsref,0        ; Look at present value
                goto    mains10            ;
;
; Last was 0, has it changed?
;
mains00            btfss    PORTA,hz        ; Still 0?
                goto    exitint            ; Yes.
                bsf        mainsref,0        ; Update flag,
;                bsf        PORTB,mref        ;
                goto    mainsx            ;
;
; Last was 1, has it changed?
;
mains10            btfsc    PORTA,hz        ; Still 1?
                goto    exitint            ; yes.
                bcf        mainsref,0        ;
;                bcf        PORTB,mref        ;
;
; Zero crossing occurred.
;
; Update phase values from output values.
;
; Look at Phase counter (counts down from 255 - 0).
; Adjust master clock to get as near 255 counts as possible per sequence.
;
;
; Do clock timing.
;
mainsx            movf    phase,w            ; Look at count
                btfsc    STATUS,Z        ; Is it Zero?
                goto    mainsnul        ; Yes, no change.
                btfsc    phase,7            ; Look at phase counter
                goto    mainsdec        ;
;
; Phase has not overflowed, shorten timer interval.
;
mainsinc        incf    clockref,f        ; Clock will run faster.
                goto    mainsnul        ;
;
; Phase has overflowed, lengthen timer interval.
;
mainsdec        decf    clockref,f        ; Clock will run slower.
;
mainsnul        movlw    0FE                ; Start just below 255, so 100% on possible.
                movwf    phase            ; Restart phase counter
                bcf        clockref,7        ; Ensure clock can't get too fast...
;
                bsf        mainsref,7        ; Show zero crossing occurred for async. program.
;
;
; Restore context & return
;
exitint         movf    pcl_temp,w      ; Restore saved regs.
                movwf   PCLATH          ;
                swapf   stat_temp,w        ;
                movwf   STATUS             ;
                swapf   w_temp,f        ;
                swapf   w_temp,w        ;
                retfie                  ; Back to prog.
;
; End of base program.
;
Thank you so much, there is so much to learn
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top