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

Problem with INT_EXT (PIC16F877A)

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



Joined: 04 Feb 2011
Posts: 9

View user's profile Send private message

Problem with INT_EXT (PIC16F877A)
PostPosted: Fri Feb 04, 2011 8:14 am     Reply with quote

Hi all,
First I'm french so excuse me if I make faults in my explanation. So, I'm making a program and I use the interrupt of PB0 to increment a counter when I press a button. In function of this number, the program select the output and I want to view a message of a LCD display. I use too RB4 and RB5 with the interrupt "portB change". I have two other buttons, and when I press it I want to increment or decrement a counter and select a output. I make this code:
Code:

#include <16F877A.h>
#device ICD=TRUE
#device adc=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES DEBUG                    //Debug mode for use with ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected

#use delay(clock=12000000)

#include <LCD.C>

#byte PORTA=5
#byte TRISA=0x85
#bit C1=PORTA.1
#bit C2=PORTA.2
#bit C3=PORTA.3
#bit C4=PORTA.4
#bit C5=PORTA.5

#byte PORTB=6
#byte TRISB=0x86
#bit up=PORTB.5
#bit down=PORTB.4

#byte PORTC=7
#byte TRISC=0x87
#bit C6=PORTC.0
#bit C7=PORTC.1
#bit C8=PORTC.3
#bit C9=PORTC.4
#bit C10=PORTC.5
#bit C11=PORTC.6
#bit C12=PORTC.7

#byte PORTE=9
#byte TRISE=0x89
#bit signal1=PORTE.0
#bit signal2=PORTE.1


int compteur_gamme=0;
int compteur_signal=0;

#int_RB // RB4 to RB7
RB_isr()
{
   disable_interrupts(INT_EXT);
   disable_interrupts(INT_RB);

   if(up==0) // RB5
   {
     compteur_gamme++;
     if(compteur_gamme==12)
         compteur_gamme=0;

     switch (compteur_gamme)
     {
         case 0:
            TRISC=0b01111111;
            TRISA=0b11111111;
            C12=0;
         break;

         case 1:
            TRISC=0b10111111;
            TRISA=0b11111111;
            C11=0;
         break;

         case 2:
            TRISC=0b11011111;
            TRISA=0b11111111;
            C10=0;
         break;

         case 3:
            TRISC=0b11101111;
            TRISA=0b11111111;
            C9=0;
         break;

         case 4:
            TRISC=0b11110111;
            TRISA=0b11111111;
            C8=0;
         break;

         case 5:
            TRISC=0b11111101;
            TRISA=0b11111111;
            C7=0;
         break;

         case 6:
            TRISC=0b11111110;
            TRISA=0b11111111;
            C6=0;
         break;

         case 7:
            TRISC=0b11111111;
            TRISA=0b11011111;
            C5=0;
         break;

         case 8:
            TRISC=0b11111111;
            TRISA=0b11101111;
            C4=0;
         break;

         case 9:
            TRISC=0b11111111;
            TRISA=0b11110111;
            C3=0;
         break;

         case 10:
            TRISC=0b11111111;
            TRISA=0b11111011;
            C2=0;
         break;

         case 11:
            TRISC=0b11111111;
            TRISA=0b11111101;
            C1=0;
         break;
     }

   }

   if(down==0) // RB4
     {
     compteur_gamme--;
     if(compteur_gamme==-1)
      compteur_gamme=11;

     switch (compteur_gamme)
     {
         case 0:
            TRISC=0b01111111;
            TRISA=0b11111111;
            C12=0;
         break;

         case 1:
            TRISC=0b10111111;
            TRISA=0b11111111;
            C11=0;
         break;

         case 2:
            TRISC=0b11011111;
            TRISA=0b11111111;
            C10=0;
         break;

         case 3:
            TRISC=0b11101111;
            TRISA=0b11111111;
            C9=0;
         break;

         case 4:
            TRISC=0b11110111;
            TRISA=0b11111111;
            C8=0;
         break;

         case 5:
            TRISC=0b11111101;
            TRISA=0b11111111;
            C7=0;
         break;

         case 6:
            TRISC=0b11111110;
            TRISA=0b11111111;
            C6=0;
         break;

         case 7:
            TRISC=0b11111111;
            TRISA=0b11011111;
            C5=0;
         break;

         case 8:
            TRISC=0b11111111;
            TRISA=0b11101111;
            C4=0;
         break;

         case 9:
            TRISC=0b11111111;
            TRISA=0b11110111;
            C3=0;
         break;

         case 10:
            TRISC=0b11111111;
            TRISA=0b11111011;
            C2=0;
         break;

         case 11:
            TRISC=0b11111111;
            TRISA=0b11111101;
            C1=0;
         break;
     }
   }
   enable_interrupts(INT_EXT);
   enable_interrupts(INT_RB);
}

#int_EXT
EXT_isr() // RB0

   disable_interrupts(INT_EXT);
   disable_interrupts(INT_RB);
      compteur_signal++;
      if(compteur_signal==3)
        {
         compteur_signal=0;
        }

      switch (compteur_signal)
      {
      case 0: // triangle
         signal1=0;
         signal2=1;
         lcd_gotoxy(1,2);
         printf(lcd_putc, "Triangle    ");
         break;

      case 1: // sinus
         signal1=1;
         signal2=1;
         lcd_gotoxy(1,2);
         printf(lcd_putc, "Sinus      ");
         break;

      case 2: // carrĂ©
         signal1=0;
         signal2=0;
         lcd_gotoxy(1,2);
         printf(lcd_putc, "Carre      ");
         break;
   }
  enable_interrupts(INT_EXT);
  enable_interrupts(INT_RB);
}


#int_TIMER1 // debordement toute les 13.1ms
TIMER1_isr()
{
   debordement=debordement++;

}


void main()
{
   
   
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);   // externe ou interne ????
   setup_timer_2(T2_DIV_BY_1,0,1);
   setup_ccp1(CCP_CAPTURE_RE);
   setup_ccp2(CCP_CAPTURE_RE);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   lcd_init();

   enable_interrupts(INT_EXT);
   enable_interrupts(INT_RB);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);

   TRISB=0b11111111;
   
   do
   {
   lcd_gotoxy(1,1);
   printf(lcd_putc, "Frequence");
   }
   while(1);
}

But when I try the program doesn't work !!! I have just the message "frequence" on my LCD.
Thanks a lot
Jeremy
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Fri Feb 04, 2011 10:40 am     Reply with quote

Hi,

This is what I understand:

1) you write to LCD on your main function inside a infinite loop.

2) you write new messages to the LCD inside your ISR. (you should only set flags inside the ISR as to get in and out fast).

3) when you press a button, your ISR fires.

4) ISR writes the new message to the LCD.

5) but as soon as you exit the ISR, your main function REwrites frequence to the LCD.... (this is your problem)


other things:

Also be advise that "interrupt on change" fires 2 times in a button press.
Once when you press the button and once you release the button... this happens because the pin changes twice: from high to low and from low to high. Also since you are using mechanical buttons you need to establish some form of debounce or you will get unpredictable results from a button press.

Furthermore it seems that what you are trying to do with TRIS is just to change the state the whole port, in other words output a byte to port of. There are specific functions for this.


hope that helps


Gabriel
_________________
CCS PCM 5.078 & CCS PCH 5.093
dubinc



Joined: 04 Feb 2011
Posts: 9

View user's profile Send private message

PostPosted: Fri Feb 04, 2011 11:17 am     Reply with quote

Thanks for your answer. I write to LCD with a infinite loop just to see if the program works. I try to remove the infinite loop and I insert a delay of 500ms after the message send to LCD in the ISR but it doesn't work.
I made several tests and sometimes (about 1 on 50) it works, but when I switch off/on the power, after it doesn't work anymore. I think it doesn't go in my interrupt and I don't know why.
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Fri Feb 04, 2011 12:54 pm     Reply with quote

Like I said, keep your ISR as short as possible.
only set flags inside your ISR. your taking too long inside your ISR.
Delays inside an IRS are a big NO-NO.

You need to compensate for the fact that you will fire the RB int twice.

Inside your ISR you should only have a small debounce loop that checks the state of the pin that triggered the input... if the state is the same for ~4 consecutive reads, the button is debounced...then increment a counter... when you release the button you pressed, the ISR will fire again... increments the counter which now has a value of 2 (ISR triggered twice) and when counter is 2, set a flag and reset counter.

In your main code the only infinite loop is one that checks the ISR flag...
when flag is set... it executes the desired command (out of the ISR).



G
_________________
CCS PCM 5.078 & CCS PCH 5.093
dubinc



Joined: 04 Feb 2011
Posts: 9

View user's profile Send private message

PostPosted: Sat Feb 05, 2011 5:13 am     Reply with quote

Ok I understand, but I'm not a very good programmer and I never use flag. Can you explain me quickly how I can use a flag.
Ttelmah



Joined: 11 Mar 2010
Posts: 19369

View user's profile Send private message

PostPosted: Sat Feb 05, 2011 6:13 am     Reply with quote

Adding an other other thing. You don't have to disable interrupts in the handler. The chip's _hardware_ does this for you...

Now on interrupts:
Code:

int8 seen_bits,old_bits,changed_bits;
int1 port_changed=FALSE;

#INT_RB
void changed_handler(void) {
    seen_bits=input_b();
    changed_bits=old_bits~seen_bits;
    old_bits=seen_bits;
    port_changed=TRUE;
}

//Then in main
    if(port_changed) {
       //coming here implies portB has changed
       port_changed=FALSE;
       Here look at the bits in 'changed_bits' to see what has changed
       and then the bits in 'old_bits' to see which way the change was

    }



Best Wishes
dubinc



Joined: 04 Feb 2011
Posts: 9

View user's profile Send private message

PostPosted: Sat Feb 05, 2011 12:30 pm     Reply with quote

I understand the method but I have yet two questions:
-What is doing this line ?
changed_bits=old_bits~seen_bits;
more when I compile I have have a mistake with the "~"

- you say: "Here look at the bits in 'changed_bits' to see what has changed and then the bits in 'old_bits' to see which way the change was" but how ?? Just in reading the byte ??
Ttelmah



Joined: 11 Mar 2010
Posts: 19369

View user's profile Send private message

PostPosted: Sat Feb 05, 2011 4:05 pm     Reply with quote

'^', is the 'XOR' operator in C. It returns '1' for each bit that is _different_ in two binary values. It is really what the interrupt on change does internally, so allows you to find which bit has changed to trigger the interrupt.
Am typing from a Mac, and for some reason the posting showed '~' which is the 'ones complement' operator (inverts each bit).
Done this through the PC simulator, so should be right this time.....

Best Wishes
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