What am I missing here?
I'm trying to setup a 100 Hz interrupt for a pic18f2550 but getting a 200 Hz interrupt.
Design data:
8 MHz internal clock
0x1388 = 5000 count match for Comparator count
Measured clocks:
OSC2 = 2 MHz
RA5 bit = 200 Hz (interrupt clock)
I have done similar interrupt timing for a pic16f876 without issue.
Design data:
20 MHz external clock
0x0140 = 320 count match
Measured clock:
15.82 KHz (interrupt clock)
PIC18F2550 code snippet:
#include <xc.h>
#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include "xtal.h"
// CONFIGURATION BITS
// CONFIG1L
#pragma config PLLDIV = 5 // PLL Prescaler Selection bits (Divide by 5 (20 MHz oscillator input))
#pragma config CPUDIV = OSC1_PLL2 // System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
#pragma config USBDIV = 1 // USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes directly from the primary oscillator block with no postscale)
// CONFIG1H
#pragma config FOSC = INTOSC_EC // Oscillator Selection bits (Internal oscillator, CLKO function on RA6, EC used by USB (INTCKO))
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
// CONFIG2L
#pragma config PWRT = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOR = OFF // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config BORV = 3 // Brown-out Reset Voltage bits (Minimum setting 2.05V)
#pragma config VREGEN = OFF // USB Voltage Regulator Enable bit (USB voltage regulator disabled)
// CONFIG2H
#pragma config WDT = OFF // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)
// CONFIG3H
#pragma config CCP2MX = OFF // CCP2 MUX bit (CCP2 input/output is multiplexed with RB3)
#pragma config PBADEN = OFF // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config LPT1OSC = OFF // Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = OFF // MCLR Pin Enable bit (RE3 input pin enabled; MCLR pin disabled)
// CONFIG4L
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
int8_t en0;
uint8_t sw0,sw1,sw2;
uint8_t currA0,lastA0;
uint8_t fUpdate=0;
uint16_t vBat;
uint8_t ddsM;
float ddsF1,ddsF2;
float ddsP1,ddsP2;
float ddsA;
float ddsT;
//============================================================
void main()
{
TRISA=0b11000001; // Set Port A direction bits
TRISB=0b11100101; // Set Port B direction bits
TRISC=0b01111111; // Set Port C direction bits
OSCCON=0x72; // Select internal oscillator @ 8MHz
ADCON0=0; // A/D converter off
ADCON1=0x0f; // All digital inputs
INTCON2bits.nRBPU=1; // Port B pull-ups disabled
UCON=0x00; // USB module and supporting circuitry disabled
UCFG=0x08; // On-chip USB transceiver disabled
PORTA=0xff;
PORTB=0xff;
// Setup battery monitor
ADCON0=0x01; // A/D converter on
ADCON1=0x0e; // AN0 only
ADCON2=0x91; // Right justified | 4*Tad | Fosc/8 (for 8 MHz system clock)
// Setup rotary encoder
en0=0;
sw0=sw1=sw2=0;
lastA0=PORTCbits.RC1;
// Setup CCP1 configuration
CCPR1H=0x13; // 100 Hz interrupt
CCPR1L=0x88;
CCP1CON=0x0b; // Compare mode, trigger special event
// Setup Timer3 configuration
TMR3H=0;
TMR3L=0;
T3CON=0x55; // T3CCP | 1:4 Prescale | TMR3CS | TMR3ON bits
// Enable CCP1 interrupt
PIR1bits.CCP1IF=0; // CCP2 Interrupt Flag bit
PIE1bits.CCP1IE=1; // CCP2 Interrupt Enable bit
INTCON=0xc0; // GIE and PEIE interrupts
while (1) {
// Read battery voltage
ADCON0bits.GO=1;
while (ADCON0bits.nDONE);
vBat = (uint16_t)ADRESH << 8 | (uint16_t)ADRESL;
ddsA = 5.0 * (float)vBat / 1024.0;
// Process encoder inputs
if (en0 > 0)
ddsF1 += pow(10.,abs(en0)-1);
else if (en0 < 0)
ddsF1 -= pow(10.,abs(en0)-1);
en0=0;
}
}
//============================================================
void interrupt isr()
{
if (PIE1bits.CCP1IE && PIR1bits.CCP1IF) {
PIR1bits.CCP1IF = 0; // clear CCP1 Interrupt Flag
LATAbits.LA5 = 0;
// Read rotary encoder
currA0=PORTCbits.RC1;
if (lastA0==0 && currA0==1) {
if (PORTCbits.RC2==1) en0--; else en0++;
}
lastA0=currA0;
if (PORTCbits.RC0==0) sw0=1;
if (PORTCbits.RC4==0) sw1=1;
if (PORTCbits.RC5==0) sw2=1;
LATAbits.LA5 = 1;
}
}