PDA

View Full Version : Help with code in Assembly ! Something is Wrong



financecatalyst
- 5th August 2010, 00:56
Someone helped me with this interrupt part of the code in assembly when I was creating a dimmer progam for my fan. Unfortunately I cannot get hold of that person & I don't have any knowledge of assembly, so if someone can help me correct the problem...

This is the only part of the code in assembly, rest is in PBP & I am comfortable dealing with it. Now, this following code controls the speed of a fan based on a variable DimmerVal which is a byte. In my code when I assign DimmerVal=0, fan stops & DimmerVal=255 takes it to full speed. The problem is that the fan speed sometimes variates & automatically goes back to the assigned speed after some moments, looks like some kind of synchronisation error with zero-detector input, but I am not sure because I can't understand this code. can someone help please....

ISR:
asm
movwf wsave
swapf STATUS, W
clrf STATUS
movwf ssave
movf FSR,w
movf fsave
movf PCLATH, W
movwf psave


; get ready to jump within the ISR page
movlw ((INTHAND) >> 8)
movwf PCLATH
btfsc INTCON, INTF
goto ZeroCrossingInt
btfss INTCON, T0IF
goto EndInt
T0Overflow
bcf INTCON, T0IF
bsf _oDimmer
goto EndInt

ZeroCrossingInt
bcf INTCON, INTF
movf _DimmerVal,w
movwf TMR0
bcf _oDimmer

EndInt ; restore the machine state and return from interrupts
movf fsave,w
movwf FSR ; restore FSR
movf psave,w
movwf PCLATH ; restore PCH
swapf ssave,w
movwf STATUS ; restore Status
swapf wsave,f
swapf wsave,w ; restore WREG
retfie
endasm

Kamikaze47
- 5th August 2010, 12:12
If it helps, I have commented the ASM code with the equivalent PBP commands. Its hard to say what the problem is without the rest of the program.


ISR:
asm
movwf wsave ; Save the machine state for restore at end of interrupt routine
swapf STATUS, W
clrf STATUS
movwf ssave
movf FSR,w
movf fsave
movf PCLATH, W
movwf psave


; get ready to jump within the ISR page
movlw ((INTHAND) >> 8) ; PCLATH=INTHAND>>8
movwf PCLATH
btfsc INTCON, INTF ; If INTF=1 THEN GOTO ZeroCrossingInt
goto ZeroCrossingInt
btfss INTCON, T0IF ; If T0IF=0 THEN GOTO EndInt
goto EndInt
T0Overflow ; T0Overflow:
bcf INTCON, T0IF ; T0IF=0
bsf _oDimmer ; oDimmer=1
goto EndInt ; GOTO EndInt

ZeroCrossingInt ; ZeroCrossingInt:
bcf INTCON, INTF ; INTF=0
movf _DimmerVal,w ; TMR0=DimmerVal
movwf TMR0
bcf _oDimmer ; oDimmer=0

EndInt ; restore the machine state and return from interrupts
movf fsave,w
movwf FSR ; restore FSR
movf psave,w
movwf PCLATH ; restore PCH
swapf ssave,w
movwf STATUS ; restore Status
swapf wsave,f
swapf wsave,w ; restore WREG
retfie
endasm

Kamikaze47
- 5th August 2010, 12:21
This may be more helpful to you. This is the same thing, but done using DT's instant interrupts. You also need to INCLUDE the DT_INTS and ReEnterPBP files relevant to your PIC.


ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR0_INT, tmr0_handler, PBP, yes
INT_Handler INT_INT, int_handler, PBP, yes
endm
INT_CREATE
ENDASM

@ INT_ENABLE TMR0_INT
@ INT_ENABLE INT_INT

main:
' your main program
goto main

tmr0_handler:
oDimmer=1
@ INT_RETURN

int_handler:
TMR0=DimmerVal
oDimmer=0
@ INT_RETURN

financecatalyst
- 6th August 2010, 01:13
This may be more helpful to you. This is the same thing, but done using DT's instant interrupts. You also need to INCLUDE the DT_INTS and ReEnterPBP files relevant to your PIC.


ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR0_INT, tmr0_handler, PBP, yes
INT_Handler INT_INT, int_handler, PBP, yes
endm
INT_CREATE
ENDASM

@ INT_ENABLE TMR0_INT
@ INT_ENABLE INT_INT

main:
' your main program
goto main

tmr0_handler:
oDimmer=1
@ INT_RETURN

int_handler:
TMR0=DimmerVal
oDimmer=0
@ INT_RETURN

I am still trying to understand the above code -
Is this code running timer0 interrupt all the time?
I learnt that in DIMMERS, you have to control the +ve half of the cycle only, so timer0 should be loaded after checking the positive half making the PIC pin HIGH and keeping the triac ON for that period.

ALSO FOR THE ASM PART:


btfsc INTCON, INTF ; If INTF=1 THEN GOTO ZeroCrossingInt (1)
goto ZeroCrossingInt ; (2)
btfss INTCON, T0IF ; If T0IF=0 THEN GOTO EndInt (3)
goto EndInt ; (4)
T0Overflow ; T0Overflow: (5)
bcf INTCON, T0IF ; T0IF=0 (6)
bsf _oDimmer ; oDimmer=1 (7)
goto EndInt ; GOTO EndInt (8)

ZeroCrossingInt ; ZeroCrossingInt: (9)
bcf INTCON, INTF ; INTF=0 (10)
movf _DimmerVal,w ; TMR0=DimmerVal(11)
movwf TMR0 ;(12)
bcf _oDimmer ; oDimmer=0(13)


I believe everytime this interrupt will be entered: (Please correct me where I go wrong)
--- Statement (1) in the code will always be true (this is the reason why interrupt has happened), so the code will jump to (9), it will act on (10) & then (11) & (12) -- SO WHERE DOES IT WAIT FOR TIMER0 TO RUN OUT & WHY STATEMENT (13) IS THERE CLEARING _oDimmer when this bit is not set in the sequence I just understood and explained above.

--- When does code enters (5) ? Does after (13) code goes to (3)?

Kamikaze47
- 6th August 2010, 06:07
Statement (1) will not always be true. The interrupt routine services all interrupts. Statements (1)-(4) are just checking which interrupt flag is set (which interrupt went off). If it was the INT interrupt then it jumps to the ZeroCrossingInt section. If it was the TMR0 interrupt then it continues on to the T0Overflow section.

I don't know what else is happening in your program, so I can only tell you what that interrupt routine is doing which is this:

When timer0 overflows: set oDimmer to 1.

When external interrupt (INT) occurs: set timer0 value to "DimmerVal" and set oDimmer to 0.

financecatalyst
- 6th August 2010, 13:27
Statement (1) will not always be true. The interrupt routine services all interrupts. Statements (1)-(4) are just checking which interrupt flag is set (which interrupt went off). If it was the INT interrupt then it jumps to the ZeroCrossingInt section. If it was the TMR0 interrupt then it continues on to the T0Overflow section.

I don't know what else is happening in your program, so I can only tell you what that interrupt routine is doing which is this:

When timer0 overflows: set oDimmer to 1.

When external interrupt (INT) occurs: set timer0 value to "DimmerVal" and set oDimmer to 0.

Is it possible to PM you?

Kamikaze47
- 6th August 2010, 13:34
If you like, but if its a question that you think others may benefit from the answer too, then you may as well ask in the thread.