Jump to content
Sign in to follow this  
Yuki

16F877 interrupt ?

Recommended Posts

Hi,

 

I wrote some code to check 16F877 interrupts.

In this code below, LEDs are connected to all portb and #2 of

portd.

 

When I run this code, LED (portb,4) switching on and off but

LED (portb,3:timer1) stays OFF. LED (portd,2) in the main loop keeps ON.

Are there anythig wrong with my code ?

 

Thsnks for your help in advance.

 

 

#include

 

 

char rcvdata;

 

/*20MHz*/

#pragma CLOCK_FREQ 20000000

 

/********************************************/

/* interrupt routine                        */

/********************************************/

void interrupt(void)

{

 clear_bit(intcon,GIE);

 

 // RS interrupt

 if( (pir1 & RCIF) != 0){ // receive

   if ( (rcsta & 00000110) == 0){  // no error

     set_bit(portb,0);

     rcvdata=rcreg;

     set_bit(rcsta,CREN);

   } else {                        // error !

     clear_bit(rcsta,CREN);

     set_bit(rcsta,CREN);

   }

 } else {

   nop();  

 

 }

 // Timer2 interrupt

 if ( (pir2 & TMR2IF) != 0){

   clear_bit(pir2,TMR2IF);

   set_bit(portb,1);

 }

 // timer0 interrupt

 if( (intcon & T0IF) != 0 ){

   clear_bit(intcon,T0IF);

   tmr0=0;

   set_bit(portb,2);

 }

 // Timer1 interrupt

 if ( (pir1 & TMR1IF) != 0){

   set_bit(portb,3);

   clear_bit(pir1,TMR1IF);

 }

 // RB0 interrrupt

 if( (intcon & INTF) != 0){

   set_bit(portb,4);

   clear_bit(intcon,INTF);

 }

 // RBs change interrupt

 if( (intcon & RBIF) != 0){

   set_bit(portb,5);

   clear_bit(intcon,RBIF);

 }

 

 delay_ms(100);

 portb=0;   // all LEDs off

 delay_ms(100);

 

 set_bit(intcon,GIE);

 

 

 

 return;

}

 

 

/********************************************/

/* main */

/********************************************/

main()

{

 

 

 /*****IO port direction *****/

trisa = 001111b;

trisb = 00000000b;   // all outputs connected to LED (high->ON, low -> OFF)

trisc = 10001001b;//

trisd = 0011b;  //

trise = 110b;

 

 // PORT  initial setting

portb=0; // ALL LEDs off

set_bit(portd,2); // LED OFF

set_bit(portd,3); // LED OFF

set_bit(portc,4); // LED OFF

set_bit(portc,5); // LED OFF

 

/***** ADC setting *****/

adcon1 = 10000111b; // AD not used

adcon0 = 10000001b;

 

// RS485

spbrg = 4;  // SPBRG

set_bit(txsta,BRGH); // high speed

clear_bit(txsta,SYNC); // async

//disable_interrupt(RCIE);

clear_bit(pie1,RCIE);

   set_bit(rcsta,RX9); // 9bit

set_bit(rcsta,CREN); // continuous receive

clear_bit(rcsta,CREN);

set_bit(rcsta,SPEN); // RS485 enable

 

// timer 0

OPTION_REG = 00000111b;

 

 

//t1con=0; // clear

tmr1l=0;

tmr1h=10;

 

   

set_bit(t1con,T1CKPS0); //

set_bit(t1con,T1CKPS1); // pre-scale 1:8

clear_bit(t1con,T1OSCEN);

clear_bit(t1con,T1SYNC);

clear_bit(t1con,TMR1CS); // internal clock;

set_bit(t1con,TMR1ON); // timer enable

 

   // interrupt enable or disable

   clear_bit(intcon,T0IE); // tim0 disable

   clear_bit(pie1,RCIE);   // RS disable

   disable_interrupt(RBIE);

   //clear_bit(intcon,RBIE); // RBs change disable

 

   set_bit(pie1,TMR1IE);   // Timer 1 enable

   set_bit(intcon,PEIE);

   set_bit(intcon,GIE);   // all interrupt

 

   while(1){   // main routine

    clear_bit(portd,2); // LED ON

    delay_ms(50);

    set_bit(portd,2);  // LED OFF

    delay_ms(50);

   } //end of while

 

   return 1;

}

Share this post


Link to post
Share on other sites
Guest Bert

If this is the actual code, shouldn't this line:

if ( (rcsta & 00000110) == 0){  // no error

be

if ( (rcsta & 00000110b) == 0){  // no error

 

I haven't looked closely enough see if there is an actual problem, but that little syntax error would cause lots of problems.    :;):

Share this post


Link to post
Share on other sites

I believe your problem is with this line:

if ( (rcsta & 00000110) == 0){  // no error

 

It should be:

if ( (rcsta & 00000110b) == 0){  // no error

 

because of the typo you are always going into the error logic branch, and the led stays off.

:cool:

Share this post


Link to post
Share on other sites

Tahnks.

By changing "00000110" to "00000110b" , LED portb 0 comes on.

However, it seems RCIF never be cleared. The code runs continuously in the interrupt routine. Main routine is not executed. I put ADM485 to RC7/RX but physically any RS485

device is not connected.

"rcvdata=rcreg;" should reset RCIF.

Share this post


Link to post
Share on other sites

The following code may be causing you problems.

     clear_bit(rcsta,CREN);
    set_bit(rcsta,CREN);

 

Generally, any two bit operations on the same register should be separated by a nop();  This is a workaround for the PIC read-modify-write problems.  (It is documented in more detail in the Microchip app notes & FAQ on their web site.)

 

I'm not sure that is the problem in this case, but the extra nop() won't hurt.  Try adding it elsewhere in the code too.  like when you operate on the intcon register.  Also be aware that enable_interrupts() is an intcon bit operation, so the same rule applies.

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...