0
\$\begingroup\$

I'm trying to run some basic code from my textbook onto a PIC18F4321, using the latest XC8 compiler. It's supposed to turn on an LED after 10 seconds, but the LED never turns on. I've checked my wiring and tested the port and it should all work fine. I try debugging via Pickit 3 and running it as a simulated version and the interrupt never triggers, which leads me to think something is wrong with the timer. Any ideas on what might be causing the interrupt to fail?

#include <pic18f4321.h> //include necessary header
#pragma config OSC = INTIO2 
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config BOR = OFF

unsigned char count;
void LEDON();

#pragma code T0ISR = 0x08;
void T0ISR() {
    asm("GOTO LEDON");
}

#pragma code
void main(void) {
    OSCCON = 0x60;
    TRISC = 0x00;
    PORTCbits.RC0 = 0; //start LED off
    INTCONbits.PEIE = 1; //turn on peripheral interrupt
    INTCONbits.GIE = 1; //enable global interrupt
    T0CON = 0x07; //16 bit mode, normal prescale, internal clock
    TMR0H = 0x67;
    TMR0L = 0x69;
    INTCONbits.TMR0IE = 1; //enable timer 1 interrupt
    INTCONbits.TMR0IF = 0; //clear the timer interrupt flag
    T0CONbits.TMR0ON = 1;

    while(1);

    return;
}

 #pragma interrupt LEDON
 void LEDON() {
    PORTCbits.RC0 = 1;
    INTCONbits.TMR0IF = 0;
}
\$\endgroup\$
5
  • \$\begingroup\$ check to see if you are enabling interrupts in correct sequence ............... found this web.archive.org/web/20180403024643/http://… \$\endgroup\$
    – jsotola
    Oct 29 '18 at 1:54
  • 2
    \$\begingroup\$ Can you turn on the LED without using an interrupt? Like starting off with the LED on rather than off. \$\endgroup\$ Oct 29 '18 at 1:59
  • \$\begingroup\$ You forgot to un-comment your header. You sort of need that. \$\endgroup\$
    – user105652
    Oct 29 '18 at 2:10
  • \$\begingroup\$ You had to set ANSELbits.ANSC0 to digital. Default setting is analog \$\endgroup\$
    – Mike
    Oct 29 '18 at 7:00
  • \$\begingroup\$ I don't have the hardware but I guess you need to reload the timer once you're inside the ISR. Could you try this? \$\endgroup\$
    – Abel Tom
    Oct 31 '18 at 14:19
1
\$\begingroup\$

You would do well to read the XC8 manual and look at better example code for the PIC18F family of parts.

Please note that XC8 versions 2.0 and later have a different syntax for declaring interrupt service routines.

This is the syntax that works for me using the Microchip XC8 version 1.45 compiler:

/* 
 * File: main.c
 * Target: PIC18F4321
 * Compiler: XC8 v1.45
 * MPLABX IDX v4.05
 * 
 * Description:
 * 
 *  Use TIMER0 interrupt to turn on LED attached 
 *  to PORTC bit RC0 ten seconds after power on reset.
 */

#pragma config OSC = INTIO2     // Oscillator (Internal oscillator block, port function on RA6 and RA7)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOR = OFF        // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config BORV = 3         // Brown-out Reset Voltage bits (Minimum Setting)
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)
#pragma config CCP2MX = RC1     // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ANA     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config BBSIZ = BB256    // Boot Block Size Select bits ( 256 Word)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
#pragma config CP0 = OFF        // Code Protection bit (Block 0 not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 not code-protected)
#pragma config CPB = OFF        // Boot Block Code Protection bitProtect Boot (Boot block not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 not write-protected)
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 not protected from table reads executed in other blocks)
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block not protected from table reads executed in other blocks)

#include <xc.h>

unsigned char count;

// Wrong way to catch interrupts with XC8
// void LEDON();

// #pragma code T0ISR = 0x08;
// void T0ISR() {
//     asm("GOTO LEDON");
// }

// #pragma code
void main(void) {
    OSCCON = 0x60;
    TRISCbits.RC0 = 0;  // make PORTC bit RC0 and output
    LATCbits.LATC0 = 0; // turn LED off PORTC bit RC0
    T0CON = 0x07; //16 bit mode, prescale 1:256, internal clock
    TMR0H = 0x67; // TIMER0 interrupt asserts 10000128 instruction clocks 
    TMR0L = 0x69; // after the timer is turned on.
    INTCONbits.TMR0IF = 0; //clear the timer interrupt flag
    INTCON2bits.TMR0IP = 1; // select timer interrupt priority
    INTCONbits.TMR0IE = 1; //enable timer interrupt
    RCONbits.IPEN = 0; // select legacy interrupt model
    INTCONbits.PEIE = 1; //turn on peripheral interrupt
    INTCONbits.GIE = 1; //enable global interrupt
    T0CONbits.TMR0ON = 1; // turn on TIMER0

    while(1); // embedded applications in a PIC never return from main()

}

// Wrong way to catch interrupts with XC8
// #pragma interrupt LEDON
// void LEDON() {
//     PORTCbits.RC0 = 1;
//     INTCONbits.TMR0IF = 0;
// }

void interrupt ISR( void )
{
    if (INTCONbits.TMR0IE) // check if TIMER0 interrupt is enabled
    {
        if (INTCONbits.TMR0IF) // check if TIMER0 interrupt has asserted
        {
            INTCONbits.TMR0IF = 0; // clear TIMER0 interrupt assert
            LATCbits.LATC0 = 1; // turn LED on PORTC bit RC0
        }
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ The syntax was all the issue was, thank you! I was quite confused since I knew this timer code had worked before... \$\endgroup\$
    – nerdsley
    Nov 16 '18 at 0:36

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.