I am having a problem with my timer interrupt routine for a project I am working on using an AT89S52. The program below should toggle the bits on ports 1 and 2 each second. It should call the timer interrupt 160 times per second and decrement R2 each time. When R2 reaches zero it should toggle the bits on ports 1 and 2. When I run the program it only calls the timer interrupt once and then gets stuck in the "HERE" loop.
Everything in my program seems to be OK. What's wrong? Is there something in the way I'm enabling or disabling the interrupt? I don't know where to begin looking. Everything seems correct to me.
Moderators note: used code tags for asm
Everything in my program seems to be OK. What's wrong? Is there something in the way I'm enabling or disabling the interrupt? I don't know where to begin looking. Everything seems correct to me.
Code:
ORG 0
JMP RESET
org 003
JMP ISERV ;NOT USED IN THIS EXAMPLE
org 000Bh
JMP TCSERV ;TIMER 0 INTERRUPT SERVICE ROUTINE
;
org 0030h
;
RESET:
MOV P1,#00H ;MAKE P1 AN OUTPUT PORT
MOV P2,#00H ;MAKE P2 AN OUTPUT PORT
MOV P3,#0FFH ;MAKE P3 AN INPUT PORT
;
START: MOV R2,#160 ;INITALIZE R2 (NUMBER OF TIMES WE CALL THE TIMER INTERRUPT BEFORE TOGGLING P1 AND P2)
MOV A,#055H ;INITAL PORT VALUE, HALF THE BITS OF THE PORT ARE ON, HALF ARE OFF.
MOV IE,#00000010b ;SETS TIMER 0 OVERFLOW INTERRUPT BUT DOESN'T ENABLE IT. (THE GATE (IE.7) IS ZERO).
CALL TINIT ;INITALIZE THE TIMER
HERE: MOV P1,A ;OUTPUT TO PORT 1
MOV P2,A ;OUTPUT TO PORT 2
SJMP HERE ;KEEP DOING IT, TOGGLING THE BITS AFTER EACH 160 TIMER INTERRUPTS.
TINIT: MOV TMOD, #01 ;Put Timer 0 into Mode 1, (16 bit timer)
MOV TL0,#0B7H ;XTAL FREQUENCY = 3.579545MHZ. CLOCK FREQUENCY=XTAL/12=3.579545M/12=298.295K
MOV TH0, #0F8H ;THE INTERUPT CALLS 160 TIMES/SEC SO IT SHOULD COUNT 298.295417K/30 = 1864 = 0748H
;SINCE THE COUNTER COUNTS UP WE WILL NEED TO SUBTRACT 26D7 FROM FFFF. 0748H- ;FFFFH=F8B7H
SETB TR0 ;THIS SHOULD START THE TIMER
SETB IE.7 ;PUTS A 1 IN THE GATE BIT OF IE AND SHOULD ENABLE TIMER 0 OVERFLOW.
RET
TCSERV: ;
CLR IE.7 ;DISABLE INTERRUPTS
CLR TR0 ;STOPS TIMER 0
CLR TF0 ;RESETS TIMER 0 OVERFLOW FLAG
MOV TMOD, #01H ;PUTS TIMER 0 INTO MODE 1 (16 bit timer)
MOV TL0,#0B7H ;RELOAD THE TIMER
MOV TH0,#0F8H
DJNZ R2,DONE ;HAS ONE SECOND PASSED?
MOV R2,#160 ;IF YES THEN RESET FOR ANOTHER SECOND AND
CPL A ;TOGLE BITS ON OUTPUT PORT
DONE: SETB IE.7 ;TURN THE TIMER INTERRUPT BACK ON
SETB TR0 ;RESTART THE TIMER
RET ;RETURN TO "HERE" LOOP
ISERV: RET ;THIS DOES NOTHING
END
Last edited by a moderator: