3

我无法让模拟比较器在 dsPIC33EP512MU810 上工作。我想比较两个外部电压。连接到 C1IN1+ 的是我的参考电压 (1.5V),C1IN1- 是我的可变电压 (1.1 - 1.9V)。我已将事件触发器设置为在上升沿和下降沿生成,但我只在程序启动时收到中断,之后什么也没有。

// Macro to provide an indicator of when the ISR is running on a digital output pin (G6).
#define MONIT_1 (LATGbits.LATG6)

// Configuration registers.
_FGS(GSSK_OFF);
_FOSCSEL(FNOSC_PRIPLL & IESO_ON);
_FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT & IOL1WAY_OFF);
_FWDT(FWDTEN_OFF);
_FPOR(BOREN_ON);
_FICD(ICS_PGD2);
_FAS(APLK_OFF);

// The SYS_OSCSEL bits are written to the OSCCON.NOSC bits to select a new
// oscillator and read from the OSCCON.COSC bits to determine the current
// oscillator.
#define SYS_OSCSEL      0b011       // 011 = Primary Oscillator with PLL (XTPLL, HSPLL, ECPLL)

#define SYS_FIN         8000000LL   // clock-frequecy in Hz with suffix LL (64-bit-long)
#define SYS_PLLPRE      0
#define SYS_PLLPOST     1
#define SYS_PLLDIV      38
#define SYS_FVCO        ((SYS_FIN * (SYS_PLLDIV + 2)) / (SYS_PLLPRE + 2))
#define SYS_FOSC        (SYS_FVCO / (2 * (SYS_PLLPOST + 1)))
#define SYS_FCY         (SYS_FOSC/2)

// bit 0 OSWEN: Oscillator Switch Enable bit
#define OSCCON_OSWEN    (0x0001)  
// bit 5 LOCK: PLL Lock Status bit (read-only)
#define OSCCON_LOCK     (0x0020)    
// bit 6 IOLOCK: Peripheral Pin Select (PPS) Lock bit
#define OSCON_IOLOCK    (0x0040)   

static volatile int _cout; // To capture the comparator output during the ISR.

int main(int argc, char** argv) 
{
     // Set up PLL to give Fosc = 40MHz from an 8MHz Crystal.
    CLKDIVbits.PLLPRE = SYS_PLLPRE;
    CLKDIVbits.PLLPOST = SYS_PLLPOST;
    PLLFBDbits.PLLDIV = SYS_PLLDIV;

    CLKDIVbits.DOZEN = 0;       // No Doze
    CLKDIVbits.ROI = 0;         // not setting recover on interrupt

    // Switch to PLL mode from XT.
    __builtin_write_OSCCONH(SYS_OSCSEL);
    __builtin_write_OSCCONL(OSCCON | 0x01);
    // Wait for Clock switch to occur
    while (OSCCON_OSWEN & OSCCON);                  
    // Wait for PLL to lock
    while (OSCCONbits.LOCK != 1);                   
    // Wait for Oscillator to match
    while (OSCCONbits.COSC != OSCCONbits.NOSC);     

    // PIN20, C1IN1+ as analogue reference pin, VBUS -> PL1.PIN20
    ANSELBbits.ANSB5 = 1;
    TRISBbits.TRISB5 = 1;
    // PIN11, C1IN1- as analogue voltage pin for VM1 -> PL1.PIN11
    ANSELGbits.ANSG7 = 1;
    TRISGbits.TRISG7 = 1;

    // PIN10: digital MONIT_1 
    ANSELGbits.ANSG6 = 0;
    TRISGbits.TRISG6 = 0;
    MONIT_1 = 0;

    // Disable comparator
    CM1CONbits.CON = 0;

    // Continue operation in idle mode.
    CMSTATbits.CMSIDL = 0;
    // Comparator output is internal only
    CM1CONbits.COE = 0;
    // Comparator input is not inverted
    CM1CONbits.CPOL = 0;
    // Trigger/event/interrupt is generated on any change of the comparator output (while CEVT = 0)
    CM1CONbits.EVPOL = 0b11;
    // Comparator reference input selection. VIN+ input connects to external C1IN1+ pin
    CM1CONbits.CREF = 0;
    // Comparator channel selection. VIN- input connects to external C1IN1- pin
    CM1CONbits.CCH = 0b00;

    // Enable comparators
    CM1CONbits.CON = 1;
    // Enable comparator interrupts
    IEC1bits.CMIE = 1;
    // Enable the global interrupt
    INTCON2bits.GIE = 1;
    // Clear comparator interrupt flag
    IFS1bits.CMIF = 0;

    // Clear this value to enable future triggers and interrupts.
    CM1CONbits.CEVT = 0;

    while(1)
    {
        Nop();
    }

    return (EXIT_SUCCESS);
}

void __attribute__ ((__interrupt__,no_auto_psv)) _CM1Interrupt(void)
{
    MONIT_1 = 1;        // Turn the G6 IO on.

    // Clear comparator interrupt flag
    IFS1bits.CMIF = 0;

    // Check if comparator event 1 occurred.
    if (CM1CONbits.CEVT > 0)
    {
        _cout = CM1CONbits.COUT;
        // Clear comparator events to trigger the next event.
        CM1CONbits.CEVT = 0;

    }
    MONIT_1 = 0;        // Turn the G6 IO off.
}
4

0 回答 0