Jump to content

Recommended Posts

Hi,

 

I'm testing the free version of BoostC to teach my students in september som basics. I need to show how interrupts work and have writen a verry small sample program :

 

// Target = 18F4455

#include <system.h>

 

void interrupt(void)

{

intcon&=0b11111110; // clear PortB IF

porta++;

}

 

void main()

{

trisb=255; // set port b to input

trisa=0; // set port a to output

porta=0; // clear port a

 

intcon=0b11001000; // GIE on , PEIE on, RBIE on

 

while (1);

}

 

The interrupt is triggered even without PORTB changes, and the debugger can't get out of the ISR (rejumps directly into a new interrupt request). Altough this little program works.... :huh:

 

 

If I use the linker directive -rb 0x800 (with the ECIO we need a code offset du to bootloader at 0x800) the program resets when the interrupt is called (I assume the interrupt vector is not changed). :(

 

 

 

 

A little hint for the BoostC developpers : it should be nice to use more than one instance of a plugin, e.g. be able to use 4 led-bars at the same time. :rolleyes:

 

 

Any hints are welcome ...

 

 

Mario

elac@online.be

Share this post


Link to post
Share on other sites

Mario,

Any hints are welcome ...

Thought you had found a simulator bug, but looks like this is NOT the case :(

Extract from 18F4455 data sheet:

Four of the PORTB pins (RB7:RB4) have an interrupton-

change feature. Only pins configured as inputs can

cause this interrupt to occur; any RB7:RB4 pin

configured as an output is excluded from the interrupton-

change comparison. The pins are compared with

the old value latched on the last read of PORTB. The

“mismatch” outputs of RB7:RB4 are ORed together to

generate the RB Port Change Interrupt with Flag bit,

RBIF (INTCON<0>).

 

You have to read the port again:

void interrupt(void)
{
intcon&=0b11111110; // clear PortB IF
porta++;
char a = portb; // read port to stop repeated interrupts for same port value
}

 

Regards

Dave

Share this post


Link to post
Share on other sites

Dave,

 

Shoudn't that be:

void interrupt(void)
{
char a = portb; // read port to stop repeated interrupts for same port value
intcon&=0b11111110; // clear PortB IF
porta++;
}

 

I belive you *must* deal with the mismatch before you CAN clear the flag. This is definately the case on PIC16s and IIRC also PIC18s.

... A mismatch condition will continue to set flag bit RBIF. Reading PORTB will end the mismatch condition, and allow flag bit RBIF to be cleared. ...

 

Mario,

 

You will also need to end the mismatch before initially enabing the interrupt:

	char a = portb; // read port to stop repeated interrupts for same port value
intcon=0b11001000; // GIE on , PEIE on, RBIE on

 

 

Also discarding the value in a temp variable in the ISR is seldom what one needs to do as it represents the switches pressed etc.

 

I am far more likely to declare it as a global of type 'volatile unsigned char' (volatile because the ISR will be updating it) so I can see it in the main program as well and also give it a meaningful name.

 

There is a fix for your LED Block plugin issue that *should* be applicable to the free version. I'll need to tidy it up a bit first though. With the availibilty of the FlexiButtons plugin one doesn't need multiples of other type of button.

Share this post


Link to post
Share on other sites
Mario,
Any hints are welcome ...

Thought you had found a simulator bug, but looks like this is NOT the case :(

Extract from 18F4455 data sheet:

Four of the PORTB pins (RB7:RB4) have an interrupton-

change feature. Only pins configured as inputs can

cause this interrupt to occur; any RB7:RB4 pin

configured as an output is excluded from the interrupton-

change comparison. The pins are compared with

the old value latched on the last read of PORTB. The

“mismatch” outputs of RB7:RB4 are ORed together to

generate the RB Port Change Interrupt with Flag bit,

RBIF (INTCON<0>).

 

You have to read the port again:

void interrupt(void)
{
intcon&=0b11111110; // clear PortB IF
porta++;
char a = portb; // read port to stop repeated interrupts for same port value
}

 

Regards

Dave

 

 

Hi Dave,

 

Thank you for you're reply !

 

The datasheets says also :

The user, in the Interrupt Service Routine, can clear the interrupt in the following manner:

a) Any read or write of PORTB (except with the MOVFF (ANY), PORTB instruction). This will end the mismatch condition.

:rolleyes: Clear flag bit, RBIF.

 

I use (generaly proposed to clear an interrupt) the :huh: -way.

 

To make it Work in BoostC the programmer should apply AND a) AND B) in order not to return to the ISR when nothing happens (only clearing the IF works in other IDE's e.g. Wiz-C).

 

 

Tomorrow I'll try the -rb 0x800 directive and download the HEX into an ECIO.

 

I let you know :-)

Share this post


Link to post
Share on other sites

Hi

 

I approve the solution IanM did bring, the final (and for me 'clean') version is :

 

#include <system.h>

 

void interrupt(void)

{

intcon&=0b11111110; // reset IF

porta++;

}

 

void main()

{

char a;

trisb=255;

trisa=0;

porta=0;

 

a=portb; // clear initial mismatch

 

intcon=0b11001000; // enable IR's

 

while (1);

}

 

 

This is working just fine :-)

 

Let's hope the ECIO will do the same IRL ;-) - but that's for tomorrow.

 

I'll give news !

Share this post


Link to post
Share on other sites
Shoudn't that be:
void interrupt(void)
{
char a = portb; // read port to stop repeated interrupts for same port value
intcon&=0b11111110; // clear PortB IF
porta++;
}

 

I belive you *must* deal with the mismatch before you CAN clear the flag. This is definately the case on PIC16s and IIRC also PIC18s.

Yes quite right.

That explains why my code when into the interruot service routine twice for each change of state.

 

For some reason Mario seems set on not reading the port again in his ISR, which does need to be done to resolve the mismatch or the interrupt flag will be set immediately again. So I don't think his code will work.

 

Regards

Dave

Share this post


Link to post
Share on other sites
...

That explains why my code when into the interruot service routine twice for each change of state.

 

For some reason Mario seems set on not reading the port again in his ISR, which does need to be done to resolve the mismatch or the interrupt flag will be set immediately again. So I don't think his code will work.

 

Regards

Dave

 

Glad to have been able to help. Even the masters can use a hint occasionally ;)

 

I suggest Mario tries:

#include <system.h>

volatile unsigned char b; // for PORTB reading
void interrupt(void)
{
  b=portb; // clear mismatch
  intcon&=0b11111110; // reset IF
  porta++;
}

void main()
{
  trisb=255;
  trisa=0;
  porta=0;

  b=portb; // clear initial mismatch
  intcon=0b11001000; // enable IR's

  while (1);
}

 

Mario,

Before teaching this to a class *PLEASE* stop using minimally commented 'magic numbers' even though they are in binary so can be easily referred to the datasheet. (I used to know one coder who worked out bitmaps and masks like this in decimal, which totally obscured what he was doing with 16 bit registers :angry: ).

 

At the very least give the bit numbers in the comment and preferably a datasheet reference, but BoostC has all the bit names #defined in the headers so you can go fully symbolic. Examine PIC18F2455.H in the sourceboost include directory for a full list for that PIC. It makes it much easier to understand and also to port to a different PIC.

 

I *know* you need to teach them to build a bitmask by hand once, but please dont turn out programmers who think obsure code is 'clever' when, with a few small hints on your part, the Compiler's optimisations can build exactly the same binary with easily readable source. Here is the above code without magic numbers except for initialising the Ports and Tris registers.

#include <system.h>

volatile unsigned char b; // for PORTB reading
void interrupt(void)
{
  b=portb; // clear mismatch
  intcon.RBIF=0; // reset IF
  porta++;
}

void main()
{
  trisb=0xFF; //all inputs
  trisa=0; //all outputs
  porta=0;

  b=portb; // clear initial mismatch
  intcon=(1<<GIE | 1<<PEIE | 1<<RBIE); // enable IR's

  while (1);
}

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...