CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

INT_RB problem 16f1827

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
zotymo



Joined: 12 Dec 2011
Posts: 5

View user's profile Send private message

INT_RB problem 16f1827
PostPosted: Mon Dec 12, 2011 4:30 pm     Reply with quote

What can I do to make the program leave the interrupt routine, because
once it enters the routine it keeps repeating itself.

My code:

Code:

#define  ALARM_LED      PIN_A2   //EXT_LED
#define  PIEZO         PIN_A1   //BUZZER_OUT

#include <16F1827.h>
#include <e:\_includes\stdlib.h>

#fuses INTRC_IO,PUT,/*NOWDT,NOPROTECT,*/NOLVP,PLL_SW

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT_SW                   //No Watch Dog Timer, enabled in Software

#FUSES PROTECT                  //Code protected from reads
#FUSES CPD                      //Data EEPROM Code Protected

#use delay(int=1000000)

#use fast_io(B)

int1 battery_alarm_flg=0;


#INT_RB
void rb_isr()
{
int c;

disable_interrupts(INT_RB);

c=input_b();

battery_alarm_flg=1;

clear_interrupt(INT_RB);

}


void main() {

//-------------------------------------------------------------
SET_TRIS_A(0x11);   // A7,A6,A5,A3,A2,A1 are outputs 00010001
               // A0,A4 are inputs

SET_TRIS_B(0xF3);   // B3,B2 are outputs 11110011
               // B0,B1,B4,B5,B6,B7 are inputs
//-------------------------------------------------------------

//-------------------------------------------------------------
port_B_pullups(0xF0); //11110000
clear_interrupt(INT_RB);    
enable_interrupts(INT_RB);
//-------------------------------------------------------------
enable_interrupts(GLOBAL);
//-----------------------------------

while(1)
      {

      if(battery_alarm_flg)
                     {
                     output_high(ALARM_LED);
                     output_high(PIEZO);
                     delay_ms(1000);
                     output_low(ALARM_LED);
                     output_low(PIEZO);
                     delay_ms(1000);
                  
                     battery_alarm_flg=0;

                     clear_interrupt(INT_RB);
                     enable_interrupts(INT_RB);
                     }
      }
}


Please help me!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Dec 12, 2011 5:47 pm     Reply with quote

Always post your compiler version.
zotymo



Joined: 12 Dec 2011
Posts: 5

View user's profile Send private message

PostPosted: Mon Dec 12, 2011 5:49 pm     Reply with quote

Sorry.

4.124
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Tue Dec 13, 2011 3:20 am     Reply with quote

At the end of the INT_RB routine, you don't need to clear the interrupt. The compiler does this for you, unless you use the 'NOCLEAR' option on the interrupt.

Two distinct problems though.

First key thing is that you cannot clear the interrupt, if the latch inside the chip does not match what is on the pins port. Hence anywhere you clear the interrupt (at the start after setting the pullups, and at the end of the loop before you re-enable the interrupt), you must read the port first.
Remember that INT_RB triggers on both edges from a signal. I'm guessing your signal is some for of pulse?. If so, then the interrupt will trigger, and call the handler, on the first edge of the signal. Then the interrupt is disabled, and you leave the handler. In the main code you then pause for a couple of seconds while you sound your buzzer, and flash the LED. If at any point in this couple of seconds, there is another change to the port B pins, the interrupt will be set (but no handler called since the interrupt is disabled). After the couple of seconds, you then clear the interrupt - which will immediately set itself again, because you haven't read the port. So when you then enable the interrupt the code will loop a second time.....

Now, you don't say what pin the signal is actually on, or what else is connected to PORTB. You do understand that as you have it programmed _every_ input pin on PORTB _will_ trigger the interrupt. So B0,1,4,5,6 & 7 will all trigger the event if they change in level. If any are floating they will trigger at times. Do you really want the interrupt triggers by six sources?. This is the 'point' of the more complex setting when enabling the interrupt.
For example:

ENABLE_INTERRUPTS(INT_RB4_H2L);

Will set INT_RB to only trigger when pin B4 goes low.

So what pin is the signal on, and which direction will it change when you want to trigger the event?.

Best Wishes
zotymo



Joined: 12 Dec 2011
Posts: 5

View user's profile Send private message

PostPosted: Tue Dec 13, 2011 12:51 pm     Reply with quote

Thank you for your advice. I change the code, but the problem stay. I check it by debugger. The program run in the main loop until the first interrupt on RB4. After that never go out from the interrupt routine. The LED never flash.
:(

Code:

#define  ALARM_LED      PIN_A2   //EXT_LED
#define  PIEZO         PIN_A1   //BUZZER_OUT

#include <16F1827.h>

#fuses INTRC_IO,PUT,/*NOWDT,NOPROTECT,*/NOLVP,PLL_SW

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT_SW                   //No Watch Dog Timer, enabled in Software

#FUSES PROTECT                  //Code protected from reads
#FUSES CPD                      //Data EEPROM Code Protected

#use delay(int=1000000)

#use fast_io(B)

int1 battery_alarm_flg=0;


#INT_RB
void rb_isr()
{
int c;

//disable_interrupts(INT_RB);

c=input_b();

battery_alarm_flg=1;

//clear_interrupt(INT_RB);

}


void main() {

//-------------------------------------------------------------
SET_TRIS_A(0x11);   // A7,A6,A5,A3,A2,A1 are outputs 00010001
               // A0,A4 are inputs

SET_TRIS_B(0xF3);   // B3,B2 are outputs 11110011
               // B0,B1,B4,B5,B6,B7 are inputs
//-------------------------------------------------------------

//-------------------------------------------------------------
port_B_pullups(0x10); //00010000
//clear_interrupt(INT_RB);   
//enable_interrupts(INT_RB);
enable_interrupts(INT_RB4_H2L);
//-------------------------------------------------------------
enable_interrupts(GLOBAL);
//-----------------------------------

while(1)
      {

      if(battery_alarm_flg)
                     {
                     output_high(ALARM_LED);
                     output_high(PIEZO);
                     delay_ms(1000);
                     output_low(ALARM_LED);
                     output_low(PIEZO);
                     delay_ms(1000);
                 
                     battery_alarm_flg=0;

//                    clear_interrupt(INT_RB);
//                   enable_interrupts(INT_RB);
                     }
      }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Dec 13, 2011 1:11 pm     Reply with quote

Quote:
Once it enters the routine it keeps repeating itself.

You have to clear bit 4 in the IOCBF register, at the end of the #int_rb
routine. This clears the condition that is causing repeated interrupts.
Add the lines shown in bold below:

Quote:

#byte IOCBF = getenv("SFR:IOCBF")
#bit IOCBF4 = IOCBF.4
#define clear_IOCBF4() IOCBF4 = 0



#INT_RB
void rb_isr()
{
battery_alarm_flg=1;

clear_IOCBF4();
}
zotymo



Joined: 12 Dec 2011
Posts: 5

View user's profile Send private message

PostPosted: Tue Dec 13, 2011 1:41 pm     Reply with quote

It works! Smile Thank you. But I have an another problem. I would like to set the configuration bits in code, like #FUSES PROTECT, #FUSES CPD, #FUSES WDT_SW but not works. Only I can do this settings with MPLAB IDE. :(

Compiler version: 4.124
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Dec 13, 2011 1:55 pm     Reply with quote

Don't compile with the "Build Configuration" in MPLAB set to "DEBUG".
The PROTECT, WDT, BROWNOUT, and maybe some other fuses are
automatically disabled for Debug mode.

You can set the Build Configuration in the Drop-Down box at the top of
the main MPLAB window. If this box is "grayed out", then do this:
Shut down MPLAB. Install the latest CCS "plug-in" for MPLAB, and
re-start MPLAB. You should now be able to select Release or Debug.
http://www.ccsinfo.com/downloads/setup_mplab_plugin.exe

MPLAB defaults to a build configuration of DEBUG. To change this
behavior so it defaults to RELEASE mode, see the instruction in this post:
http://www.ccsinfo.com/forum/viewtopic.php?t=46818&start=21
zotymo



Joined: 12 Dec 2011
Posts: 5

View user's profile Send private message

PostPosted: Tue Dec 13, 2011 2:07 pm     Reply with quote

You solved my problems. Thank you again.
doguhanpala



Joined: 05 Oct 2016
Posts: 120

View user's profile Send private message

PostPosted: Fri Oct 21, 2016 5:38 am     Reply with quote

Ttelmah wrote:

Now, you don't say what pin the signal is actually on, or what else is connected to PORTB. You do understand that as you have it programmed _every_ input pin on PORTB _will_ trigger the interrupt. So B0,1,4,5,6 & 7 will all trigger the event if they change in level. If any are floating they will trigger at times. Do you really want the interrupt triggers by six sources?. This is the 'point' of the more complex setting when enabling the interrupt.
For example:

ENABLE_INTERRUPTS(INT_RB4_H2L);

Will set INT_RB to only trigger when pin B4 goes low.

So what pin is the signal on, and which direction will it change when you want to trigger the event?.

Best Wishes


I have a few questions. I want to increase counter value each time on int_rb interrupt, but i want to do it from just RB4.

As i understand, ENABLE_INTERRUPTS(INT_RB4_H2L) line, does this work for me ? If i want to use just RB5, i change the code as ENABLE_INTERRUPTS(INT_RB5_H2L) ?

If i want to use both pins i have to write ENABLE_INTERRUPTS(INT_RB4_H2L | INT_RB5_H2L)

Are these 2 assumptions correct?

I did some research and found some sources that say the pic can not understand which pin changed.
http://www.just.edu.jo/~amjaradat/_ee445/_doc/interrupt-rb4-7.pdf
also another source says that.
https://www.ccsinfo.com/faq.php?page=int_ext_button (same but without example).

So i could not understand which is correct. Is it possible or not possible? And if possible, how? My compiler doesn't accept the line: ENABLE_INTERRUPTS(INT_RB4_H2L)

I thought it is because of 18f2550 but it accepts int_rb line and works properly. I read the datasheet and it says there is int_rb for 18f2550.

Another possibility is that Ttelmah and sources say the same thing but i misunderstood what Ttelmah said. Can anyone explain please?

Note: I use 18f2550.

Best wishes

Doğuhan
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Fri Oct 21, 2016 7:08 am     Reply with quote

Key is different chips....

The original PIC INT_RB, had no ability to know 'which' pin triggers the interrupt. This is normally only on RB4 to RB7. It also worked on every change (both high to low, and low to high), on all the pins enabled as inputs. This is the INT_RB on the 2550/4550, and probably 90% of PIC's.

Some later chips have an 'improved' INT_RB (and often an INT_RA as well). On these there is a separate mask to say which pins are to be included, and often a mask to specify which edge(s) are used. These chips also have a separate latch register, to say which pin has triggered. These then offer the ability to set these masks with the INT_RB4_H2L type syntax.

On the standard chips. Only INT_RB. No edges or bits.
On the 'improved RB' chips. Settings like INT_RB4, and INT_RB4_H2L.

On these later chips you also have to clear the latch yourself. This is the IOCBF register that PCM_programmer is pointing to. It's left 'uncleared', since it then allows your INT_RB code to check which bit has caused the interrupt.
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Sat Oct 22, 2016 7:39 pm     Reply with quote

I am using port B interrupt in two ways:

* Using RB4 as input for the interrupt and RB5,6,7 as outputs so I know the interrupt is from RB4
* Using more than one RB for interrupt, for example RB4 & RB5 and testing the changes of the pins in the isr

For both cases if I want just interrupt H to L (or L to H) ignoring the other case

Best wishes
Joe
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Sun Oct 23, 2016 12:41 am     Reply with quote

If your PIC only has INT_RB, you can't. INT_RB, is an interrupt on change. It'll trigger on _every_ change. (High to low, and low to high). You will just have to add a test in the routine for the edge.

So on a PIC like a 4550, just using INT_RB
Code:

void INT_RB(void)
{
   static int1 old_RB4=1;
   static int1 old_RB5=1;
   //Assuming lines are pulled up, so idle high.
   if (input(PIN_B4)==1)
   {
       //input is high
       if (old_RB4==0)
       {
           //low to high
           old_RB4=1;
           //do nothing except record the level
       }
   }
   else
   {
       //input is low
       if (old_RB4==1)
       {
           //here signal has changed high to low
           old_RB4=0;
           //your code here for RB4 having dropped

       }
   }
   //Now the same for B5
   if (input(PIN_B5)==1)
   {
       //input is high
       if (old_RB5==0)
       {
           //low to high
           old_RB5=1;
           //do nothing except record the level
       }
   }
   else
   {
       //input is low
       if (old_RB5==1)
       {
           //here signal has changed high to low
           old_RB5=0;
           //your code here for RB5 having dropped

       }
   }
}


This is only a handful of machine instructions.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group