??? 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 |
Topic | Author | Date |
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 |