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 CCS Technical Support

interrupt on change Rb4-Rb7 16F877A

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



Joined: 01 Nov 2014
Posts: 2

View user's profile Send private message

interrupt on change Rb4-Rb7 16F877A
PostPosted: Sat Nov 01, 2014 10:12 pm     Reply with quote

Hi, I have the follow situation. Both codes have the same problem. When I push a button, the ISR does not disable the interrupt on change and make more than one action. Any idea why?

first code
Code:

#int_RB
void RB_isr (void) {

   static char i;

// Clear the change condition by reading Port B.
   i = portb;
     
   delay_ms(50);   //antirrebote
   int current;   
   current=input_b();       //lee el puerto         inhabilita la interrupcion
   
   static int last=0;   
   
   //SET_TRIS_B(0x00);    //Configura el puerto B: 0=Salida; 1=Entrada
   //output_b(0x00);      //Limpia el registro del puerto
   // set_tris_b(0xF1);        //      B7 B6 B5 B4 B3 B2 B1 B0
                     //      0  0  0  0  0  1  0  1  =  0x05   ---  1 1 1 1 0 0 0 1 = 0xF1    tambien pone el pin B0 como alta impedacia
   
                     //bit_test lee la posicion
 
   #if   LOWTOHIGH 
   
   if ((!bit_test(last,4))&&(bit_test(current,4)))   //avanzar arriba
   {}
   if ((!bit_test(last,5))&&(bit_test(current,5)))   //tecla abajo
   {}
   if ((!bit_test(last,6))&&(bit_test(current,6)))   //tecla aceptar
   {}
   if ((!bit_test(last,7))&&(bit_test(current,7)))   //tecla atras/cancelar
   {}
   
   #elif  HIGHTOLOW  //deteccion por flanco de bajada
 
   //TECLA ARRIBA //
   
   if ((!bit_test(current,4))&&(bit_test(last,4)))     
   {
   
    }
   
   //TECLA ABAJO //
   
   if ((!bit_test(current,5))&&(bit_test(last,5)))
   {
     
   }
   
   //TECLA ACEPTAR //
   
   if ((!bit_test(current,6))&&(bit_test(last,6)))
   {
     
     }
   
         
   //TECLA CANCELAR/ATRAS //
   
   if ((!bit_test(current,7))&&(bit_test(last,7))) //atras -cancelar
   {   
   
   
    }
   
   
   lcdclear=1;
   
   #endif   
   
   last=current;           // dejo como registro el anterior estado para la comparacion
   //output_b(input_b());      //habilito la interrupcion
   
   




second

Code:

#int_RB 
void Rbinterrup(void){

 static char i;

// Clear the change condition by reading Port B.
   i = portb;
   lcdclear=1;
if(input(PIN_B4)==0)
{
 //TECLA ARRIBA //
   
   
   
}


if(input(PIN_B5)==0)
{
//TECLA ABAJO //
   
   
   
}

if(input(PIN_B6)==0)

{
 //TECLA ACEPTAR//
   
   
   
}


if(input(PIN_B7)==0)
{

 //TECLA CANCELAR/ATRAS //
   
       
     

}
      }



main
Code:

  set_tris_b(0xF1);
      clear_delta();
      clear_interrupt(int_rb); // borro el flag de interrupciĆ³n para que no entre al principio
       
      port_b_pullups(False); // disable
     
      enable_interrupts(int_ext);   
      enable_interrupts(INT_RB); 

      ext_int_edge( H_TO_L );         //inicialmente de 5V a 0V
     
      enable_interrupts(GLOBAL);
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Sun Nov 02, 2014 5:40 am     Reply with quote

The code looks (insert rude word here).....

Delays in the interrupt. Don't.

Basic structure. Poor.

Trying to do more in an interrupt than you should.....

You show two interrupts being enabled, but only one handler. For posting/testing, _simplify_. Have code that is complete, and shows the problem. Yours is not complete (we can't compile it and look what it is doing), and it is impossible to know wat you may be doing wrong in all the other routines in the interrupt.

If this is being used to read something like switches, then 'think again'.

Also use the C standard and declare variables at the start of code sections. C (historically) requires this. CCS 'allows' mid code declarations, but every version I have tried eventually gives odd problems if these are used. So stick to standard coding.

Things like keys and switches _will_ bounce. Multiple triggers will be common.

Get rid on the INT_RB entirely. This should _only_ be used, where you are triggering off stable reliable signals, where you need a fast response. Your delay, says this is not the case.

Instead just have a 'tick' interrupt running at perhaps 50* per second. Have this read the port, and go something like:
Code:

//Your processor header
struct
{
    int1 job1;
    int1 job2;
    int1 job3;
    int1 job4;
} jobs = {FALSE,FALSE,FALSE,FALSE};
#byte direct=jobs
//allow direct access to bit fields
#define ALL_OFF 0xF0 //pattern for all signals high

#int_Timer1//for whatever interrupt you use
void tick(void)
{
    //here every few mSec
    static int8 last_read = ALL_OFF;
    static int8 processed = ALL_OFF;
    int8 read, changed, ctr;;
    int8 mask=0x11;
    read=input_b() & 0xF0; //top four bits of port b.
    //Now situation is that immediate changes are ignored. If the signal has been
    //stable for two calls, and has not been 'processed', then flag the job
    //assuming pins go low when button is pushed.
    if (read!=ALL_OFF)
    {
       //At least one button is pushed
       if (last_read==read)
       {
          //signal has been the same for two calls
          if (processed!=read)
          {
             //and the signal has not been processed
             changed=processed^read;
             //Now changed has bits set for each pin which has not been handled
             swap(changed); //move bits into low nibble
             for (ctr=0;ctr<4;ctr++)
             {
                if (mask & changed)
                {
                   if (mask & read)
                   {
                      //here signal has gone off
                      processed|=(mask&0xF0); //turn off processed bit
                   }
                   else
                   {
                      processed&=(~mask); //turn on processed bit (low)
                      direct|=(mask&0xF); //turn on the job flag to say what to do
                   }
                }
                mask<<=1;
             }
          }
       }
       else
          processed=ALL_OFF;
    }
    last_read=read;
}

void main(void)
{     
      setup_adc(ADC_OFF);
      setup_adc_ports(NO_ANALOGS);
      setup_comparator(NC_NC_NC_NC);
      port_b_pullups(True); // enable to ensure the pins pull-up
     
      setup_timer_1(T1_INTERNAL);
      enable_interrupts(INT_TIMER1); //chose to suit your timer.
      //With a master clock at (say) 16MHz, this would tick at 61* per second.
      //for lower clock rates use timer2 or advance the tick in the interrupt
      enable_interrupts(GLOBAL);
     
      do
      {
         if (jobs.job1)
         {
            //button 1 pressed
            delay_cycles(1);
            jobs.job1=FALSE; //up to you if you want to keep processing
         }
         if (jobs.job2)
         {
            //button 2 pressed
            delay_cycles(1);     
            jobs.job2=FALSE; //up to you if you want to keep processing           
         }
         if (jobs.job3)
         {
            //button 3 pressed
            delay_cycles(1);   
            jobs.job3=FALSE; //up to you if you want to keep processing           
         }
         if (jobs.job4)
         {
            //button 4 pressed
            delay_cycles(1); 
            jobs.job4=FALSE; //up to you if you want to keep processing           
         }       
      } while(TRUE);
}


The key point to understand, is that the interrupt on change, is _not_ suitable for receiving signals with bounce. You can use it to decode buttons, but only if you add signal processing to actually ensure you get clean button signals. It is designed for logic signals that are _clean_.
This has been explained many times here.
There are ways of using it by (for instance) having it enable a timer, and come back in this a few mSec later, and 'double check' that the signal is still good, but if you are going to do this then you might as well just use the timer in the first place.
The code handles each button just _once_ If you want the handler to be repeatedly called so long as the button is pressed, then don't clear the 'job' until you have finished processing it.
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Nov 02, 2014 6:02 am     Reply with quote

First thing I'd do is look at the example that CCS supplies in the FAQ section of the manual !! It's been in there since v2.5xx.


jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Sun Nov 02, 2014 7:49 am     Reply with quote

However 'beware', that is for polling a button, not anything interrupt driven....
walxar



Joined: 01 Nov 2014
Posts: 2

View user's profile Send private message

PostPosted: Sun Nov 02, 2014 8:16 am     Reply with quote

Ttelmah wrote:
The code looks (insert rude word here).....

Delays in the interrupt. Don't.
Ok, my bad

Thanks for the reply , I deleted the code, use flags and masks , but I saw no need to put all code

this answer is fine for me,

It is designed for logic signals that are _clean_.
This has been explained many times here.


I assumed that the signals were clean in ISIS. Polling is the right answer for my purpose .
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Nov 02, 2014 8:23 am     Reply with quote

OK..NOW we know this isn't a real PIC in the real world, rather a silly ISIS 'simulation'

1) please read PIC101 on the top of the heap here

2) get a PIC, breadboard and other components.

3) come back when you get a 1Hz LED program to run THEN we can help you.

You will NEVER, ever be able to 'simulate' a PIC in ISIS properly.
ISIS is full of bugs, errors, faulty DRCs...bottom line, 'it's busted',

All the 'regulars' here know this and most will not reply to queries posted with ISIS or Proteus. The fact is this is a CCS C compiler forum and no one here cares to spend anytime trying to rewrite ISIS.

Yes, we 'deviate' a bit to help with hardware issues(EMI, glitches, etc.) as well as oddball drivers for weird chips or recoding another compiler to CCS.

jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Sun Nov 02, 2014 9:40 am     Reply with quote

and (of course), if you 'assume they are clean', when you try to move to the real world, you will have to write the code _again_ to cope with real events. This is why unless you are already experienced, Isis can actually waste time, rather than saving it.....
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Sun Nov 02, 2014 11:20 am     Reply with quote

I can't help but add:
Quote:

unless you are already experienced

And those who ARE experienced wouldn't
fool with Proteus / Isis under any conditions !!
That ought to be food for thought.
Very Happy Very Happy Very Happy Very Happy Very Happy
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