PIC Programming question (interrupts)

Thread Starter


Joined Aug 31, 2012
Greetings all,

this is my first post to this forum but I will try to stay within guidelines for posting. Basically, I am using the PIC12F683 to read the RPM signal from a CPU fan. I know this seems easy, but I am having trouble figuring out how to write the code to enable to interrupt so that I can count the rising edges that can be read. I have written the code for an A/D which works and have set everything else up in the code. How do I write an interrupt that will time the edges? Have any of you done this before? By the way this is not for school, I have already received my engineering degree. This is for my own experimentation. I am not very experienced with programming PICS but have done this same application using another chip. Also, I am writing the code with a C compiler.

Datasheet for this PIC- http://ww1.microchip.com/downloads/en/devicedoc/41211d_.pdf

There is so much information on the datasheet regarding interrupts that I do not know where to simply begin! Should I enable the global interrupt or will I not need it for this specific task? I basically need an explanation of how I might go about this, or maybe point me in the right direction please?

Thank you for the help in advance. :)
I will continue to post my progress.


Joined Feb 24, 2006
Interrupts are generated by events in the peripheral devices. Each of the interrupt sources, and there are dozens, has an enable bit. In order for a specific interrupt to happen one of the individual enable bits must be a 1. It is also the case that the Global Interrupt Enable bit must be a one. All of the interrupts will send the processor to the same location, like address 0x0004. There you must test all of the possible interrupt flags that could be the source and service the correct one as quickly and expeditiously as possible. NB. This does not mean you have to check every flag; you only check the ones that you know are enabled.

For processing edges read the section on the Capture/Compare module (Section 11.1, p. 76). The input capture peripheral is designed to record the value of a free running timer when an edge occurs. Capturing a second edge, of the same or different type, allows you to measure elapsed time.

BTW. the purpose of GIE is to provide sections of code during which NO interrupts are allowed. These sections need to be short and infrequent.
Last edited:

Thread Starter


Joined Aug 31, 2012
Below is the code I have completed so far. I 'think' that I should be getting the value of the time so I solved for the RPM of the fan. The only problem now is how could I output it in voltage? Do I need an A/D to do this? If so any hints on how the code should be written? Also, feel free to edit my code if you feel generous. I enabled the global interrupt as you said before and have tried to do everything properly... keep in mind that I am new to programming PIC chips though. Am I anywhere near being able to read the RPM? I have followed the datasheet and tried my best.

Rich (BB code):
    // RPM of CPU Fan
     enable the internal interrupt
     interrupt that will time edge
     time * 2 = speed per second
     * 60 and output as voltage
     0 to 5 v output
     5v = 2000 RPM
#include <pic.h>
#ifndef _XTAL_FREQ
 // Unless already defined assume 4MHz system frequency
 // This definition is required to calibrate __delay_us() and __delay_ms()
 #define _XTAL_FREQ 8000000


unsigned long t1; // 16 bit number
unsigned short int i; // counter
unsigned short int stringLength;
unsigned long sps;
unsigned long output;
unsigned char input;

void config(){
    T1CON = 0b00110001; // enable timer1
    CCP1CON = 0x05; // capture rising edge
    INTCON = 0b11000000; // enable global/periph interrupt
    PIE1 = 0b00100000; // enable CCP interrupt
    TRISIO = 0x01; // gpio 2 pin (rising edge)

    ANSEL=0b01110001; // A/D pin
    ADCON0=0b00000001; // A/D setup

void interrrupt(void){
//respond to CCP interrupt
    INTCON = 0; // disable interrupts
    PIR1 = 0; // periph interrupt flag reset
    t1 = TMR1H;
    t1 = t1 << 8; // shift 8 bits
    t1 = t1 | TMR1L; //t1 long
    sps = t1 * 2; // time * 2 = speed per second
    output = sps * 60; // sps * 60hz = output

    // output in voltage here (not sure I am doing it right)
    ADCON0bits.GO_DONE=1; // not sure about this
    CCPR1L = input;

    INTCON = 0b11000000; // re-enable the interrupt again

void main() {
    // set up output here