void interrupt() not working

General discussion on mikroC.
Post Reply
Author
Message
ascomm
Posts: 129
Joined: 30 Mar 2005 18:28
Location: Finland

void interrupt() not working

#1 Post by ascomm » 09 Jul 2005 09:12

Code: Select all

/*   Fillarimittari
     Polkupyörän matka- / matka-aikamittari
      - PIC16F876 @ 8MHz
      - 2x16 LCD näyttö

*/

unsigned static CIRC = 2060;          // Renkaan ympärysmitta (mm)

void alustus()
{

  Lcd_Init(&PORTB);
  Lcd_Cmd(Lcd_CLEAR);
  Lcd_Cmd(Lcd_CURSOR_OFF);
  Lcd_Out(1, 1, "-Fillarimittari-");
  INTCON.INTE = 1;                   // Enable INTE (RB0 external interrupt)
  TRISB  = 0b00000001;               // RB0 is input
  Delay_ms(2000);
}

void interrupt(){
  INTCON.INTF = 0;                    // clear INTF
  INTCON.INTE = 0;                    // disable external interrupts
  Lcd_Out(1, 1, "23,6  19,4  56,8");
  Lcd_Out(2, 1, "10:34      13:42");
  INTCON.INTE = 1;                    // Enable INTE
}

void main(void)
{
  alustus();

  asm
  {
    SLEEP
  }
}

And this is what I get:

lstr1__1: not found.
Bank not found: lstr1__1
lstr1__2: not found.
Bank not found: lstr1__2
lstr1__3: not found.
Bank not found: lstr1__3
and so on...

What can be wrong?

Storic
Posts: 393
Joined: 01 Oct 2004 00:20
Location: Australia (S.A.)

#2 Post by Storic » 09 Jul 2005 10:22

I dont know,

try moving your call for Lcd_Out() outside of the interrupt.

I was always under the impression not to run any librarys within the interrupt. :?

Andrew

pizon
mikroElektronika team
Posts: 823
Joined: 11 Oct 2004 08:53

#3 Post by pizon » 09 Jul 2005 21:43

Looks like some kind of bug about the temporary string usage in the interrupt() routine. We will check this on Monday, in the meantime try using pointers, like this:

Code: Select all

/*   Fillarimittari
     Polkupyörän matka- / matka-aikamittari
      - PIC16F876 @ 8MHz
      - 2x16 LCD näyttö

*/

unsigned static CIRC = 2060;          // Renkaan ympärysmitta (mm)
char *pstr1;

void alustus()
{

  Lcd_Init(&PORTB);
  Lcd_Cmd(Lcd_CLEAR);
  Lcd_Cmd(Lcd_CURSOR_OFF);
  Lcd_Out(1, 1, "-Fillarimittari-");
  INTCON.INTE = 1;                   // Enable INTE (RB0 external interrupt)
  TRISB  = 0b00000001;               // RB0 is input
  Delay_ms(2000);
}

void interrupt(){
  INTCON.INTF = 0;                    // clear INTF
  INTCON.INTE = 0;                    // disable external interrupts
  Lcd_Out(1, 1, pstr1);
  Lcd_Out(2, 1, pstr2);
  INTCON.INTE = 1;                    // Enable INTE
}

void main(void)
{
  pstr1 = "23,6  19,4  56,8";
  pstr2 = "10:34      13:42";
  alustus();

  asm
  {
    SLEEP
  }
}
I do have a couple of remarks, though:
  • 1. Function calls from within the interrupt are a tricky business; you cannot do this in a straightforward way like you did. Please take a look at "interrupt" topic in mikroC help; you can see a code example of this in the "rs485" example.

    2. All functions that work with LCD are slow, and Lcd_Out() is the slowest of them all. It is highly unrecommended to use such functions in the interrupt routine. Interrupt routine has to be as fast and small as possible, otherwise you'll be missing lots of interrupt events. Generally, in these cases, you should set a flag (or flags) in interrupt() routine when it happens, then process the case somewhere outisde the interrupt (turning off the interrupt during processing whenever possible).
pizon

ascomm
Posts: 129
Joined: 30 Mar 2005 18:28
Location: Finland

#4 Post by ascomm » 10 Jul 2005 09:08

pizon wrote:Interrupt routine has to be as fast and small as possible, otherwise you'll be missing lots of interrupt events.
In this case it doesn't matter if the interrupt function is slow. This project is bicycle speed meter / odometer and these external (RB0) interrupts occures once in every round of front wheel.
I.e. at 80km/h (which should be enough ;) ) with 26" wheels the interrupt rate would be about 10,7 times per second. So we have at least 93ms to process every interrupt.

pizon
mikroElektronika team
Posts: 823
Joined: 11 Oct 2004 08:53

#5 Post by pizon » 11 Jul 2005 09:26

We did a check on this issue; it is definitely a bug, so you cannot work directly with temporary strings in the interrupt() function. The workaround I mentioned should 'do the trick' for now.
pizon

sonic
Posts: 55
Joined: 18 Apr 2005 14:10
Location: NS

#6 Post by sonic » 12 Jul 2005 11:48

I have noticed that if you are using LCD on PORTB or some other PORT,..
you can expect some kind of strange behavior on pins that are not connected on LCD.

In your situation RB0, RB1 and RB2 are STRANGE BEHAVIOR PINS!
Every time u call the LCD routine, it may cause change on RB0 so MCU don`t know then what is INTERRUPT exactly!

My advice is to use the LCD_Config to configure your LCD pins on PORTB,
but better way is to put LCD on PORTA or PORTC and then u can freely use PORTB0 as an interrupt pin :wink:

Thanx

ascomm
Posts: 129
Joined: 30 Mar 2005 18:28
Location: Finland

#7 Post by ascomm » 12 Jul 2005 20:52

Actually, I was wondering if I need interrupts at all. This could be done, I think, by means of an infinitive loop which monitors the state of one pin (with Button function) and calls necessary functions every time when that pin goes up (or down).
Any comments for this idea...?

sonic
Posts: 55
Joined: 18 Apr 2005 14:10
Location: NS

#8 Post by sonic » 13 Jul 2005 06:08

Sure...!
You don`t need to use button as well.., just monitor the state of the pin.
Interrupt is one of the solution, but too complicated for that simple job.

pizon
mikroElektronika team
Posts: 823
Joined: 11 Oct 2004 08:53

#9 Post by pizon » 13 Jul 2005 08:34

ascomm wrote:Actually, I was wondering if I need interrupts at all. This could be done, I think, by means of an infinitive loop which monitors the state of one pin (with Button function) and calls necessary functions every time when that pin goes up (or down).
Any comments for this idea...?
By all means; this is called 'polling' and is the ancestor of the Real Time OS. It is still widely used (and will continue to do so), due to its simplicity and applicability on the smaller (8-bit) systems. It is just what you said: the main() rouitne has an infinite loop that performs cyclically all the required tasks. An additional 'enhancement' on the polling loop is also widely used, and that is connecting it to the Watchdog timer. In other words, WDT is updated between the successive tasks, so that a single task has a limited amount of time to finish its job, and the application cannot get stuck (if it does, WDT interrupt will reset the machine). This way you can obtain a 'near-real-time' behaviour of your system.
pizon

Post Reply

Return to “mikroC General”