Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
???
01/17/06 16:48
Read: times


 
#107610 - Program only sees external int0 once...
I'm having a really strange problem. I have been reading the forums all week in search of an answer but all I found was one guy who has the exact same problem but he never posted his solution.

I've written a small test program that bitbangs SPI to my display driver chips. It has a very small interrupt handler for an external INT0:

XRL keypressed, #01h ; flip this so the alternate numbers are sent to the display
MOV AGAIN, #01h ; set this flag so the main loop knows to send data to the display
RETI

My problem is a weird one, however. The interrupt get triggered once and never sees another. I know the program is servicing the interrupt that one time and going back into the main loop because I've now included watchdog code and it will reset if it doesn't go back to the main loop. So the processor isn't locking up, it's just ignoring further interrupts.

To make it even stranger, it works perfectly if I go into boot-loader mode and either start the program from FLIP or even if I hit the reset button (and I mean every single time, not a fluke). When I remove power it goes back to only seeing the first interrupt.

I'm using an AT89C51ED2. This is my entire test routine that has been through a zillion iterations trying to solve this. It's a bit wordy but I think simple enough to understand.

I'm not one to beg for help on the internet but I'm 100% out of ideas!

MOSI EQU P2.0
MISO EQU P2.1
SCK EQU P2.2

SPI_OutA EQU 21H ; Data we wish to send to Slave.
LOOPBITS EQU 30H ; Bits to transfer
LOOPBYTEs EQU 31H ; Bytes to transfer
LOOPWORDS EQU 32H ; Words to transfer
CHIPSELECT EQU 33H ; 20h is the toshiba, 10h is the 2nd maxim, 8h is the 1st maxim
keypressed EQU 23H ;
AGAIN EQU 22H

org 00000h
LJMP BEGIN

org 000003h
ljmp int0_it

org 0100h
BEGIN:

ORL WDTPRG,#07;/*2.275s @ FOSCA=11.059200 MHz */
MOV WDTRST,#1Eh; Enable watchdog
MOV WDTRST,#0E1h; Enable watchdog

MOV P0,#00h ; set P0 all low
MOV LOOPBITS,#08h ; 8 Bits to transfer (fixed)
MOV LOOPBYTES,#02h ; 2 Bytes to transfer (fixed)
MOV AUXR, #00001001B; go into low EMI mode
SETB EX0 ; enable int0 externally
SETB IT0 ; set for edge triggering
SETB EA ; enable interrupts globally

; send 99.9 to the display and turn it on
MOV LOOPWORDS,#05h ; Words to transfer
MOV DPTR, #0050Eh ; Set data pointer
MOV CHIPSELECT, #20h ; 20h is the toshiba, 10h is the 2nd maxim, 8h is the 1st maxim
LCALL SPIDISPLAY

loop:

MOV WDTRST,#1Eh ; babysit the dog, prevent self-reset
MOV WDTRST,#0E1h; babysit the dog, prevent self-reset

MOV R6, AGAIN
CJNE R6, #01h, loop ; if the interrupt routine ran, go through the following code to send data to the displays

MOV R7, keypressed
CJNE R7, #01h, ONEFORTHEROAD ; send 27.4 to the display every other time. If not, skip below and change DPTR so 23.3 is sent
MOV LOOPWORDS,#03h ; Words to transfer via SPI routine
MOV DPTR, #00500h ; Set data pointer to 500h for SPI routine
MOV CHIPSELECT, #20h ; 20h is the toshiba, 10h is the 2nd maxim, 8h is the 1st maxim
JMP GITERDONE

ONEFORTHEROAD:
MOV LOOPWORDS,#03h ; Words to transfer via SPI routine
MOV DPTR, #00506h ; Set data pointer to 506h for SPI routine
MOV CHIPSELECT, #20h ; 20h is the toshiba, 10h is the 2nd maxim, 8h is the 1st maxim

GITERDONE:
LCALL SPIDISPLAY ; run the SPI routine to light up display

MOV AGAIN, #00h ; reset the flag so we go back into main loop
LJMP loop


SPIDISPLAY:

MOV P2, #18h ; Set MOSI, MISO, SCK Low, Maxim chips high, Toshiba low
MOV SPI_OutA, #00h
MOV A, CHIPSELECT
JB ACC.5, XFERA ; If the toshiba bit is set skip the maxim chip select
XRL P2, A

XFERA:

MOV A,#00h
MOVC A, @A+DPTR
MOV R0, A
MOV SPI_OutA, R0 ; Load byte from table

XFERB:

MOV C,SPI_OutA.7 ; Move bit 7 into Carry (SPI is MSB first).
MOV MOSI,C ; I/O port reflects the Carry bit, which is the Data bit.
SETB SCK ; Generate SCK rising edge, after Data is stable.
CLR SCK ; Generate SCK falling edge, after data read in.
MOV A,SPI_OutA ; Accumulator is temp holder for shift operation.
RL A ; Rotate left (but not through Carry!).
MOV SPI_OutA, A ; Prepare bit 7 for next transfer to Slave.
DJNZ LOOPBITS,XFERB ; Decrement LOOPBIT. Jump if not zero to XFERB

MOV LOOPBITS,#08h ; One byte done, reset BIT counter
INC DPTR ; Increment data pointer to grab the next byte
DJNZ LOOPBYTES,XFERA ; Decrement LOOPBYTES and jump to XFERA if it's not zero
MOV LOOPBYTES,#02h

MOV A, CHIPSELECT ; Get the chip select (maxim1, maxim2, or toshiba)
XRL P2, A ; Set the proper chip select to the opposite of what it was
JBC P2.5, TOSHIBA_FAIL ; if the above instruction set the Toshiba chip select high, set it low and move on

TOSHIBA_FAIL:

DJNZ LOOPWORDS,XFERA ; Send all the words like a good program should
RET

int0_it:


XRL keypressed, #01h ; flip this so the alternate numbers are sent to the display
MOV AGAIN, #01h ; set this flag so the loop knows to send data to the display
RETI

org 00500H
DB 22h,01h,23h,47h,24h,04h ; 27.4 to the toshiba
DB 22h,02h,23h,43h,24h,03h ; 23.3 to the toshiba
DB 07h,01h ; Maxim self-test
DB 00h,02h,22h,09h,23h,09h,24h,09h,10h,00h ; Toshiba start up

THEEND:
END

List of 12 messages in thread
TopicAuthorDate
Program only sees external int0 once...            01/01/70 00:00      
   Int flag ?            01/01/70 00:00      
   your code is tough to read            01/01/70 00:00      
      runs fine in the emulator I have...            01/01/70 00:00      
         to reiterate what Erik said            01/01/70 00:00      
            the great disappearing act            01/01/70 00:00      
               doh            01/01/70 00:00      
               I'll strip it down            01/01/70 00:00      
                  as suggested            01/01/70 00:00      
         divide and conquer            01/01/70 00:00      
         Not That            01/01/70 00:00      
   ah ha            01/01/70 00:00      

Back to Subject List