I got this error using MikroC "Reentrancy not allowed function[Spi_Write] called in both main and interrupt threads". I used PIC16F873 and having the SPI communication at the moment.
Why do I get this problem? How will I solve this? I really have to call some functions inside the interrupt to perform some task.
I got this error using MikroC "Reentrancy not allowed function[Spi_Write] called in both main and interrupt threads". I used PIC16F873 and having the SPI communication at the moment.
Why do I get this problem? How will I solve this? I really have to call some functions inside the interrupt to perform some task.
A Reenterant function is one that can be called when it is already active. In the case of your interrupt routine I think you are getting interrupts while you are still inside your routine. This should not happen because the interrupt should be off while in the interupt service function.
Post the code. Use [code] ... your code here [/code] to keep the code formated.
Think what would happen if an interrupt came along whilst the main code was half way through transmitting a byte. Change your code so that all the SPI stuff is in either the main code or the interrupt. If your unsure how to do this then post your code (put
By the way, will it interrupt the main program? Do I have to put the mov_pot function to a loop so it does the changes as soon as the interrupt is activated?
This is an issue with BoostC as well so perhaps with many microcontroller Cs.
In any case the code in an interrups should be as short as possible. No delays.... State variables as suggested above let you do the slow stuff in the main line.
For the INTCON.RBIF part, everything worked fine. The code reacts exactly as expected everytime PORTS 5,6,and 7 are interrupted.. The problem comes when I try to interrupt the INTCON.INTF. my code doesn't interrupt at all. why is this happening?
take note that when I try to interrupt INTCON.INTF, the PORTA.F1 = 1; is executed but not the case W: statement.
The only reason I can think of for that strange behaviour is that a port B change is happening at the same time as the int0 interrupt and so the code gets executed twice and SWITCH gets set to something else. Note that a pin going from 0 to 1 will also produce a change interrupt.
What happens if you change it to,
Code:
if(INTCON.INTF)
{
SWITCH = W ;
PORTA.F1 = 1;
INTCON.INTF = 0;
[COLOR="Red"]INTCON.RBIE = 0; //turn off port b interrupts
INTCON.RBIF = 0; //and clear it[/COLOR]
}
else if(INTCON.RBIF)
{
if(PORTB.F5 == 0)
The interrupt will get turned back on when the switch W is executed and so the code should still work correctly.
If the changes I suggested made it work then it is the RBIF that is causing the problem. I assume that you only want the relevant code to execute when the pin goes low. The way it is currently written you could (and did) get strange results. To make it edge triggered requires a little more code but may save you some future headaches. Let me know if you want me to post the code.
To stop case W from continually executing you need to set SWITCH to zero in the case W code.
Sure, I would want to know about edge triggering. Ive been seeing those terms in the datasheet but i never really had an idea what it meant. It would be really helpful if you could post the code on how to do it.
By the way, Im new to firmware programming and I've learned a lot from you! Than you very much!!
#define X 1
#define Y 2
#define Z 4 //now powers of 2
#define W 8 //I.E bit values
unsigned short SWITCH = 0;
unsigned char Previous;
void Interrupt()
unsigned char Edges,Pins;
{
if(INTCON.INTF)
{
SWITCH |= W;
PORTA.F1 = 1;
INTCON.INTF = 0;
}
if(INTCON.RBIF)
{
Pins=PORTB; //read the inputs
Pins=~Pins; //invert so active low
Edges=Pins^Previous; //find bits that have changed
Edges&=Pins; //and are now high
Previous=Pins; //keep copy for next time
INTCON.RBIF = 0;
if(Edges.5 == 0)
{
SWITCH |= X; //set X bit
}
if(Edges.6 == 0)
{
SWITCH |= Y;
}
if(Edges.7 == 0)
{
SWITCH |= X;
}
}
}
void main()
{
init_all();
do {
if(SWITCH & X){ //if X bit set then
//X code
SWITCH&=255-X; ///reset X bit
}
if(SWITCH & Y){
//Y code
SWITCH&=255-Y;
}
if(SWITCH & Z){
//Z code
SWITCH&=255-Z;
}
if(SWITCH & W){
//W code
PORTA.F0 = 1;
SWITCH&=255-W;
}
} while(1);
The way it works is by keeping a previous copy of the state of PORTB. By XORing the current and previous states we find any bits that have changed. To find any bits that were previously zero and are now one we AND the bits that have changed with the current state. This is of course the wrong way around as we want to detect bits that went from 1 to 0 and so we simply invert PORTB after we read it.
The other main change needed is because two events may happen at the same time. Because of this we need the ability to tell the main program that this happened and so we set bits in SWITCH instead of a value. These changes wouldn't be required if only 1 event could happen at once.