PIC Programming question (interrupts)

Discussion in 'Embedded Systems and Microcontrollers' started by mrmodest, Aug 31, 2012.

  1. mrmodest

    Thread Starter New Member

    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.
  2. Papabravo


    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: Sep 1, 2012
  3. russ_hensel

    Well-Known Member

    Jan 11, 2009
  4. mrmodest

    Thread Starter New Member

    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.

    Code ( (Unknown Language)):
    2.     // RPM of CPU Fan
    3. /*
    4.      enable the internal interrupt
    5.      interrupt that will time edge
    6.      time * 2 = speed per second
    7.      * 60 and output as voltage
    8.      0 to 5 v output
    9.      5v = 2000 RPM
    10. */
    11. #include <pic.h>
    12. #ifndef _XTAL_FREQ
    13.  // Unless already defined assume 4MHz system frequency
    14.  // This definition is required to calibrate __delay_us() and __delay_ms()
    15.  #define _XTAL_FREQ 8000000
    16. #endif
    20. unsigned long t1; // 16 bit number
    21. unsigned short int i; // counter
    22. unsigned short int stringLength;
    23. unsigned long sps;
    24. unsigned long output;
    25. unsigned char input;
    27. void config(){
    28.     T1CON = 0b00110001; // enable timer1
    29.     CCP1CON = 0x05; // capture rising edge
    30.     INTCON = 0b11000000; // enable global/periph interrupt
    31.     PIE1 = 0b00100000; // enable CCP interrupt
    32.     TRISIO = 0x01; // gpio 2 pin (rising edge)
    34.     ANSEL=0b01110001; // A/D pin
    35.     ADCON0=0b00000001; // A/D setup
    36. }
    38. void interrrupt(void){
    39. //respond to CCP interrupt
    41.     INTCON = 0; // disable interrupts
    42.     PIR1 = 0; // periph interrupt flag reset
    43.     t1 = TMR1H;
    44.     t1 = t1 << 8; // shift 8 bits
    45.     t1 = t1 | TMR1L; //t1 long
    46.     sps = t1 * 2; // time * 2 = speed per second
    47.     output = sps * 60; // sps * 60hz = output
    50.     // output in voltage here (not sure I am doing it right)
    51.     ADCON0bits.GO_DONE=1; // not sure about this
    52.     input=ADRESH;
    53.     CCPR1L = input;
    56.     INTCON = 0b11000000; // re-enable the interrupt again
    57. }
    59. void main() {
    60.     // set up output here
    61.     config();
    62.     while(1){
    63.         // NOT SURE IF I NEED THIS LOOP YET
    64.     }
    66. }