Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Interrupts not firing in PIC18

Status
Not open for further replies.

Manolo Envido

Newbie level 4
Newbie level 4
Joined
Oct 10, 2014
Messages
6
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Location
Argentina
Visit site
Activity points
80
Hi everyone.
I’m having a problem with interrupts in a PIC18F14K50. IRS are not firing and I cannot find what I’m missing here. Interrupts are used for the Timer0 and recieving data from the UART.
The code was ported from a PIC16F877 and we are moving it to newer technology. I’m using MPLABX v2.10 with XC8 v1.31. Everything else seems to be working fine, even the UART transmition.
Sorry the commenst are in spanish, if you need I can translate them for you, but I think they are still readable.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void Timer_Init(void) {
    TMR0ON = 0; // Timer0
    T08BIT = 0; // 8 Bits
    T0CS = 0; // Internal/External
    T0SE = 0; // Rising
    PSA = 0; // Timer 0 (1 - WDT )
 
    TMR0 = 0; // Timer0
    TMR0IE = TRUE; // Enable Timer0 Interrupt
    TMR0IF = FALSE; // Reset Start
 
    T0PS0 = 1; // Divisor 0b111 = 2^(7+1) = 256
    T0PS1 = 1;
    T0PS2 = 1;
 
    PEIE = TRUE; // Habilita interrupciones de Perifericos
    GIE = TRUE; // Habilita interrupciones Globales
}




Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
void UART_Init(void) {
 
    PORTB = 0; // Limpia salidas
 
    SYNC = FALSE; // Modo asynchronous
    SPEN = TRUE; // Habilita RC7/RX y RC6/TX como pines del puerto serie
    DTRXP = FALSE; // No Invertir polaridad
 
    // Config Baud Rate - Pg. 192
    ABDOVF = FALSE; // Auto-baud
    BRG16 = FALSE; // Baud Rate Generator 16 bits
    BRGH = FALSE; // Baud Rate Generator High
    SPBRGH = 0;
    SPBRG = 25; // 9600 Bauds
 
    // Recepcion Rx
    TRISB5 = ENTRADA; // RB5 -> RX ENTRADA
    RX9 = FALSE; // Sin 9no bit de Rx
    SENDB = FALSE; // Break Char
    CREN = TRUE; // Habilita la recepcion continua
    RCIDL = FALSE; // Rx idle flag
    RCIE = TRUE; // Habilita las interrupciones de Rx
 
    // Trasmicion Tx
    TRISB7 = SALIDA; // RB7/TX como salida
    TX9 = FALSE; // 9no bit de Tx
    CKTXP = FALSE; // Tx idle is HIGH
    TXEN = FALSE; // Purga la Tx
    TXEN = TRUE; // Habilita la Tx
    TXIE = FALSE; // No habilita las interrupciones de Tx
 
    // Interrupciones UART
    RCIF = FALSE; // Reset Rx pin flag
    RCIP = FALSE; // Not high priority    
    PEIE = TRUE; // Habilita interrupciones de Perifericos
    GIE = TRUE; // Habilita interrupciones Globales
 
    UART_Clear_Errors();
}




Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void interrupt isr(void) {
    // UART Rx
    if (RCIF) {
        RCIF = FALSE;
        rx_buffer[in] = RCREG;
        in++;
        in %= BUFFER_SIZE;
        rx_empty = FALSE;
    }
 
    // Timer0
    if (TMR0IF) {
        TMR0IF = FALSE;
        TestUART(); // [Debug]
        if (print_timeout) {
            print_timeout--;
        }
    }
}



Thanks for your help
 

The code above show that you are enabling general interrupts inside routines, but do you do that also on main() program ?

Code:
    PEIE = TRUE; // Habilita interrupciones de Perifericos
    GIE = TRUE; // Habilita interrupciones Globales
 

The code above show that you are enabling general interrupts inside routines, but do you do that also on main() program ?

Code:
    PEIE = TRUE; // Habilita interrupciones de Perifericos
    GIE = TRUE; // Habilita interrupciones Globales

Those rutines are the initalizacions and are called form the main at the startup.

Just to be sure tried it from the main itself and still isn't working. I suspect that I'm making a mistake when defining the isr routine, but I can't nail where... or could be wrong somewhere else.
 

have not used pic18 for many years but seem to remember there are #pragma statements to set up the low and high priority ISRs

have you had a look at the Sample PIC18 C Template included with MPLABX? it has a file interrupts.c which may be helpful
 

have not used pic18 for many years but seem to remember there are #pragma statements to set up the low and high priority ISRs

have you had a look at the Sample PIC18 C Template included with MPLABX? it has a file interrupts.c which may be helpful

Yes, it doesn't says much. Since it's made with XC compiler most of it is not used, specially the #pragma comands.

Acording to this template the low and high priority interrupts are define by:

void low_priority interrupt low_isr(void)
and
void interrupt high_isr(void)

Just like I'm doing it...

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/******************************************************************************/
/*Files to Include                                                            */
/******************************************************************************/
 
#if defined(__XC)
    #include <xc.h>         /* XC8 General Include File */
#elif defined(HI_TECH_C)
    #include <htc.h>        /* HiTech General Include File */
#elif defined(__18CXX)
    #include <p18cxxx.h>    /* C18 General Include File */
#endif
 
#if defined(__XC) || defined(HI_TECH_C)
 
#include <stdint.h>         /* For uint8_t definition */
#include <stdbool.h>        /* For true/false definition */
 
#endif
 
/******************************************************************************/
/* Interrupt Routines                                                         */
/******************************************************************************/
 
/* High-priority service */
 
#if defined(__XC) || defined(HI_TECH_C)
void interrupt high_isr(void)
#elif defined (__18CXX)
#pragma code high_isr=0x08
#pragma interrupt high_isr
void high_isr(void)
#else
#error "Invalid compiler selection for implemented ISR routines"
#endif
 
{
 
      /* This code stub shows general interrupt handling.  Note that these
      conditional statements are not handled within 3 seperate if blocks.
      Do not use a seperate if block for each interrupt flag to avoid run
      time errors. */
 
#if 0
    
      /* TODO Add High Priority interrupt routine code here. */
 
      /* Determine which flag generated the interrupt */
      if(<Interrupt Flag 1>)
      {
          <Interrupt Flag 1=0>; /* Clear Interrupt Flag 1 */
      }
      else if (<Interrupt Flag 2>)
      {
          <Interrupt Flag 2=0>; /* Clear Interrupt Flag 2 */
      }
      else
      {
          /* Unhandled interrupts */
      }
 
#endif
 
}
 
/* Low-priority interrupt routine */
#if defined(__XC) || defined(HI_TECH_C)
void low_priority interrupt low_isr(void)
#elif defined (__18CXX)
#pragma code low_isr=0x18
#pragma interruptlow low_isr
void low_isr(void)
#else
#error "Invalid compiler selection for implemented ISR routines"
#endif
{
 
      /* This code stub shows general interrupt handling.  Note that these
      conditional statements are not handled within 3 seperate if blocks.
      Do not use a seperate if block for each interrupt flag to avoid run
      time errors. */
 
#if 0
 
      /* TODO Add Low Priority interrupt routine code here. */
 
      /* Determine which flag generated the interrupt */
      if(<Interrupt Flag 1>)
      {
          <Interrupt Flag 1=0>; /* Clear Interrupt Flag 1 */
      }
      else if (<Interrupt Flag 2>)
      {
          <Interrupt Flag 2=0>; /* Clear Interrupt Flag 2 */
      }
      else
      {
          /* Unhandled interrupts */
      }
 
#endif
 
}



I'm not allowed to share the hole project, but I'll edit some parts so you can take a safe look.

Thanks again for your help.View attachment Interrupts18K.7z
 

Where is timer value reloaded ? You want timer to count from 00 ?

I found these. http://microchip.wikidot.com/faq:31

www.gooligum.com.au/tutorials/midrange/PIC_Mid_C_3.pdf

- - - Updated - - -

Please show your Config Word settings done using #pragma directives.

- - - Updated - - -

http://picguides.com/beginner/interrupts.php

http://singularengineer.com/tag/timer-interrupt-xc-8/

I wrote this and it works fine.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/* 
 * File:   main.c
 * Author: System Administrator
 *
 * Created on October 12, 2014, 7:47 AM
 */
#include <xc.h>
 
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <plib/timers.h>
 
#define _XTAL_FREQ 4000000
 
#define TRUE 1
#define FALSE 0
/*
 * 
 */
 
#pragma config CPUDIV = 0x01, USBDIV = 0x00
#pragma config IESO = ON, PLLEN = ON, FOSC = XT, FCMEN = ON
#pragma config BOREN = ON, BORV = 22, PWRTEN = ON
#pragma config WDTEN = OFF
#pragma config MCLRE = OFF
#pragma config LVP = OFF
#pragma config CP0 = OFF, CP1 = OFF
#pragma config CPD = OFF, CPB = OFF
 
//Timer0
//Prescaler 1:8; TMR0 Preload = 3036; Actual Interrupt Time : 500 ms
 
//Place/Copy this part in declaration section
void InitTimer0() {
  T0CON  = 0x82;
  TMR0H  = 0x0B;
  TMR0L  = 0xDC;
  GIE = 1;
  TMR0IE = 1;
}
 
void interrupt isr(void) {
 
    if (TMR0IF) {
            TMR0IF = 0;
            
            TMR0H = 0x0B;
            TMR0L = 0xDC;
            //Enter your code here
            LATB = ~LATB;
    }
}
 
int main(int argc, char** argv) {
 
    TRISA = 0xFF;
    PORTA = 0x00;
    TRISB = 0x00;
    PORTB = 0x00;
 
    InitTimer0();
 
    while(1) {
 
        
    }
 
    return (EXIT_SUCCESS);
}



- - - Updated - - -

Where were you turning ON Timer0 ?


Code C - [expand]
1
TMR0ON = 0;



Where is


Code C - [expand]
1
TMR0ON = 1;

 
Last edited:
Where is timer value reloaded ? You want timer to count from 00 ?

I found these. http://microchip.wikidot.com/faq:31

www.gooligum.com.au/tutorials/midrange/PIC_Mid_C_3.pdf

- - - Updated - - -

Please show your Config Word settings done using #pragma directives.

- - - Updated - - -

http://picguides.com/beginner/interrupts.php

http://singularengineer.com/tag/timer-interrupt-xc-8/

I wrote this and it works fine.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/* 
 * File:   main.c
 * Author: System Administrator
 *
 * Created on October 12, 2014, 7:47 AM
 */
#include <xc.h>
 
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <plib/timers.h>
 
#define _XTAL_FREQ 4000000
 
#define TRUE 1
#define FALSE 0
/*
 * 
 */
 
#pragma config CPUDIV = 0x01, USBDIV = 0x00
#pragma config IESO = ON, PLLEN = ON, FOSC = XT, FCMEN = ON
#pragma config BOREN = ON, BORV = 22, PWRTEN = ON
#pragma config WDTEN = OFF
#pragma config MCLRE = OFF
#pragma config LVP = OFF
#pragma config CP0 = OFF, CP1 = OFF
#pragma config CPD = OFF, CPB = OFF
 
//Timer0
//Prescaler 1:8; TMR0 Preload = 3036; Actual Interrupt Time : 500 ms
 
//Place/Copy this part in declaration section
void InitTimer0() {
  T0CON  = 0x82;
  TMR0H  = 0x0B;
  TMR0L  = 0xDC;
  GIE = 1;
  TMR0IE = 1;
}
 
void interrupt isr(void) {
 
    if (TMR0IF) {
            TMR0IF = 0;
            
            TMR0H = 0x0B;
            TMR0L = 0xDC;
            //Enter your code here
            LATB = ~LATB;
    }
}
 
int main(int argc, char** argv) {
 
    TRISA = 0xFF;
    PORTA = 0x00;
    TRISB = 0x00;
    PORTB = 0x00;
 
    InitTimer0();
 
    while(1) {
 
        
    }
 
    return (EXIT_SUCCESS);
}



- - - Updated - - -

Where were you turning ON Timer0 ?


Code C - [expand]
1
TMR0ON = 0;



Where is


Code C - [expand]
1
TMR0ON = 1;


All right, timer is working not. For some reazon the TMR0ON = 1; was not in the core program when it needed to be turned on. I can't belive I miss that out, thanks you so much for noticing that out!

The UART resepcion interupt is still no firing, but I suspect is more of a Simulator problem.
 

Zip and post your MPLAB project files so that it can be tested.

I just made this little test program. It sends to the UART what it recieves. Very simple, but the problem remains. Funny thing is that the same proyect but for a PIC16 works like charm, there must be something new in the PIC18 that I'm missing...

View attachment BasicTest-18K.X.zip

And this is the one I uploaded before, I has to delete some part since I'm not allowed to share all the code.
View attachment Interrupts18K.7z
 


Code C - [expand]
1
2
3
TRISB7 = ENTRADA; 
 
RCIE = TRUE;



Some files are missing. Send complete XC8 project files so that it can be opened in MPLAB X.

- - - Updated - - -

UART and Timer0 both are working now.

The main problem was you were toggling PORTB (LATB) and using PORTB for UART. I am not sure whether this really affected or not but another issue was UART Rx pin was not configured as digital IO using ANSEL and ANSELH registers. Turning off ADC on PORTB was necessary atleast ADC on UART pins had to be turned off.

110349d1413416428-uart_timer_sim_ss.png
 

Attachments

  • UART and Timer Test.rar
    139.8 KB · Views: 133
  • uart_timer_sim_ss.png
    uart_timer_sim_ss.png
    32.3 KB · Views: 164
All right! Here is the solution:

Code C - [expand]
1
ANS11 = FALSE; // ADC (Ch.11) same pin as Rx



Since the Rx is in the same pin of the ADC's Channel 11 there was some conflict. I don't know why it's On by default since the datasheet said it's supoced to be off. But now is working! Thank you all so much for your help!
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top