Problem about Interrupts on portb pin 1 (PIC16F877A)

Discussion in 'Embedded Systems and Microcontrollers' started by lloydi12345, Jan 2, 2011.

  1. lloydi12345

    Thread Starter Member

    Aug 15, 2010
    103
    0
    Hello guys, I'm having problem with my external interrupts using pic16f877a. I can't make the interrupt service routine run. The command "portc.f0 = ~portc.f0;" should be executed when the logic state is changed either from 0 to 1 or 1 to 0 on the pin 1 of PORTB.

    Here's my code:

    Code ( (Unknown Language)):
    1.  
    2. void interrupt(void){
    3.      if (pir1.rbif == 1){
    4.         portc.f0 = ~portc.f0;   //invert the state of output to see an if an interrupt occured
    5.         pir1.rbif = 0;
    6.      }
    7. }
    8.  
    9. void main() {
    10.   ADCON1  = 0x06;
    11.   CMCON = 0x07;
    12.  
    13.   TRISB  = 0xFF;
    14.   TRISC = 0x00;
    15.  
    16.   portc = 0x00;
    17.  
    18.   intcon.rbie = 1;
    19.   intcon.gie = 1;
    20.  
    21.   while(1) {
    22.            delay_ms(1);
    23.   }
    24. }
    I hope you can help me. Thank you.
     
  2. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    Quote from the datasheet:
    You can't have PORTB change interrupt on RB1. It's only available on RB4, RB5, RB6 and RB7.

    Hope this helps.
    Tahmid.
     
  3. lloydi12345

    Thread Starter Member

    Aug 15, 2010
    103
    0
    Thanks for the reply Tahmid but after disconnecting it to pin 1 and connecting it to pin 5, it still doesn't work
     
  4. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    Don't you have to read the port to clear the mismatch condition before clearing the RBIF flag?
     
    lloydi12345 likes this.
  5. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    Exactly. The datasheet states:
    So, you can do two things:
    Code ( (Unknown Language)):
    1. void interrupt(void){
    2.      if (intcon.rbif == 1){
    3.         portc.f0 = portb.f4;   //invert the state of output to see an if an interrupt occured
    4.         intcon.rbif = 0;
    5.      }
    6. }
    7.  
    8. void main() {
    9.   ADCON1  = 0x06;
    10.   CMCON = 0x07;
    11.  
    12.   TRISB  = 0xFF;
    13.   TRISC = 0x00;
    14.  
    15.   portc = 0x00;
    16.  
    17.   intcon.rbie = 1;
    18.   intcon.gie = 1;
    19.  
    20.   while(1) {}
    21. }
    or you could have a dummy read:

    Code ( (Unknown Language)):
    1. unsigned char buffer;
    2.  
    3. void interrupt(void){
    4.      if (intcon.rbif == 1){
    5.         buffer = portb;
    6.         portc.f0 = ~portc.f0;   //invert the state of output to see an if an interrupt occured
    7.         intcon.rbif = 0;
    8.      }
    9. }
    10.  
    11. void main() {
    12.   ADCON1  = 0x06;
    13.   CMCON = 0x07;
    14.  
    15.   TRISB  = 0xFF;
    16.   TRISC = 0x00;
    17.  
    18.   portc = 0x00;
    19.  
    20.   intcon.rbie = 1;
    21.   intcon.gie = 1;
    22.  
    23.   while(1) {}
    24. }
    Hope this helps.
    Tahmid.
     
    lloydi12345 likes this.
  6. lloydi12345

    Thread Starter Member

    Aug 15, 2010
    103
    0
    Thanks for both of your replies :)

    Both of your codes work well Tahmid.

    Last clarification.

    1. What does a mismatch mean on the PIC?

    2. And also, I tried this code:

    Code ( (Unknown Language)):
    1. void interrupt(void){
    2.      if (intcon.rbif == 1){
    3.         portc.f0 = ~portc.f0;   //invert the state of output to see an if an interrupt occured
    4.         intcon.rbif = 0;
    5.      }
    6. }
    7.  
    8.  
    9. void main() {
    10.   ADCON1  = 0x06;
    11.   CMCON = 0x07;
    12.  
    13.   TRISB  = 0xFF;
    14.   TRISC = 0x00;
    15.  
    16.   portc = 0x00;
    17.  
    18.   intcon.rbie = 1;
    19.   intcon.gie = 1;
    20.  
    21.   while(1) {
    22. }
    23. }
    After an interrupt occured, it then changes the state of the LED always from 1 to 0 then to 1 and so on. Is it because it is triggered always?

    3. So it means if I'm using the PORTB as external interrupts, I have to place it first on any variable or even just read it?
    (Sorry I can't clearly understand some terms on the datasheet)

    Edit: I think it has a problem. When I start the simulation from 6v, I reduce the power to 0v the LED doesn't light yet. It only lights when I increase again the voltage above. What I mean is that the interrupt is activated at the second change of state. The interrupt should be activated at the first change of state when the 6v approaches a voltage below the reference voltage.
     
    Last edited: Jan 2, 2011
  7. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    Hi,
    Mismatch is the state of change I guess, I'm not very sure about this. But if the mismatch is not ended, the interrupt keeps on occurring. Your code does not end the mismatch because it does not read the port, so the interrupt keeps on occurring just after the service routine is carried out.

    Hope this helps.
    Tahmid.
     
    lloydi12345 likes this.
  8. lloydi12345

    Thread Starter Member

    Aug 15, 2010
    103
    0
    Thank you Tahmid I got it now.

    Can someone help me on the problem left? It is about the changing state. Starting from 6v when I lower the voltage to 0v (1st change of state), the interrupt is not yet called. The interrupt starts only to execute when I return back the voltage to 6v (2nd change of state) and from that point, any change of state will trigger the interrupt routine.
     
    Last edited: Jan 3, 2011
  9. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    From the bit that mentions "the last read of PORTB" I'd try reading the port and then setting up the interrupt or maybe the other way round.
     
  10. lloydi12345

    Thread Starter Member

    Aug 15, 2010
    103
    0
    Hi Markd77 thanks for replying, the interrupt is already working but it is only activated on the second change of state not in first change of state. Suggestions?
     
  11. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    Spot on.

    Try with this piece of code:
    Code ( (Unknown Language)):
    1. unsigned char buffer;
    2.  
    3. void interrupt(void){
    4.      if (intcon.rbif == 1){
    5.         buffer = portb;
    6.         portc.f0 = ~portc.f0;   //invert the state of output to see an if an interrupt occured
    7.         intcon.rbif = 0;
    8.      }
    9. }
    10.  
    11. void main() {
    12.   ADCON1  = 0x06;
    13.   CMCON = 0x07;
    14.  
    15.   TRISB  = 0xFF;
    16.   TRISC = 0x00;
    17.  
    18.   portc = 0x00;
    19.  
    20.   intcon.rbie = 1;
    21.   intcon.gie = 1;
    22.  
    23.   buffer = portb;
    24.  
    25.   while(1) {}
    26. }
    I hope you understand the difference.

    Hope this helps.
    Tahmid.
     
    lloydi12345 likes this.
  12. lloydi12345

    Thread Starter Member

    Aug 15, 2010
    103
    0
    This is the most exact code :)
    I think I lacked the reading part of portb at first before initializing the interrupts. All I know is just to read portb at the interrupt service routine already. I didn't know it should be twice.

    Thank you alot Tahmid :D
     
  13. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    Not necessarily. PORT should be read before first interrupt occurs, it could be after initializing interrupts as well, as I've shown in the code.

    Hope this helps.
    Tahmid.
     
Loading...