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

12f629, interrupt on pin change

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



Joined: 18 Feb 2011
Posts: 7

View user's profile Send private message

12f629, interrupt on pin change
PostPosted: Sun Mar 06, 2011 3:05 pm     Reply with quote

Hello!

I'm working on a project with a PIC 12F629... A task the PIC should perform is decode a digital signal, applied on a digital PIN. The signal is a square wave with a period of about 120us. I used an 'interrupt on change' on the PIN and tried to optimize my ISR but it doesn't work.

To debug the problem, I wrote a simpler program which should only "move" a PIN on each interrupt:

Code:
#int_ra
void isr() {
   output_high(PIN_LED);
   output_low(PIN_LED);
}

void main() {

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);   
   setup_comparator(NC_NC);
   setup_vref(FALSE);

   enable_interrupts(INT_DCC);
   enable_interrupts(GLOBAL);
   
   while(1) {}
}


Using a logical analyzer, I drawed the original signal (Track0) and the output (PIN_LED) of the PIC (Track2)... the result is:



As you can see, it takes 36us on the rising edge (T2-T1) and 45us (T4-T3) on the falling one... and sometimes the interrupt is missing.

If I check che ASM of my program, I can see my isr is just 8 instructions, so it should take only 4us (4 instructions at 4MHz) to output_high:

Code:
.................... void isr() {
....................    output_high(PIN_LED);
0040:  BSF    03.5
0041:  BCF    05.4
0042:  BCF    03.5
0043:  BSF    05.4
....................    output_low(PIN_LED);
0044:  BSF    03.5
0045:  BCF    05.4
0046:  BCF    03.5
0047:  BCF    05.4
.................... }


But at address 0x0004 (the interrupt vector address) I can see several instructions added by the compiler, I think to detect which interrupt fired and to jump to the correct #int_xx instruction.

As this is the only interrupt I need to manage, is there a way to optimize interrupt routine?

Can you explain the different time my PIC seems to respond to falling and rising changes on the PIN?

Thanks!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 06, 2011 3:12 pm     Reply with quote

Quote:
INT_DCC

What is this ? I just scanned the whole CCS "Devices" directory and I
don't find that constant in any of the .h files. What's your compiler version ?
lukyluke



Joined: 18 Feb 2011
Posts: 7

View user's profile Send private message

PostPosted: Sun Mar 06, 2011 3:25 pm     Reply with quote

Sorry it was in my .h file, a way to change the signal PIN:

Code:
#define INT_DCC 0x080B08


which comes from 12F629.H:

Code:
#define INT_RA3                   0x080B08
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Sun Mar 06, 2011 3:45 pm     Reply with quote

It shouldn't take any different time, on the rising or falling edge, and missing edges, suggests a voltage problem (level not actually getting low enough or high enough). However the delay, is the overhead involved in saving _all_ the registers that may be used inside the interrupt, and testing the actual source. The former typically takes perhaps 28 instructions, while using a single interrupt on change, extends the latter, with the compiler having to add code to work out just which pin has actually changed.
If you 'rem' out the option 'nolist' at the start of the processor include file, the 'hidden' code will become visible.
However the missing in this case, may just be running out of time. The handler has to also clear the interrupt, and restore all the registers on exit, taking nearly as long again...

How to reduce this?.
When an interrupt occurs, _one_ handler is called. The 'int_global' handler. It then does the housekeeping, saving all the registers, and working out which interrupt has triggered. On return, it also clears the interrupt, and as you are using it, also reads the port (which is a hardware requirement to clear the int on change).
Now, you can replace this handler, by writing your own 'int_global'. Look at ex_glint. Obviously, provided this is the only interrupt in use, then all the testing for 'which interrupt', is not needed. How many registers you need to save, will depend on what code you then put in your handler. You need to manually work out everything that your handler changes, and make sure these registers are all saved.
You can also gain speed, by switching to 'fast_io' mode. Half of the instructions for each output, are the ones setting the TRIS. Remember though, that if you go DIY, _you_ need to do all the hardware tasks. So must read the port, clear the interrupt flag, save and restore every register used in your code, etc., so it is significant work. However you should be able to reduce the time to perhaps 20uSec in total, depending on what is in your real code.

Best Wsihes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 06, 2011 4:21 pm     Reply with quote

Code:
#include <12F629.h>
#fuses INTRC_IO, NOWDT, NOMCLR, PUT, BROWNOUT
#use delay(clock=4000000)

#define PIN_LED PIN_A4

#int_ra
void isr() {
   
   output_high(PIN_LED);
   output_low(PIN_LED);
}

void main() {

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);   
   setup_comparator(NC_NC);
   setup_vref(FALSE);

   enable_interrupts(INT_RA3);
   enable_interrupts(GLOBAL);
   
   while(1) {}
}

You didn't post a test program, so I made one. You didn't post your
compiler version, so I went back and looked at one of your old posts
and installed vs. 4.057.

I connected a BK4011 function generator to pin A3 with a 120 Hz,
0 to 5v peak-to-peak, 50% duty cycle squarewave. I put a scope
probe on pin A4.

I get an interrupt frequency of 240 Hz, with some slight variation.
I get a solid positive pulse width of 4 us, with no ghosting to longer
pulses.

So to me, it's working.
hmnrobots



Joined: 02 Oct 2009
Posts: 11

View user's profile Send private message

PostPosted: Wed Mar 09, 2011 10:49 am     Reply with quote

Hi
did you use the 12F629 header (equipped with the 12F629-ICD) or directly the 12F629
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 09, 2011 1:03 pm     Reply with quote

Just an ordinary 8-pin DIP package 12F629.
mars79



Joined: 19 Jun 2013
Posts: 6
Location: Bulgaria, Plovdiv

View user's profile Send private message Send e-mail

PostPosted: Tue Apr 30, 2024 3:07 am     Reply with quote

Code:
#include <12F629.h>
#fuses INTRC_IO, NOWDT, NOMCLR, PUT, BROWNOUT
#use delay(clock=4000000)

#define PIN_LED PIN_A4

#int_ra
void isr() {
   
   output_high(PIN_LED);
   output_low(PIN_LED);
}

void main() {

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);   
   setup_comparator(NC_NC);
   setup_vref(FALSE);

   enable_interrupts(INT_RA3);
   enable_interrupts(GLOBAL);
   
   while(1) {}
}


I hope I'm not breaking the forum rules, but I decided to use the thread to avoid creating a new one for my problem.
Can I use this code to measure the frequency of the signal applied to the RA3 pin?
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