View previous topic :: View next topic |
Author |
Message |
Siquell
Joined: 22 Dec 2017 Posts: 2
|
Main loop hangs after interrupt-on-change in PIC16F1827 |
Posted: Fri Dec 22, 2017 4:40 am |
|
|
Hi all. I'm tring to implement interrupt-on-change in my PIC16F1827 on pin B2. Here is my code:
Code: | #include <main.h>
int8 button = 0;
#int_RB
void RB_isr(void)
{
int current;
static int last=0;
set_tris_b(0x0C);
current=input_b();
if((!bit_test(last,2))&&(bit_test(current,2))) { button++; }
/* If uncomment this, and comment same in main loop, it works
if(button==1) {
button++;
output_high(PIN_A1);
}
if(button==3) {
button = 0;
output_low(PIN_A1);
}*/
last=current;
}
void main()
{
enable_interrupts(INT_RB2);
enable_interrupts(GLOBAL);
set_tris_a(0x0);
set_tris_b(0x0C);
output_high(PIN_A1);
for(;;) {
delay_ms(20);
// code below stops work after interrupt
if(button==1) {
button++;
output_high(PIN_A1);
}
if(button==3) {
button = 0;
output_low(PIN_A1);
}
}
}
|
LED connected to pin A1.
Input voltage is on pin B3.
It seems that any operations in main loop stops after first interrupt. When insert LED blink code in main loop, it works after startup until any change on pin B2. When level on B2 changed, blinking stops. But if I uncomment code in interrupt function, it works (LED toggle after each positive edge). |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Fri Dec 22, 2017 5:20 am |
|
|
What compiler version?.
This is important here, because later compilers have code to do what is needed, while earlier ones require you to go DIY.
Problem is that your chip has individual 'flag' bits for this type of interrupt. There is a master interrupt 'flag', and then a separate IOCBF register for all the bits. This has to be cleared separately:
Code: |
//for a modern compiler
#int_RB NOCLEAR
void RB_isr(void)
{
int1 current;
static int1 last=0;
//set_tris_b(0x0C); //don't fiddle with the IRIS
current=input(PIN_B2); //This is the only pin you are using
if(current==1 && last==0)
button++;
last=current;
clear_interrupt(INT_RB2); //This clears the IOCBF bit for you
}
//For an older compiler
#BYTE IOCBF=getenv("SFR:IOCBF")
#int_RB
void RB_isr(void)
{
int1 current;
static int1 last=0;
//set_tris_b(0x0C); //don't fiddle with the TRIS in the interrupt
current=input(PIN_B2); //This is the only pin you are using
if(current==1 && last==0)
button++;
last=current;
IOCBF=0; //This clears the IOCBF bit for you
}
|
Problem is the actual interrupt flag can't be cleared (is read only!), till the IOCBF bit is cleared, so the extra clear is needed. I declare the handler to 'NOCLEAR' on the modern compiler since the clear instruction does this and it saves an instruction. |
|
|
Siquell
Joined: 22 Dec 2017 Posts: 2
|
|
Posted: Fri Dec 22, 2017 5:44 am |
|
|
Compiler version 4.120.
The trick was in IOCBF bit. Great thanks, now it's working! |
|
|
|