Probando la interrupción de ADC en dsPIC33EP256MC506

1

Tengo una placa de desarrollo Microchip MCLV-2 diseñada para controlar las clasificaciones pequeñas BLDC y PMSM. Estoy tratando de desarrollar un programa simple para probar la interrupción de ADC. Básicamente, quiero que el programa simplemente espere la interrupción en la rutina principal. Una vez que ocurre, debe ingresar en la rutina de servicio de interrupción e iluminar un LED durante 1 segundo. La interrupción se activa cada vez que se cambia la lectura del potenciómetro girándola manualmente.

Escribí un programa usando diferentes notas de aplicación de Microchip. Estoy usando MPLAB X con el compilador XC16. El programa no está funcionando. ¿Alguien por favor puede ayudar?

Gracias.

Código fuente (main.c):

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#define Fosc 20000000       // system clock frequency, Fosc = Fin*M/(N1*N2)
#define FCY 10000000        // xtal = 8MHz, Fosc = 20MHz, FCY = Fosc/2
#define FPWM 20000          // desired PWM frequency
#define MILLISEC FCY/20000  // 1 mSec delay constant

/* Functions and variable declarations */
INTCON2bits.GIE = 1;            // global interrupt enable
void InitClkSettings(void);
void DelayNmSec(unsigned int N);
void InitADC10(void);

unsigned int t1 = 100;      // 100 ms variable
unsigned int t2 = 400;      // 400 ms variable
unsigned int i;             // counter variable

// Main routine
int main(void)
{
    /* Initialize clock, ADC and PWM modules */
    INTCON2bits.GIE = 1;    // global interrupt enable
    InitClkSettings();
    InitADC10();
    TRISD = 0xFF9F;     // RD6 and RD7 are outputs for LEDs 1 and 2 

    while(1)
    {
        // do nothing, just wait for ADC interrupt
    } // end of while(1)
}   // end of main

/* Initialize clock settings, PLL, etc. */
void InitClkSettings(void)
{
    // Configure Oscillator to operate the device at 20Mhz
    // Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
    // Fosc= 8*10/(2*2)= 20Mhz for 8M input clock

    PLLFBD =  8;                // M=10
    CLKDIVbits.PLLPOST = 0;     // N1=2
    CLKDIVbits.PLLPRE = 0;      // N2=2
    /* Initiate Clock Switch to Primary Oscillator with PLL (NOSC = 0x3) */
    __builtin_write_OSCCONH(0x03);
    __builtin_write_OSCCONL(0x01);

    while(OSCCONbits.COSC != 0b011);
    // Wait for PLL to lock
    while(OSCCONbits.LOCK != 1);    
}

/* ADC Module Configuration*/
void InitADC10(void)
{
    //ADC Init
    ANSELE = 0;
    ANSELEbits.ANSE13 = 1;  // POTENTIOMETER   

    AD1CON1 = 0x006C;   //ADC is off
                        //Continue module operation in Idle mode
                        //10-bit, 4-channel ADC operation
                        //Data Output Format bits Integer (0000 00dd dddd dddd)
                        //PWM Special Event Trigger comparator triggered
                        //Samples CH0, CH1, CH2, CH3 simultaneously when CHPS<1:0> = 1x
                        //Sampling begins immediately after last conversion SAMP bit is auto-set.
    Nop();
    AD1CON1bits.SSRC = 0;   //0 for manual, 2 for Timer3, 3 for SEVTCMP

    AD1CON4 = 0x0000;   //no dma usage

    AD1CHS0 = 0x000D;   //MUX B Channel 0 negative input is VREF-
                        //MUX B Channel 0 positive input is AN0
                        //MUX A Channel 0 negative input is VREF-
                        //MUX A Channel 0 positive input is AN8
                        //just a startup sequence to read the POT ( AN13 )

    AD1CSSL = 0x0000;   //Skip all ANx channels for input scan

    AD1CON3 = 0x0005;   //ADC Clock derived from system clock
                        //Autosample time time bits = 0 TAD since PWM is controlling sampling time
                        //TAD = 6*TCY, TAD approx 85 nSec

    AD1CON2 = 0x0000;   //ADREF+ = AVDD ADREF- = AVSS
                        //Do not scan inputs
                        //00 = Converts CH0 only
                        //A/D is currently filling buffer 0x0-0x7
                        //Interrupts at the completion of conversion for each sample/convert sequence
                        //Always starts filling buffer from the beginning
                        //Always uses channel input selects for Sample A

    AD1CON1bits.DONE = 0;   //Making sure that there is not any conversion in progress
    IPC3bits.AD1IP = 5;     //Assigning ADC ISR priority
    IFS0bits.AD1IF = 0;     //Clearing the ADC Interrupt Flag
    IEC0bits.AD1IE = 1;     //Enabling the ADC conversion complete interrupt
    AD1CON1bits.ADON = 1;   //Enabling the ADC module
}

/*Delay subroutine*/
void DelayNmSec(unsigned int N)
{
unsigned int j;
while(N--)
    for(j=0;j < MILLISEC;j++);
}

/* ADC Interrupt subroutine */
void __attribute__((interrupt,no_auto_psv)) _AD1Interrupt(void)
{
    AD1CON1bits.DONE = 0;
    IFS0bits.AD1IF = 0;
    LATDbits.LATD6 = 1;     // turn on LED 2
    DelayNmSec(1000);       // wait 1 sec
    LATDbits.LATD6 = 0;     // turn off LED 2
    DelayNmSec(1000);       // wait 1 sec
}

Archivo de configuración (config.c)

// DSPIC33EP256MC506 Configuration Bit Settings

// 'C' source line config statements

#include <xc.h>

// FICD
#pragma config ICS = PGD2               // ICD Communication Channel Select bits (Communicate on PGEC2 and PGED2)
#pragma config JTAGEN = OFF             // JTAG Enable bit (JTAG is disabled)

// FPOR
#pragma config ALTI2C1 = OFF            // Alternate I2C1 pins (I2C1 mapped to SDA1/SCL1 pins)
#pragma config ALTI2C2 = OFF            // Alternate I2C2 pins (I2C2 mapped to SDA2/SCL2 pins)
#pragma config WDTWIN = WIN25           // Watchdog Window Select bits (WDT Window is 25% of WDT period)

// FWDT
#pragma config WDTPOST = PS32768        // Watchdog Timer Postscaler bits (1:32,768)
#pragma config WDTPRE = PR128           // Watchdog Timer Prescaler bit (1:128)
#pragma config PLLKEN = ON              // PLL Lock Enable bit (Clock switch to PLL source will wait until the PLL lock signal is valid.)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable bit (Watchdog Timer in Non-Window mode)
#pragma config FWDTEN = ON              // Watchdog Timer Enable bit (Watchdog timer always enabled)

// FOSC
#pragma config POSCMD = XT              // Primary Oscillator Mode Select bits (XT Crystal Oscillator Mode)
#pragma config OSCIOFNC = OFF           // OSC2 Pin Function bit (OSC2 is clock output)
#pragma config IOL1WAY = ON             // Peripheral pin select configuration (Allow only one reconfiguration)
#pragma config FCKSM = CSECMD           // Clock Switching Mode bits (Clock switching is enabled,Fail-safe Clock Monitor is disabled)

// FOSCSEL
#pragma config FNOSC = FRC              // Oscillator Source Selection (Internal Fast RC (FRC))
#pragma config PWMLOCK = ON             // PWM Lock Enable bit (Certain PWM registers may only be written after key sequence)
#pragma config IESO = ON                // Two-speed Oscillator Start-up Enable bit (Start up device with FRC, then switch to user-selected oscillator source)

// FGS
#pragma config GWRP = OFF               // General Segment Write-Protect bit (General Segment may be written)
#pragma config GCP = OFF                // General Segment Code-Protect bit (General Segment Code protect is Disabled)
    
pregunta Adeel

1 respuesta

0

¿En qué parte de su código inicia realmente la conversión de ADC? Simplemente habilitar el módulo no es suficiente.

Por su pregunta, parece que está esperando que el módulo ADC genere una interrupción simplemente en virtud de que su voltaje de entrada haya sido cambiado (por su manipulación del potenciómetro) pero no funciona de esta manera.

Para que el módulo ADC genere una interrupción, necesita completar una conversión de analógico a digital.
Solo inicia una conversión cuando le indica que lo haga en su código (o si se activa por un temporizador o algún otro método que haya configurado en su código). Un cambio de voltaje en su entrada no inicia una conversión y, por lo tanto, no dará como resultado una interrupción.

    
respondido por el brhans

Lea otras preguntas en las etiquetas