2015-03-06 2 views
1

J'essaie de faire une petite application sur le pic32mx795f512l mais je ne peux pas le faire fonctionner. Ce que je veux réaliser, c'est que l'adc reçoive continuellement la valeur analogique actuelle du canal 0 avec le taux le plus élevé possible. Si le tampon de 16 mots est rempli, il devrait déclencher le dma pour enregistrer ce tampon dans le RAM. Le dma devrait déclencher une interruption si le tampon de RAM est plein. Donc, je pourrais commencer le calcul dans la boucle principale. Mon problème maintenant est que le dma n'est pas déclenché du tout. Lorsque j'active l'interruption sur l'adc, la boucle principale ne fonctionne pas. Est-ce que quelqu'un sait ce que j'ai fait de mal? Voici mon code source:PIC32MX dma pas déclenché par adc

/*** DEVCFG0 ***/ 

#pragma config DEBUG = OFF 
#pragma config ICESEL = ICS_PGx2 
#pragma config PWP = 0xff 
#pragma config BWP = OFF 
#pragma config CP = OFF 

/*** DEVCFG1 ***/ 

#pragma config FNOSC = PRIPLL 
#pragma config FSOSCEN = ON 
#pragma config IESO = ON 
#pragma config POSCMOD = XT 
#pragma config OSCIOFNC = OFF 
#pragma config FPBDIV = DIV_8 
#pragma config FCKSM = CSDCMD 
#pragma config WDTPS = PS1048576 
#pragma config FWDTEN = ON 

/*** DEVCFG2 ***/ 

#pragma config FPLLIDIV = DIV_2 
#pragma config FPLLMUL = MUL_20 
#pragma config FPLLODIV = DIV_1 
#pragma config UPLLIDIV = DIV_2 
#pragma config UPLLEN = ON 

/*** DEVCFG3 ***/ 

#pragma config USERID = 0xffff 
#pragma config FSRSSEL = PRIORITY_7 
#pragma config FMIIEN = ON 
#pragma config FETHIO = ON 
#pragma config FCANIO = ON 
#pragma config FUSBIDIO = ON 
#pragma config FVBUSONIO = ON 

int adcValues[128]; 

void __ISR(_ADC_VECTOR, IPL7SRS) ADCHandler(void) // interrupt every 8 samples 
{ 

    IFS1bits.AD1IF = 0; // clear interrupt flag 
} 



void __ISR(_DMA0_VECTOR, ipl5) _IntHandlerSysDmaCh0(void) 
{ 

    int dmaFlags=DCH0INT&0xff; // read the interrupt flags 

    /* 
    perform application specific operations in response to any interrupt flag set 
    */ 
    DCH0INTCLR=0x000000ff; // clear the DMA channel interrupt flags 
    IFS1CLR = 0x00010000; // Be sure to clear the DMA0 interrupt flags 

} 

unsigned int __attribute__((always_inline)) _VirtToPhys(const void* p) { 
    return (int) p < 0 ? ((int) p & 0x1fffffffL) : (unsigned int) ((unsigned char*) p + 0x40000000L); 
} 

void initADC(void) { 


    AD1PCFG = 0xFFFB; // PORTB = Digital; RB2 = analog 
    AD1CON1 = 0x0000; // SAMP bit = 0 ends sampling 
    // and starts converting 

    // turn ADC on | unsigned 32-bit int output | auto-convert after sample finished | 
    // don?t stop conversions at interrupt | auto-sample after conversion finished 
    AD1CON1 = (1 << 15) | (4 << 8) | (7 << 5) | (0 << 4) | (1 << 2); 


    IPC6bits.AD1IP = 7; // INT priority level 7, for shadow register set 
    IFS1bits.AD1IF = 0; // clear interrupt flag 
    IEC1bits.AD1IE = 1; // enable interrupts 

    AD1CHS = 0x00020000; // Connect RB2/AN2 as CH0 input 

    AD1CON1SET = 0x8000; // turn on the ADC 
} 

void initDMA(void) { 


    IEC1CLR=0x00010000; // disable DMA channel 0 interrupts 
    IFS1CLR=0x00010000; // clear any existing DMA channel 0 interrupt flag 
    DMACONSET=0x00008000; // enable the DMA controller 
    DCH0CON=0x03; // channel off, priority 3, no chaining 
    DCH0ECON=0; 
    DCH0ECONbits.CHSIRQ=_ADC_IRQ; // This should map the AD1 ? ADC1 Convert Done Interrupt to start the dma IRQ no. 33 Vector no. 27 
    // program the transfer 
    DCH0SSA=_VirtToPhys(&ADC1BUF0); // transfer source physical address 
    DCH0DSA=_VirtToPhys(adcValues); // transfer destination physical address 
    DCH0SSIZ=16; // source size 16 bytes 
    DCH0DSIZ=128; // destination size NUM_SAMPS bytes 
    DCH0CSIZ=16; // 16 bytes transferred per event 
    DCH0INTCLR=0x00ff00ff; // clear existing events, disable all interrupts 
    //DCH0INTSET=0x00090000; // enable Block Complete and error interrupts 

    DCH0INTbits.CHDDIF=1; //1 = Channel Destination Pointer has reached end of destination (CHDPTR = CHDSIZ) 

    IPC9CLR=0x0000001f; // clear the DMA channel 0 priority and sub-priority 
    IPC9SET=0x00000016; // set IPL 5, sub-priority 2 
    IEC1SET=0x00010000; // enable DMA channel 0 interrupt 
    DCH0CONSET=0x80; // turn channel on 

} 

void main(){ 
    INTDisableInterrupts(); // disable interrupts before configuring ADC 
    initADC(); 
    initDMA(); 
    INTEnableSystemMultiVectoredInt(); // enable interrupts at CPU 

    while(1); 

} 
+0

question est assez détaillée, ce qui est bon, mais peut-être pourriez-vous donner un exemple réduit? Pouvez-vous éliminer le code inutile de l'exemple afin que nous ayons seulement à travailler avec le cas minime? http://sscce.org/ –

+0

je vous remercie pour vos commentaires. J'ai modifié le code source autant que possible. Il devrait compiler maintenant. – peet

Répondre

0

Il me semble que la question est que vous avez deux sources différentes qui essaient de consommer le vecteur d'interruption de l'ADC, le canal DMA et un ISR. D'après mon expérience, cela signifie qu'un seul des deux aura le vecteur d'interruption, et il a tendance à être l'ISR.

Je vous recommande de retirer l'ISR pour l'ADC. D'autant qu'il semble que vous ne faites que rétablir le drapeau d'interruption, mais il devrait être possible de configurer l'ADC pour réinitialiser automatiquement le drapeau et interrompre tous les échantillons (j'ai pu le faire sur le PIC32mx256f128B)