# PIC Programming question (interrupts)

#### mrmodest

Joined Aug 31, 2012
4
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.

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.

#### Papabravo

Joined Feb 24, 2006
12,407
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:

#### russ_hensel

Joined Jan 11, 2009
825

#### mrmodest

Joined Aug 31, 2012
4
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
#endif

__CONFIG(FCMEN_OFF & IESO_OFF & MCLRE_OFF & WDTE_OFF & FOSC_INTOSCIO);

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
}

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)
CCPR1L = input;

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

void main() {
// set up output here
config();
while(1){
// NOT SURE IF I NEED THIS LOOP YET
}

}