3
\$\begingroup\$

I was trying to learn and implement the priority property of interrupts on PIC18F46K22 uC. I use MPLABX and XC8 compiler.

In my code (transformed from a sample code), I have one external interrupt (INT1) and one USART receive interrrupt (RC1IF). External input is a LED driver and USART is a simple echo program driven by a PC terminal.

Some parts of the code are provided below, with comments. Code builds succesfully. But with this "high-low" combination, when USART is active and program succesfully echos text to terminal, I cannot interrupt the transmission with external interrupt which has given by a pushbutton.

Here are ISR's.

void interrupt low_priority USB(void)
{

if (PIR1bits.RC1IF==1)  // check if receive interrupt has fired
{
    t = RCREG1;      // read received character to buffer


    // check if received character is not new line character
    // and that maximum string length has not been reached
    if ( (t != '\n') && (rcindex < STRLEN) )
    {
        rcbuf[rcindex] = t; // append received character to string
        rcindex++;          // increment string index
    }
    else
    {
        rcindex = 0;         // reset string index
        USART_puts(rcbuf);  // echo received string


        for(int x=0; x<STRLEN+1; x++){ //clear
                rcbuf[x] = 0;           // any leftover
            }                           // from
        RCREG1 = 0x00;                  // last
        TXREG1 = 0x00;                  // transmission
    }

    PIR1bits.RCIF = 0;      // reset receive interrupt flag
}
}

and

void interrupt high_priority inticik(void)
{
if(INTCON3bits.INT2IF==1)
{
    LATAbits.LA1 = ~LATAbits.LA1;
    __delay_ms(20);
}

INTCON3bits.INT2IF = 0;
}

This is the interrupt configuration function;

void interrupt_config(void)
{
 //interrupt main configuration
RCONbits.IPEN = 1;        // interrupt priority mode enabled, H or L interrupts
INTCONbits.GIE_GIEH = 1;  // high priority interrupts are enabled
INTCONbits.PEIE_GIEL = 1; // low priority interrupts are enabled

//pin interrupt 1&2 enable + priority assignments + edge selection
TRISBbits.TRISB2 = 1;
ANSELBbits.ANSB2 = 0;
INTCON3bits.INT1IE = 1; // int1 is enabled
INTCON3bits.INT2IE = 1; // int2 is enabled
INTCON3bits.INT1IP = 1; // int1 is high priority
INTCON3bits.INT2IP = 1; // int2 is high priority
INTCON2bits.INTEDG1 = 1;  // rising edge
INTCON2bits.INTEDG2 = 1;  // rising edge

//EUSART interrupt enable + priority assignments

PIE1bits.RC1IE = 1; //receive interrupt enabled
PIE1bits.TX1IE = 1; //transmit interrupt enabled
IPR1bits.RC1IP = 0; // receive is low priority
IPR1bits.TX1IP = 0; // transmit is low priority
}

And here is the main function.

int main(void)
{
TRISAbits.TRISA1 = 0;
LATA = 0x00;
interrupt_config();

USART_init();

USART_puts("Init complete!\n");

//main loop
while(1)
{
    Sleep();
}

return 0;
}

Other parts of the code such as USART functions and "config.h" conf. bit headers are not provided because of irrelevancy.

Thank you.

Edit

I forgot to mention, when i change the,

"void interrupt low_priority USB(void)"

statement to

"void interrupt high_priority USB(void)"

program succesfully works and echoes on terminal. But when set as "low_priority", USART module does not work on terminal. Only external interrupt runs successfully.

\$\endgroup\$
  • 1
    \$\begingroup\$ Regardless of the answer to your (good) question you shouldn't delay in an interrupt. Set a flag and delay elsewhere in the main program. \$\endgroup\$ – David May 9 '15 at 19:37
  • \$\begingroup\$ Are you using INT1 or INT2? The intro text says INT1, the code initialises both and the interrupt uses INT2. \$\endgroup\$ – David May 9 '15 at 19:38
  • \$\begingroup\$ Both INT1 and INT2 pins also have a comparator which I dint see you disabling. All analogue functions need disabling to use a pin as a digital input. \$\endgroup\$ – David May 9 '15 at 19:41
  • \$\begingroup\$ Thanks for the comment. I am using INT1 for my purpose, INT2 was just there for further applications, I will disable it and try again now. Also, I assume you mentioned clearing ANSELB register bits by disabling the analogue functions, or am I wrong? At the definition of ANSELB reg., it says "digital input buffer is enabled" in datasheet. Or is there something else to change? \$\endgroup\$ – Esfand May 10 '15 at 12:58
1
\$\begingroup\$

Altough I'm not sure why, this solved my problem.

From PIC18F46K22 Datasheet

At Power-On-Reset, ADON bit is cleared, which means it disables the A/D converter by default, right? This means whether or not I disable the A/D converter, it is disabled automatically.

ADCON0bits.ADON = 0;

But, I did add this line to my configuration and it worked, now both external (high priority) interrupt and USART (low priority) interrupt works at the same program.

It is a solution, but i still wonder why it worked.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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