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

Ext, Timer1 spurious interrupts

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



Joined: 25 Feb 2004
Posts: 28

View user's profile Send private message

Ext, Timer1 spurious interrupts
PostPosted: Fri Oct 30, 2009 9:57 am     Reply with quote

Can anybody help me with this,

I'm currently using CCS compiler v 4.042 on the pic18F8722. What I want to do is catch IR pulses on the interrupt pin using timer1 to time between the pulses. A general shell for the code is shown
Code:

#include <18F8722.h>

#device adc=8

#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV25                   //Brownout reset at 2.5V
#FUSES PUT                    //No Power Up Timer
#FUSES NOLVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES LPT1OSC                  //Timer1 configured for low-power operation
#FUSES MCLR                     //Master Clear pin enabled
#FUSES MCU                      //Microcontroller Mode

#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

#byte highbyte = 0xFCF
#byte lowbyte = 0xFCE


#int_TIMER1
void  TIMER1_isr(void)
{
   int16 time = 0;
   int8 inputb;
   static int count = 0;
   static int first = true; 
   
   disable_interrupts(int_timer1);
   
   if(first)
   {
      highbyte = 0xF7;
      lowbyte = 0x53;
      first = false;
      count = 0;
      enable_interrupts(int_timer1);
   }
   else
   {
      highbyte = 0xF7;
      lowbyte = 0x53;
      count++;
   }   
   
   if(count >13)
   {
      count = 0;
      first = true;
      enable_interrupts(int_ext);
   }
   else
      enable_interrupts(int_timer1);   
   
}

#int_EXT
void  EXT_isr(void)
{
   disable_interrupts(int_ext);
   highbyte = 0xFF;
   lowbyte = 0xFA;
   enable_interrupts(int_timer1);
}



void main()
{

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF|ADC_TAD_MUL_0);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);   
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_4(T4_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   
   
   
   ext_int_edge( H_TO_L );   
   disable_interrupts(int_timer1);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
//Setup_Oscillator parameter not selected from Intr Oscillotar Config tab

   // TODO: USER CODE!!
   
   while(1)
   {
      delay_ms(1);
   }

}

HighByte and low byte are the register addresses for timer 1 counts and I'm using this to set the value for timer1 to count FROM. The general trend of how the code should work is:

An interrupt hits RB0 and triggers int_EXT. The external interrupt is then disabled and timer 1 count is set to the point of just triggering. Timer 1 is then enabled. When timer 1 is triggered it checks to see if it is the first interrupt bit. If it is it sets up timer 1 to a set value and then re-enables timer1. It also says that the next timer1 interrupt will not be the first and sets abit count to zero. If the bit count goes to more than 13 interrupts it resets every thing.

My problem is that after the interrupt in RB0 the code works fine, counts up to 13 disables everything etc and then seems to retrigger the ext interrupt or timer1 interrupt on its own with no second external interrupt arriving. After this second spurious interrupt it sits quite happy until I put another interrupt onto RB0. Why the spurious second interrupt?


Any idea why??

This is killing me!!!

Thanks for any help

Sandy Wilson
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Fri Oct 30, 2009 10:06 am     Reply with quote

You have to read the port in order to clear the #int_EXT interrupt.
As soon as you re-enable the #int_EXT interrupt it fires again, because it has not been cleared.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Oct 30, 2009 12:57 pm     Reply with quote

Quote:

You have to read the port in order to clear the #int_EXT interrupt.

That's true for #int_rb, but not for #int_ext.


Quote:

My problem is that after the interrupt in RB0 the code works fine, counts
up to 13 disables everything etc and then seems to retrigger the ext
interrupt or timer1 interrupt on its own with no second external interrupt
arriving.

Create a cleaner test environment. Get rid of the IR device as an input
to your INT_EXT pin. Use a 2nd PIC board to generate test pulses and
send those pulses to the RB0 pin on the 1st board.

The 2nd board will wait for a keypress in a terminal window (using getc).
Upon receiving a keypress, it will send one pulse to the first board.
These will be clean pulses, with no "bounce" on the edges. There won't
be any unknown pulses generated by the 2nd board.

Or, instead of sending single pulses, you could send a stream of 13 or
more pulses upon each keypress. You can make the pulse generator
board do whatever you want it to do. You now control the test
environment. This will allow you to debug the problem.

The pulse generator board should be connected to the first board with
two short wires: A signal wire and a ground wire. Turn on power to
the pulse generator board first, and have it keep the output pin in a
benign state (either high or low level, based on your design). Then
turn on power to the board under test (the first board). Then start
the tests.
sandy wilson



Joined: 25 Feb 2004
Posts: 28

View user's profile Send private message

PostPosted: Mon Nov 02, 2009 3:18 am     Reply with quote

Hello Wayne_ and PCM Programmer,

Problem solved.

I had assumed, wrongly it appears, that the compiler generates the code automatically for reseting the interrupt flags in INTCON for the external interrupt and in PIR for timer 1 interrupt. The compiler doesn't.

After I reset them manually, problem solved so now its onwards and upwards.

Thanks again for your help. It pointed me in the right direction and I found the fault fairly quickly after theat.


SandyW
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Mon Nov 02, 2009 4:16 am     Reply with quote

Quote:
I had assumed, wrongly it appears, that the compiler generates the code automatically for reseting the interrupt flags in INTCON for the external interrupt and in PIR for timer 1 interrupt. The compiler doesn't.
It actually does (in a recent version), but possibly not in rather outdated PCH V4.042. Unfortunately I can't check.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Nov 02, 2009 5:07 pm     Reply with quote

Quote:

I had assumed, wrongly it appears, that the compiler generates the code
automatically for reseting the interrupt flags in INTCON for the external
interrupt and in PIR for timer 1 interrupt. The compiler doesn't.

The compiler does in fact clear the interrupt flags at the end of each isr.
I installed vs. 4.042 and compiled your program. See the .LST file code
shown below. The line that clears the interrupt flag is at the end of the
code in each case. I've add a comment to mark it.
Code:

CCS PCH C Compiler, Version 4.042, xxxxx    02-Nov-09 14:40

.................... #int_EXT 
.................... void  EXT_isr(void) 
.................... { 
....................    disable_interrupts(int_ext); 
000EE:  BCF    FF2.4
....................    highbyte = 0xFF; 
000F0:  MOVLW  FF
000F2:  MOVWF  FCF
....................    lowbyte = 0xFA; 
000F4:  MOVLW  FA
000F6:  MOVWF  FCE
....................    enable_interrupts(int_timer1); 
000F8:  BSF    F9D.0
.................... } 
.................... 
.................... 
.................... 
000FA:  BCF    FF2.1  // *** Clear the INTCON.INT0IF bit ***
000FC:  GOTO   0068


Code:

.................... #int_TIMER1 
.................... void  TIMER1_isr(void) 
.................... { 
....................    int16 time = 0; 
*
000B2:  CLRF   1C
000B4:  CLRF   1D
....................    int8 inputb; 
....................    static int count = 0; 
....................    static int first = true;   
....................     
....................    disable_interrupts(int_timer1); 
000B6:  BCF    F9D.0
....................     
....................    if(first) 
000B8:  MOVF   1A,F
000BA:  BZ    00CC
....................    { 
....................       highbyte = 0xF7; 
000BC:  MOVLW  F7
000BE:  MOVWF  FCF
....................       lowbyte = 0x53; 
000C0:  MOVLW  53
000C2:  MOVWF  FCE
....................       first = false; 
000C4:  CLRF   1A
....................       count = 0; 
000C6:  CLRF   19
....................       enable_interrupts(int_timer1); 
000C8:  BSF    F9D.0
....................    } 
....................    else 
000CA:  BRA    00D6
....................    { 
....................       highbyte = 0xF7; 
000CC:  MOVLW  F7
000CE:  MOVWF  FCF
....................       lowbyte = 0x53; 
000D0:  MOVLW  53
000D2:  MOVWF  FCE
....................       count++; 
000D4:  INCF   19,F
....................    }     
....................     
....................    if(count >13) 
000D6:  MOVF   19,W
000D8:  SUBLW  0D
000DA:  BC    00E6
....................    { 
....................       count = 0; 
000DC:  CLRF   19
....................       first = true; 
000DE:  MOVLW  01
000E0:  MOVWF  1A
....................       enable_interrupts(int_ext); 
000E2:  BSF    FF2.4
....................    } 
....................    else 
000E4:  BRA    00E8
....................       enable_interrupts(int_timer1);     
000E6:  BSF    F9D.0
....................     
.................... } 
.................... 
000E8:  BCF    F9E.0  // *** Clear the PIR1.TMR1IF bit ***
000EA:  GOTO   0068
sandy wilson



Joined: 25 Feb 2004
Posts: 28

View user's profile Send private message

PostPosted: Tue Nov 03, 2009 10:40 am     Reply with quote

Hello PCM Programmer,

I can see in my listing the two instructions for clearing the timer1 and ext interrupts. It still doesn't explain how, when I clear them manually, the code works ok.

Is there anything that you know about in the compiler/assembler/projects options that can affect this?

thanks for any help

sandy wilson
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Nov 03, 2009 10:50 am     Reply with quote

Post the source code for those two routines (not the .LST files), that
contains your modifications to clear the interrupts manually.
sandy wilson



Joined: 25 Feb 2004
Posts: 28

View user's profile Send private message

PostPosted: Wed Nov 04, 2009 4:00 am     Reply with quote

Hello PCM Programmer,

Here's the listing of the program with the resets in it. I've put in a couple of pointers to show where. I've also shown where I set a break/run to point.

Code:
#include <18F8722.h>

#device adc=8

#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV25                   //Brownout reset at 2.5V
#FUSES PUT                    //No Power Up Timer
#FUSES NOLVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES LPT1OSC                  //Timer1 configured for low-power operation
#FUSES MCLR                     //Master Clear pin enabled
#FUSES MCU                      //Microcontroller Mode

#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

#byte highbyte = 0xFCF
#byte lowbyte = 0xFCE
#bit  EXT_RESET = 0xFF2.1  <======= Declaration of the reset bit
#bit  TIMER_RESET = 0xF9E.0 <======= Declaration of the reset bit


#int_TIMER1
void  TIMER1_isr(void)
{
   int16 time = 0;
   int8 inputb;
   static int count = 0;
   static int first = true; 
   
   disable_interrupts(int_timer1);
   
   if(first)
   {
      highbyte = 0xF7;
      lowbyte = 0x53;
      first = false;
      count = 0;
      enable_interrupts(int_timer1);
   }
   else
   {
      highbyte = 0xF7;
      lowbyte = 0x53;
      count++;
   }   
   
   if(count >13)
   {
      count = 0;
      first = true;
      EXT_RESET = 0;                  <==== Use of reset
      TIMER_RESET = 0;              <==== Use of reset
      enable_interrupts(int_ext); , <===== Break Point
   }
   else
      enable_interrupts(int_timer1);   
   
}

#int_EXT
void  EXT_isr(void)
{
   disable_interrupts(int_ext);
   highbyte = 0xFF;
   lowbyte = 0xFA;
   enable_interrupts(int_timer1);
}



void main()
{

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF|ADC_TAD_MUL_0);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);   
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_4(T4_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   
   
   
   ext_int_edge( H_TO_L );   
   disable_interrupts(int_timer1);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
//Setup_Oscillator parameter not selected from Intr Oscillotar Config tab

   // TODO: USER CODE!!
   
   while(1)
   {
      delay_ms(1);
   }

}

What happens is that with NO interrupt resets in the code and the program running to the break point it receives all thirteen bits and stops at the break point as expected. If I then tell it to run again to the break point it will and then stop at the same point with NO bits being received on ext interrupt. If I then restart it again it runs quite happily until the next thirteen bits arrive. This implies that the ext interrupt clear bit is being toggled.
If I then clear the interrupt flags as shown the program runs as expected. It receives thirteen bits and then waits for the next thirteen bits.
Again I've checked the lst file and I am clearing the correct bits in the registers.

After a bit more digging it appears that it is the ext interrupt not clearing. If I step through it looking at the interrupt registers in the IDE even after it passes the "enable_interrupts(int_ext)" line the external interrupt never clears. On stepping through the assembler it seems to reach line "000EA: GOTO 0068" and then jumps of to address 0068 steps through what appears to be (to the ignorant eye) a delay routine and then jumps back into the external interrupt routine. It never gets to the line that clears the external interrupt until its gone through this process again.

Still no clue why Neutral

I'm pretty sure there's no external interrupts arriving when they aren't supposed to as I'm looking at them on the scope. The pulses that do arrive when required are clean and sharp with no slow rising/falling edges or anything funny like that.

Thanks for the help

Sandy Wilson
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Wed Nov 04, 2009 5:14 am     Reply with quote

Obviously, resetting the EXT interrupt flag before re-enabling the EXT interrupt is an additional action in your code, that's not provided by the self-reset in EXT ISR. If it's necessary for intended operation, simply assume that you have received additional H_TO_L edges at the EXT pin in the meantime. Why are you so sure that it can't happen?
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