1
\$\begingroup\$

need some help with interrupts and the 16f887.

I'm using MPLAB and writing my code in C. I am using the 44-pin demo board from Microchip. There is a push button wired to RBO/INTO which is normally high, and pulled low when the button is pressed.

I've already verified that the input and push button are working, however I dont think I'm setting up the interrupt properly. When the button is pressed, I'm try to turn PORTD on, and when the interrupt returns, PORTD is turned off.

However when I run the code, PORTD turns on right away. Any ideas?

#include <pic16f887.h>
#include <htc.h>

__CONFIG (DEBUG_ON, LVP_OFF, FCMEN_OFF, IESO_OFF, BOREN_OFF,
    CPD_OFF, CP_OFF, MCLRE_ON, WDTE_ON, FOSC_INTRC_NOCLKOUT, BOR4V_BOR21V);


void intMain() {
PORTD=0xff;
INTF=0;
GIE=1;
}


void main(void){

 TRISB = 0xff;        //set PORTB as inputs
 TRISD = 0x00;        // Set PORTD as an Output
 ANSEL = 0x00;
 ANSELH = 0x00;
 GIE=1;
 INTE=1;
 PORTD=0x00;
 while(1)
 {
     PORTD=0x00;

 }
}

EDIT

I've updated my code based on some suggestions below. Here is the current code. I've written it so that, when the ISR is called, port D will count from 0 to 256, then clear and exit the ISR. I've written in a trap to stop the ISR from exiting and keep it in an endless loop. When i start the controller, the port counts to 256, clears and restarts repeatedly.

#include <pic16f887.h>
#include <htc.h>

__CONFIG (DEBUG_ON, LVP_OFF, FCMEN_OFF, IESO_OFF, BOREN_OFF,
    CPD_OFF, CP_OFF, MCLRE_ON, WDTE_ON, FOSC_INTRC_NOCLKOUT, BOR4V_BOR21V);

void interrupt intMain() {
int i,k;
i=0;
k=0;
while(i<256)
{
    while(k<3000) //delay
        k++;
    i++;
    k=0;
    PORTD=i;
}
while(1){} //trap
//INTF=0;
}

void main(void){

 TRISB = 0xff;        //set PORTB as inputs
 TRISD = 0x00;        // Set PORTD as an Output
 ANSEL = 0x00;
 ANSELH = 0x00;
 INTE=1;
 GIE=1;
 INTEDG=0;
 nRBPU=0;
 WPUB0=1;
 PORTD=0x00;
 while(1)
 {
     PORTD=0x00;

 }
}
\$\endgroup\$
2
  • \$\begingroup\$ What demo board are you using? \$\endgroup\$
    – m.Alin
    Dec 15, 2011 at 10:26
  • \$\begingroup\$ Microchips 44-pid demo board that came with the PICkit2. \$\endgroup\$
    – Michael
    Dec 15, 2011 at 16:15

4 Answers 4

3
\$\begingroup\$

Try clearing INTEDG bit of OPTION_REG register. From the datasheet page 30(32):

INTEDG: Interrupt Edge Select bit
        1 = Interrupt on rising edge of INT pin
        0 = Interrupt on falling edge of INT pin

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; before GIE=1; in the main function.

Edit

Try changing void intMain() to void interrupt intMain(). According to

HI-TECH C® for PIC10/12/16 User’s Guide 3.8 INTERRUPT HANDLING IN C (Page 86) Link

Edit After Second Question

According to the same manual mentioned above page(299):

To produce an infinite loop, use for(;;).

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.

...
int i,k;
...
PORTD=i;
...
\$\endgroup\$
4
  • \$\begingroup\$ Made the INTEDG change. I appreciate the suggestion, but I dont think switch bounce is my problem. When the program starts, PORTD goes hi (all bits) right away, before the switch is activated. \$\endgroup\$
    – Michael
    Dec 15, 2011 at 16:39
  • \$\begingroup\$ Did you tried adding a delay of 1 sec after "PORTD=0xff;" in the interrupt routine? That will help us see if it goes into the interrupt routine. \$\endgroup\$ Dec 15, 2011 at 16:47
  • \$\begingroup\$ changing to void interrupt intMain() worked great. Thanks for the link. However, this has lead to some other interesting problems. I've edited my initial post for details. thanks. \$\endgroup\$
    – Michael
    Dec 15, 2011 at 17:48
  • \$\begingroup\$ I'm glad you solved that one. However, it would have been better if you created a new question for that one. \$\endgroup\$ Dec 16, 2011 at 6:48
0
\$\begingroup\$

I don't know about Hi-tec C, but certainly in others you have to do special things to get interrupts working:

Create an interrupt function at a specific memory location - this is the interrupt "vector" address - usually 0x80 or 0x88 depending on the microcontroller - check the data sheet. This function should have one command in it, which is an ASM "GOTO" command to your real interrupt routine. This should be flagged as an interrupt function (not sure how in HTC) so that it uses the RETFIE instruction instead of the normal RETURN instruction, and also handles the preserving of registers on the stack.

Exactly how you arrange all this in HTC I can't tell you - I suggest you read the Hi-Tec C Manual - it should be installed on your system somewhere.

\$\endgroup\$
2
  • \$\begingroup\$ You don't have to add any command in some compilers like MikroC PRO from Mikroelektronika, it is automatically done by the compiler itself. But I don't know HTC, too :) \$\endgroup\$ Dec 15, 2011 at 13:51
  • \$\begingroup\$ according to the documentation, HTC handles the ISR vectoring. \$\endgroup\$
    – Michael
    Dec 15, 2011 at 18:30
0
\$\begingroup\$

It looks like you forgot to turn on the weak pullup for RB0. Without that the pin will just float when the button is not pressed.

I don't know your compiler, but manually resetting GIE in the interrupt routine makes no sense. That should be done with a RETFIE instruction. I don't know how to explain that to your compiler. You'll have to dig thru the manual yourself. Or easier, just write it in assembler so you know exactly what instructions the machine is running.

Added:

Your second code tries to compare INT variables to values greater than 255. That implies INT is more than a byte. Is that really true in your compiler? Remember, this is a 8 bit machine, so it might not be.

\$\endgroup\$
1
  • \$\begingroup\$ The GIE in the ISR was an oversight. I've cleared the nRBPU bit (pull up resistor for portb), and set WPUB0 (pull up resistor for RB0) with no change. \$\endgroup\$
    – Michael
    Dec 15, 2011 at 16:46
-1
\$\begingroup\$

It's because you have watchdog timer enabled (WDTEN_ON) is causes you controller to reset.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.