In my previous blog "PIC32MZ tutorial -- Output Compare", I shows how to apply Output Compare without interrupt to generate PWM signal. I also tried the Output Compare interrupt. I selected OC to be PWM mode without fault pin (OCM = "110") and enable its interrupt. Below is the initialization of OC.
void OC1_Init(void) { OC1CON = 0x0000; //RPD1/RD1 -> OC1 RPD1R = 0xC; IPC1SET = 0x1E000000; IFS0CLR = 0x80; IEC0SET = 0x80; OC1RS = OC_MIN; OC1R = OC_MIN; OC1CON = 0x2E; OC1CONSET = 0x8000; // Enable OC }
But the application run not properly. The symptom was the OC interrupt never happened ( I set a breakpoint in the OC interrupt service routine, never saw the application entry this interrupt service routine). I raised a support ticket for this issue to Microchip. And the fleedback was that PWM mode without fault pin would not generate interrupt. So I decided change the PWM mode to Continuous Pulses mode (OCM = "101") and enabled interrupt then retried. This time the whole application is like below.
#include <xc.h> #include <sys/attribs.h> #pragma config FMIIEN = ON // Ethernet RMII/MII Enable (MII Enabled) // need a 25MHz XTAL in MII mode, a 50MHz Clock in RMII mode. #pragma config FETHIO = ON // Ethernet I/O Pin Select (Default Ethernet I/O) #pragma config PGL1WAY = ON // Permission Group Lock One Way Configuration (Allow only one reconfiguration) #pragma config PMDL1WAY = ON // Peripheral Module Disable Configuration (Allow only one reconfiguration) #pragma config IOL1WAY = ON // Peripheral Pin Select Configuration (Allow only one reconfiguration) #pragma config FUSBIDIO = OFF // USB USBID Selection (Controlled by Port Function) // DEVCFG2 7FF9B11A #pragma config FPLLIDIV = DIV_3 // System PLL Input Divider (3x Divider) #pragma config FPLLRNG = RANGE_5_10_MHZ // System PLL Input Range (5-10 MHz Input) #pragma config FPLLICLK = PLL_POSC // System PLL Input Clock Selection (POSC is input to the System PLL) #pragma config FPLLMULT = MUL_50 // System PLL Multiplier (PLL Multiply by 50) //PLL must output between 350 and 700 MHz #pragma config FPLLODIV = DIV_2 // System PLL Output Clock Divider (2x Divider) #pragma config UPLLFSEL = FREQ_24MHZ // USB PLL Input Frequency Selection (USB PLL input is 24 MHz) #pragma config UPLLEN = OFF // USB PLL Enable (USB PLL is disabled) // DEVCFG1 7F7F3839 #pragma config FNOSC = SPLL // Oscillator Selection Bits (System PLL) #pragma config DMTINTV = WIN_127_128 // DMT Count Window Interval (Window/Interval value is 127/128 counter value) #pragma config FSOSCEN = OFF // Secondary Oscillator Enable (Disable SOSC) #pragma config IESO = OFF // Internal/External Switch Over (Disabled) #pragma config POSCMOD = EC // Primary Oscillator Configuration (External clock mode) #pragma config OSCIOFNC = ON // CLKO Output Signal Active on the OSCO Pin (Enabled) #pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection (Clock Switch Disabled, FSCM Disabled) #pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576) #pragma config WDTSPGM = STOP // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming) #pragma config WINDIS = NORMAL // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode) #pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled) #pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window size is 25%) #pragma config DMTCNT = DMT31 // Deadman Timer Count Selection (2^31 (2147483648)) #pragma config FDMTEN = OFF // Deadman Timer Enable (Deadman Timer is disabled) // DEVCFG0 FFFFFFF7 #pragma config DEBUG = OFF // Background Debugger Enable (Debugger is disabled) #pragma config JTAGEN = ON // JTAG Enable (JTAG Port Enabled) #pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2) #pragma config TRCEN = ON // Trace Enable (Trace features in the CPU are enabled) #pragma config BOOTISA = MIPS32 // Boot ISA Selection (Boot code and Exception code is MIPS32) #pragma config FECCCON = OFF_UNLOCKED // Dynamic Flash ECC Configuration (ECC and Dynamic ECC are disabled (ECCCON bits are writable)) #pragma config FSLEEP = OFF // Flash Sleep Mode (Flash is powered down when the device is in Sleep mode) #pragma config DBGPER = ALLOW_PG2 // Debug Mode CPU Access Permission (Allow CPU access to Permission Group 2 permission regions) #pragma config EJTAGBEN = NORMAL // EJTAG Boot (Normal EJTAG functionality) // DEVCP0 #pragma config CP = OFF // Code Protect (Protection Disabled) #define Mvec_Interrupt() INTCONSET = 0x1000; asm volatile("ei"); #define OC1_VALUE (PORTD & 0x2) #define OC_MAX (0x7A120) #define OC_MIN (0x0) #define STEP_VALUE (500) #define LED_IOCTL() TRISHCLR = (1<<0) #define LED_SETON() LATHSET = (1<<0) #define LED_SETOFF() LATHCLR = (1<<0) #define LED_ONOFF() LATHINV = (1<<0) #define LED_OPEN() ANSELH &= 0xFFFFFFFE typedef enum _eRUN_MODE { Stable1, Welcome, Stable2, Goodbye, } eRUN_MODE; eRUN_MODE LED_RunMode; void OC1_Init(void) { OC1CON = 0x0000; //RPD1/RD1 -> OC1 RPD1R = 0xC; IPC1SET = 0x1E000000; IFS0CLR = 0x80; IEC0SET = 0x80; OC1RS = OC_MIN; OC1R = OC_MIN; OC1CON = 0x2D; OC1CONSET = 0x8000; // Enable OC } void LED_Init(void) { LED_SETOFF(); LED_OPEN(); LED_IOCTL(); LED_RunMode = Stable1; } void T23_Init(void) { T2CON = 0x0; T3CON = 0x0; TMR2 = 0; TMR3 = 0; //IPC3SET = 0x50000; IPC3SET = 0x120000; IEC0SET = 0x4000; IFS0CLR = 0x4000; PR2 = 0xA120; PR3 = 0x7; T2CON = 0x0008; T2CON |= 0x8000; } void T45_Init(void) { T4CON = 0; T5CON = 0; TMR4 = 0; TMR5 = 0; IPC6SET = 0x6; IFS0CLR = 0x1000000; IEC0SET = 0x1000000; PR4 = 0xE100; PR5 = 0x05F5; T4CON = 0x0008; T4CON |= 0x8000; } void __ISR(_OUTPUT_COMPARE_1_VECTOR,ipl7AUTO) OC1_Handler(void) { IFS0CLR = 0x80; LED_SETOFF(); if (LED_RunMode == Stable1) { ; // do nothing } else if (LED_RunMode == Stable2) { ; // do nothing } else if (LED_RunMode == Welcome) { OC1RS = OC1RS + STEP_VALUE; if (OC1RS >= OC_MAX) { T4CON = 0x0008; TMR4 = 0; TMR5 = 0; PR4 = 0xE100; PR5 = 0x05F5; T4CON = 0x8008; IFS0CLR = 0x1000000; LED_RunMode = Stable2; } } else // LED_RunMode == Goodbye { OC1RS = OC1RS - STEP_VALUE; if (OC1RS == OC_MIN) { T4CON = 0x0008; TMR4 = 0; TMR5 = 0; PR4 = 0xE100; PR5 = 0x05F5; T4CON = 0x8008; IFS0CLR = 0x1000000; LED_RunMode = Stable1; } } Nop(); } void __ISR(_TIMER_3_VECTOR,ipl4AUTO) T23_Handler(void) { LED_SETON(); TMR2 = 0; TMR3 = 0; IFS0CLR = 0x4000; Nop(); } void __ISR(_TIMER_5_VECTOR,ipl1AUTO) T45_Handler(void) { if (LED_RunMode == Stable1) { LED_RunMode = Welcome; //PR5 = 0x98; PR4 = 0x9680; PR5 = 0x98; } else if (LED_RunMode == Welcome) { ; // do nothing } else if (LED_RunMode == Stable2) { LED_RunMode = Goodbye; //PR5 = 0x98; PR4 = 0x9680; PR5 = 0x98; } else // LED_RunMode == Goodbye { ; // do nothing } TMR4 = 0; TMR5 = 0; IFS0CLR = 0x1000000; Nop(); } void main(void) { LED_Init(); OC1_Init(); T23_Init(); T45_Init(); Mvec_Interrupt(); while(1) { LED_Scheduler(); } }
PIC32MZ tutorial -- OC Interrupt
原文:http://www.cnblogs.com/geekygeek/p/pic32mz_ocinterrupt.html