Interrupt Routine not firing

General discussion on mikroPascal PRO for PIC.
Author
Message
philcr
Posts: 24
Joined: 24 Jul 2014 09:37

Interrupt Routine not firing

#1 Post by philcr » 11 Jan 2015 15:15

Hi Guys,

I am learning about PIC development, and I have been tinkering with interrupts, I am using a RTC clock module to wake my PIC every minute for reading temp, time etc. I have been having issues with the interrupt routine not working, So I put the code in the main loop so when my PIC comes back to life the code is executed to reset registers. Can anyone help it would be awesome to have this happen in the Interrupt procedure instead of the main loop.

Code: Select all


program RealTimeClock;

//uses RTC2_DS1307;
  uses RTC_DS3231SN, EEPROM_24LC512;
  
{ Declarations section }

// For DS1307 to uses
Var ts : String[8];   // String to hold the time from DS1307
Var ds : String[10];  // String to hold the date from DS1307

Var text3,text4 : String[20];
Var text1 : String[10];
Var text2 : String[3];
Var EEPROM_Byte : Byte;

Var Values : Array[256] of Byte;

Var Count : Byte;

// LCD module connections
var LCD_RS : sbit  at LATE4_bit;
var LCD_EN : sbit  at LATE5_bit;
var LCD_D4 : sbit  at LATE0_bit;
var LCD_D5 : sbit  at LATE1_bit;
var LCD_D6 : sbit  at LATE2_bit;
var LCD_D7 : sbit  at LATE3_bit;

var LCD_RS_Direction : sbit at TRISE4_bit ;
var LCD_EN_Direction : sbit at TRISE5_bit ;
var LCD_D4_Direction : sbit at TRISE0_bit;
var LCD_D5_Direction : sbit at TRISE1_bit;
var LCD_D6_Direction : sbit at TRISE2_bit;
var LCD_D7_Direction : sbit at TRISE3_bit;
// End LCD module connections

var Flag : Bit;

Procedure Interrupt_Low;
Begin
     Flag := 1;
     if TestBit(INTCON, INT0IF) = 1 then
     begin
          INTCON.INT0IF := 0;
          INTCON.INT0IE := 1;
          ClearBit(INTCON, INT0IF); //Clear the interrupt Flag
         
     end;
end;

begin        org 0x1000;
  orgall(0x1000);
  { Main program }

  TRISB := 1;
  INTCON := 0x10;
  INTCON2.6 := 0;
  
  TRISG0_Bit := 0;
  PORTG.0 := 1;
  
  EEPROM_Byte := 99;
  //initialize the LCD display
  Lcd_Init();                        // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);               // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
  
  Lcd_Out(1,1,'Booted !');
  //initialize the I2C
  i2c1_init(100000);
  Lcd_Out(1,1,'I2C Init Done !');

  initRTC; //Initialize Connection to the RTC
  
  RtcSetInterruptMinute;
  RTCClearInterrupt;

  Lcd_Out(1,1,'RTC Init Done !');
  delay_ms(1000);
  Lcd_Cmd(_LCD_CLEAR);
  while true do
    begin
    
     if TestBit(INTCON, INT0IF) = 1 then
     begin
          INTCON.INT0IF := 0;
          INTCON.INT0IE := 1;
          ClearBit(INTCON, INT0IF); //Clear the interrupt Flag
          RTCClearInterrupt; //Clear the RTC Interrupt Flag
     end;

     RtcTimeDateStr(text3, text4);  //Get the Time and Date
     Lcd_Out(1, 1, text3);         // Print text at LCD
     Lcd_Out(2, 1, text4);         // Print text at LCD
     RtcTempStr(text1);
     Lcd_Out(1,9,text1);
     Lcd_Chr(1,15,223);                                         // Print degree character, 'C' for Centigrades
                                                             // Different LCD displays have different char code for degree
     Lcd_Chr(1,16,'C');


    delay_ms(2500);
    LCD_CMD(_LCD_CLEAR);
    LCD_Out(1,1,'Sleeping....');
    PORTG.0 := 0;
    asm
        sleep; //Send Processor to sleep
    end;

    end;
end.

Many thanks in advance for your assistance.

Phil

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Interrupt Routine not firing

#2 Post by janni » 11 Jan 2015 16:11

For any interrupt to work one has to enable it. Furthermore, INT0 cannot work as low priority interrupt, not to mention that for low priority interrupts to work one has to enable the priority feature (bit RCON.IPEN). Change your ISR to

Code: Select all

Procedure interrupt;
 Begin
   if INTCON.INT0IF then
     begin
        INTCON.INT0IF:=0;
        Flag:=1;
     end;
 end;
activate the interrupt in proper sequence

Code: Select all

  INTCON.INTEDG0:=1;
  INTCON.INT0IE:=1;
  INTCON.GIE:=1;
and test the Flag (and clear it if set) in main to undertake proper action in response to INT0 interrupt.

BTW, use LAT register for switching single output bit (LATG.0 instead of PORTG.0).

philcr
Posts: 24
Joined: 24 Jul 2014 09:37

Re: Interrupt Routine not firing

#3 Post by philcr » 11 Jan 2015 18:09

Thanks for the advice, I tried what you suggested with the intcon.bit and it didn't work I must be missing something really basic.if I posted my code any chance you would be so kind as to take a look?

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Interrupt Routine not firing

#4 Post by janni » 11 Jan 2015 18:51

Sure, it's the only way anyone may help :) .

philcr
Posts: 24
Joined: 24 Jul 2014 09:37

Re: Interrupt Routine not firing

#5 Post by philcr » 11 Jan 2015 19:49

I think I implemented your example bits as expected, I don't get my PIC waking up.

Code: Select all

program RealTimeClock;

//uses RTC2_DS1307;
  uses RTC_DS3231SN, EEPROM_24LC512;
  
{ Declarations section }

// For DS1307 to uses
Var ts : String[8];   // String to hold the time from DS1307
Var ds : String[10];  // String to hold the date from DS1307

Var text3,text4 : String[20];
Var text1 : String[10];
Var text2 : String[3];
Var EEPROM_Byte : Byte;

Var Values : Array[256] of Byte;

Var Count : Byte;

// LCD module connections
var LCD_RS : sbit  at LATE4_bit;
var LCD_EN : sbit  at LATE5_bit;
var LCD_D4 : sbit  at LATE0_bit;
var LCD_D5 : sbit  at LATE1_bit;
var LCD_D6 : sbit  at LATE2_bit;
var LCD_D7 : sbit  at LATE3_bit;

var LCD_RS_Direction : sbit at TRISE4_bit ;
var LCD_EN_Direction : sbit at TRISE5_bit ;
var LCD_D4_Direction : sbit at TRISE0_bit;
var LCD_D5_Direction : sbit at TRISE1_bit;
var LCD_D6_Direction : sbit at TRISE2_bit;
var LCD_D7_Direction : sbit at TRISE3_bit;
// End LCD module connections

var Flag : Bit;

Procedure interrupt;
Begin
     if TestBit(INTCON, INT0IF) = 1 then
     begin
          INTCON.INT0IF := 0;
          Flag := 1;
     end;
end;

begin        org 0x1000;
  orgall(0x1000);
  { Main program }

  TRISB := 1;
  //INTCON := 0x10;
  //INTCON2.6 := 0;
  
  INTCON2.INTEDG0:=0;
  INTCON.INT0IE:=1;
  INTCON.GIE:=1;
  
  LATG.0 := 0;
  
  //EEPROM_Byte := 99;
  //initialize the LCD display
  Lcd_Init();                        // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);               // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
  
  Lcd_Out(1,1,'Booted !');
  //initialize the I2C
  i2c1_init(100000);
  Lcd_Out(1,1,'I2C Init Done !');

  initRTC; //Initialize Connection to the RTC
  
  RtcSetInterruptMinute;

  Lcd_Out(1,1,'RTC Init Done !');
  delay_ms(1000);
  Lcd_Cmd(_LCD_CLEAR);
  while true do
    begin
    
     if Flag = 1 then
     begin
          LCD_Out(1,1, 'Interrupt');
          RTCClearInterrupt; //Clear the RTC Interrupt Flag
          Flag := 0;
     end
     else LCD_Out(1,1, 'No Interrupt');
     
     RtcTimeDateStr(text3, text4);  //Get the Time and Date
     Lcd_Out(1, 1, text3);         // Print text at LCD
     Lcd_Out(2, 1, text4);         // Print text at LCD
     RtcTempStr(text1);
     Lcd_Out(1,9,text1);
     Lcd_Chr(1,15,223);                                         // Print degree character, 'C' for Centigrades
                                                             // Different LCD displays have different char code for degree
     Lcd_Chr(1,16,'C');


    delay_ms(2500);
    LCD_CMD(_LCD_CLEAR);
    LCD_Out(1,1,'Sleeping....');
    LATG.0 := 1;
    asm
        sleep; //Send Processor to sleep
    end;

    end;

end.

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Interrupt Routine not firing

#6 Post by janni » 11 Jan 2015 22:18

Any enabled interrupt wakes processor from sleep. Are you sure there's proper signal on INT0 pin to wake the processor up (falling edge, as you set it)?

You may check if INT0 interrupt is working by skipping the sleep instruction for the moment (add a delay after LCD_Out(1,1, 'Interrupt') to see the message).

hadv
Posts: 116
Joined: 29 Mar 2013 12:55

Re: Interrupt Routine not firing

#7 Post by hadv » 12 Jan 2015 01:43

I don't know which controller you are using, but are you sure INT0 is a low-priority interrupt or you can set it to be a low-priority interrupt?
I checked a couple of 18F datasheets and INT0 is ALWAYS high-priority.
What Janni says is not quite right, it should read 'any enabled external interrupt can wake the controller from sleep'.
E.g. on a 18F4550 Timer0 can not wake up the device from sleep.

philcr
Posts: 24
Joined: 24 Jul 2014 09:37

Re: Interrupt Routine not firing

#8 Post by philcr » 12 Jan 2015 10:54

Guys,

I am using the PIC18F67J50 processor, with my original code it is waking up every minute on the signal from the RTC going low but not using the interrupt, when I try to get it to use the interrupt procedure as Janni suggested it doesn't work. It doesn't wake up.

I am really greatful for your help so far.

Phil

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Interrupt Routine not firing

#9 Post by janni » 12 Jan 2015 15:02

philcr wrote:I am using the PIC18F67J50 processor, with my original code it is waking up every minute on the signal from the RTC going low but not using the interrupt, when I try to get it to use the interrupt procedure as Janni suggested it doesn't work. It doesn't wake up.
Does the interrupt work at all? Have you tried what I suggested? I noticed that you moved code to 0x1000 - if you're using a bootloader, maybe it overwrites the jump to ISR that compiler places at 0x08.
hadv wrote:What Janni says is not quite right, it should read 'any enabled external interrupt can wake the controller from sleep'.
I was thinking only about INTx interrupts, pertinent to the problem, but I should have written so. Anyway, neither 'any' nor 'external' is a proper qualifier - the datasheet uses 'any available' which does not explain much, but is the only appropriate one (there are other interrupt sources, like ADC, Timer1 working as RTC, and more that may wake processor from sleep).
Last edited by janni on 12 Jan 2015 15:48, edited 1 time in total.

philcr
Posts: 24
Joined: 24 Jul 2014 09:37

Re: Interrupt Routine not firing

#10 Post by philcr » 12 Jan 2015 15:17

It definitely does work with INT0 with falling edge set, you are maybe correct with the boot loader code being at the start of the program memory and the ISR being at 0x0008, Am I correct in understanding that it is possible to change the address of the ISR?

Again, I really appreciate your help guys, I'm not confident enough to blitz my boot loader and start coding manual.

Kind Regards

Phil

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Interrupt Routine not firing

#11 Post by janni » 12 Jan 2015 15:41

philcr wrote:Am I correct in understanding that it is possible to change the address of the ISR?
One may move the ISR body, but not interrupt vector (address to which processor branches at interrupt) which is hardware wired at 0x08.
I'm not confident enough to blitz my boot loader and start coding manual.
So you're using somebody else's bootloader, but it may still have provisions for interrupts. Do you have some description of this bootloader (like where it expects to find ISRs)?

philcr
Posts: 24
Joined: 24 Jul 2014 09:37

Re: Interrupt Routine not firing

#12 Post by philcr » 12 Jan 2015 15:55

I understand that the bootloader on my processor is the microchip boot loader, I haven't investigated documentation for it though as up until now it has just worked. I have programmer that I have never used, for fear of breaking my dev board.

The dev board I'm using is http://www.robot-electronics.co.uk/htm/dev-p182432.htm which comes with Microchips USB bootloader already programmed. Can anyone advise me as this heading to completely uncharted territory for me.

Kind Regards

Phil

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Interrupt Routine not firing

#13 Post by janni » 12 Jan 2015 16:12

The link you've given contains the needed info:
The boot loader occupies internal program memory:
PIC18, 0x0000 - 0x0FFF. Application programs start at 0x1000. High/Low interrupt Vectors are at 0x1008/0x1018
It means that the bootloader contains a jump from 0x08 to 0x1008. All you have to do is org your ISR to 0x1008.

philcr
Posts: 24
Joined: 24 Jul 2014 09:37

Re: Interrupt Routine not firing

#14 Post by philcr » 12 Jan 2015 16:39

Thanks Janni,

I will give this a try when I get in tonight, fingers crossed.

Regards

Phil

philcr
Posts: 24
Joined: 24 Jul 2014 09:37

Re: Interrupt Routine not firing

#15 Post by philcr » 12 Jan 2015 20:45

Hi Guys,

I attempted the following with my Interrupt procedure

Code: Select all

Procedure interrupt; org 0x1008;
Begin
     Flag := 1;
     if TestBit(INTCON, INT0IF) = 1 then
     begin
          INTCON.INT0IF := 0;
          Flag := 1;
     end;
end;
I am unable to build my project i get the following errors,

39 1021 Hint: interrupt handler (interrupt at 0x0008) RealTimeClock.mpas
160 1010 Hint: Unit "RealTimeClock.mpas" has been recompiled RealTimeClock.mpas
0 134 Compiled Successfully D:\Embedded Development\PIC Code\RealTimeClock\RealTimeClock.mpas
0 139 All files Compiled in 46 ms
39 361 Bad function absolute address 'interrupt[4104]' RealTimeClock.mpas
39 342 There is not enough ROM space interrupt[4104] RealTimeClock.mpas
0 453 Unsuccessful linking 'RealTimeClock.mpppi' Unsuccessful linking 'RealTimeClock.mpppi'
0 102 Finished (with errors): 12 Jan 2015, 19:38:02 RealTimeClock.mpppi

I'm now confused I guess it doesn't work because I have to org statements in my code.

Can anyone shed any light on it please.

Post Reply

Return to “mikroPascal PRO for PIC General”