This is not a silicon bug. This is me being a complete idiot.
What is happening is that my uart code was written a year ago and relied on the fact that PIR1, TXIF was high if the UART transmit buffer was empty. My code shovels data pointed to by FSR0 until it hits a "\0" and then disables TXIE. Thus when I load FSR and set TXIE, the data is automatically transmitted A year passes and I write an ISR like this:
.intr CODE 4
; Enhanced Midrange CPU does a context save on:
; W, STATUS, BSR, FSR, PCLATH
; retfie restores context
pagesel $
ifbset INTCON, TMR0IF ; Timer0
goto Timer0_Entry
banksel PIR1 ; Bank #0
ifbset PIR1, TXIF ; Serial transmit
goto SerialTX_Entry
ifbset PIR1, SSP1IF
goto I2C_Entry ; I2C Peripheral
retfie ; Nothing else
Well that's total and utter nonsense. If any interrupt is received other than a timer one - so either UART or I2C, the SerialTX_Entry will be called. TXIF is always set if the UART is enabled and no character is beng held for transmission. So in the above example, I2C_Entry will never be reached.
There is so much bad code here, it's hard to know where to begin. Answering the question directly in pointless until other things are fixed. You're worrying about what color socks to wear when jumping off a cliff.
I'll just mention a few things:
DCOUNT EQU 20H
CNT_100th EQU 21H ; counter for 0.01s
CNT_10th EQU 22H ; counter for 0.1s
CNT_sec EQU 23H ; counter for seconds
CNT_10sec EQU 24H ; counter for tens of seconds
CNT_min EQU 25H ; counter for minutes
CNT_10min EQU 26H ; counter for tens of minutes
RUN EQU 70H ;the run variable that does stuff to things
OCOUNT EQU 28H
ICOUNT EQU 29H
You seem to think you are allocating variables here, but all you are really doing is creating constants that have specific values. Only you know that these values are the addresses of memory locations. That's bad enough, but you are also specifying fixed addresses in the source code. You may have a reason to know what bank these variables are in, but there is no point specifying exact addresses. If you ever move this code to a different PIC, you may find that PIC doesn't have general RAM at 20h. Specify the bank if you need to, but let the linker place the variables within the bank.
The only way to allocate variables with MPASM/MPLINK is to use the RES directive.
Also, I see some comments, but "variable that does stuff to things"!? And what about DCOUNT, OCOUNT, and ICOUNT? What are those supposed to do.
I see you put RUN in the shared region, but didn't point this out. That's both sneaky and obnoxious.
ORG 004H
GOTO ISR
Not only is this silly, but also downright wrong on this machine. First, why not put the interrupt routine at 4? Some code will end up there, so it might as well be the one routine that actually benefits from being there. Second, this is outright wrong on a machine that has more than one code page. The GOTO instruction only encodes the low 11 bits of the address, with the upper 2 address bits coming from PCLATH. You don't know what PCLATH might be set to when a interrupt occurs, so you have one chance in 4 this will actually go to the right place.
Start the interrupt routine at 4 and let everything else flow around it.
ORG 008H
GOTO LOOP
What? Huh? This makes absolutely no sense whatsoever. Did you even look at the datasheet?
BSF STATUS,RP1 ;change to bank 3
BSF STATUS,RP0
Don't do fixed bank setting. At the least use BANKSEL.
CLRF ANSEL ;Using all digital mode, turns off analog
CLRF ANSELH ;Make all analog ports digital
At least we've got some comments here so we can tell what you intended. However, this machine doesn't have ANSEL registers, which even a brief look at the datasheet would have revealed. To make all analog pins digital, you use the ADCON registers. Again, READ THE DATASHEET.
BCF STATUS,RP1 ;change to correct bank to configure TRIS registers
This will actually change the bank to 0 or 1, depending on the RP0 bit setting. The code above does set RP0, so this actually goes to bank 1. However, this dependency is not stated and this code will break if the code above it is modified to leave RP0 set to 0. Again, at least use BANKSEL. There are more clever and efficient ways to manage the bank setting, but BANKSEL is totally reliable and self-contained. When you're just starting, use it instead of trying to get tricky.
GOTO LOOP
LOOP
Where else did you think the code was going to go?
ISR
COMF RUN,1
BCF INTCON,1
RETFIE
In this case, you put RUN in the shared bank and INTCON is mapped to all bank, so these two instructions will actually work. However, you never cleared the interrupt condition! The processor will generate a new interrupt right after interrupts are enabled again by RETFIE. Once again, you actually have to read the datasheet, which is quite clear about how interrupts work.
Then there is the issue of debouncing, which I don't see any of. Even if you were to clear the interrupt condition properly, this still wouldn't work since you'll get multiple counts per button press and release.
I skipped over other issues, and there's more code I haven't even looked at, but I'm quitting here.
Best Answer
Try clearing INTEDG bit of OPTION_REG register. From the datasheet page 30(32):
When PORTD is high, does the LED turn ON or OFF?
Also check out switch contact bounce. Here is a link on it and how to debounce. To check it is the contact bounce causing the thing that is seen as a "problem", add a delay of 500msec or 1 sec after
PORTD=0xff;
in the interrupt routine. If the port is high, your problem is contact bounce if the above suggested solution doesn't solve your problem -that is clearing INTEDG bit.You don't need that
GIE=1;
in the last line of the interrupt block.I have no experience with Hi-Tech C compiler. Chances are low but try doing
INTE=1;
beforeGIE=1;
in the main function.Edit
Try changing
void intMain()
tovoid interrupt intMain()
. According toEdit After Second Question
According to the same manual mentioned above page(299):
You are trying to assign an 'integer' value to a 'character' variable as I quoted below. Define variable i as unsigned char. Compiler should take care of this, but it is worth trying.