2015-03-06 12 views
1

Я пытаюсь сделать небольшое приложение на pic32mx795f512l, но я не могу заставить его работать. Что я хочу достичь, так это то, что adc непрерывно получает текущее аналоговое значение с канала 0 с максимально возможной скоростью. Если буфер 16 Word заполнен, он должен заставить dma сохранить этот буфер в ram. Dma должен инициировать прерывание, если буфер буфера заполнен. Поэтому я мог бы начать вычисление в основном цикле. Моя проблема в том, что dma не запускается вообще. Когда я включаю прерывание на adc, основной цикл не запускается. Кто-нибудь знает, что я сделал неправильно? Вот мой исходный код:PIC32MX dma не запускается 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

Ваш вопрос довольно подробный, что хорошо, но, возможно, вы могли бы предоставить приведенный пример? Можете ли вы устранить ненужный код из примера, так что нам нужно работать с минимальным случаем? http://sscce.org/ –

+0

Благодарим вас за отзыв. Я отредактировал исходный код столько, сколько смогу. Он должен скомпилироваться сейчас. – peet

ответ

0

Мне кажется, что проблема в том, что у вас есть два различных источников, которые пытаются поглотить вектор прерывания от АЦП, как канал DMA и ISR.

Из моего опыта это означает, что только один из двух получит вектор прерывания, и он имеет тенденцию быть ISR.

Я рекомендую удалить ISR для АЦП. Тем более, что кажется, что вы только перезапускаете флаг прерывания, но при этом необходимо настроить АЦП для автоматического сброса флага и прервать каждое количество выборок (я смог сделать это на PIC32mx256f128B)