Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

PIC32MX, ADC + DMA, на 2(като за начало) канала.
http://mcu-bg.com/mcu_site/viewtopic.php?f=3&t=15143
Страница 1 от 1

Автор:  sparkybg [ Пон Мар 20, 2017 1:27 am ]
Заглавие:  PIC32MX, ADC + DMA, на 2(като за начало) канала.

PIC32MX, ADC + DMA, на 2(като за начало) канала.

Някой да е боричкал това? Трябва да чета примерно по 200 семпъла от 2 аналогови канала, в 2 различни буфера. Опитвам се да конфигурирам 2 DMA канала, единия четящ ADCBUFF0, другия ADCBUFF1, като 2-те DMA-та се задействат от IRQ-то на ADC-то, което съм сетнал да цъка прекъсване на всеки 2 семпъла.

- ако отворя ADC-тата стандартно, (без чейнинг и със native приоритети), всеки 2 съседни семпъла в буфера са еднакви и на двата канала. (в смисъл - двата канала са с отделни стойности, но в буфера на всеки от двта канала стойността се променя на всеки втори семпъл)
- ако променя приоритета на някое ADC към по-висок, без да правя нищо друго, него започва да го чете нормално, а другия си остава по стария начин.
- опитвам се да ги "чейнна", ама резултата е нулев - пак ги чете по 2 пъти и нищо не се променя.

PIC32MX564F128H е конкретния чип.

Ей това му е инициализацията в момента. Така и двата кенала са с двойни семпли:
Код:
void mcuADCStartAuto(){
    mcuADCStop();
    DmaChnDisable(DMA_CHANNEL0);
    DmaChnDisable(DMA_CHANNEL1);

    DmaChnOpen(DMA_CHANNEL0,DMA_CHN_PRI0, DMA_OPEN_DEFAULT);
    DmaChnSetEventControl(DMA_CHANNEL0, DMA_EV_START_IRQ_EN | DMA_EV_START_IRQ(_ADC_IRQ));
    DmaChnSetTxfer(DMA_CHANNEL0,(void*)&ADC1BUF0,(void*)VBuff,4,sizeof(VBuff),4);
    DmaChnWriteEvEnableFlags(DMA_CHANNEL0, 0);
    DmaChnEnable(DMA_CHANNEL0);

    DmaChnOpen(DMA_CHANNEL1,DMA_CHN_PRI0, DMA_OPEN_DEFAULT);
    DmaChnSetEventControl(DMA_CHANNEL1, DMA_EV_START_IRQ_EN | DMA_EV_START_IRQ(_ADC_IRQ));
    DmaChnSetTxfer(DMA_CHANNEL1,(void*)&ADC1BUF1,(void*)IBuff,4,sizeof(IBuff),4);
    DmaChnWriteEvEnableFlags(DMA_CHANNEL1, 0);
    DmaChnEnable(DMA_CHANNEL1);

    SetChanADC10(ADCH_VIN);// | (ADCH_VSHUNT<<8));
    OpenADC10(\
            ADC_MODULE_ON | ADC_IDLE_STOP | ADC_FORMAT_INTG32 | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON | ADC_SAMP_ON , \
            ADC_VREF_EXT_EXT | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_2 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF, \
            ADC_SAMPLE_TIME_31 | ADC_CONV_CLK_PB | ADC_CONV_CLK_63Tcy2, \
            ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN14_ANA, \
            SKIP_SCAN_ALL ^ (ADCH_VIN_SCAN | ADCH_VSHUNT_SCAN));
    AD1CON1bits.CLRASAM = 0;
    ADCAuto = 1;
}

Автор:  sparkybg [ Пон Мар 20, 2017 8:57 pm ]
Заглавие:  Re: PIC32MX, ADC + DMA, на 2(като за начало) канала.

Излъгах го. Понеже интеръпта на ADC-то е "persistent", тоест флага е вдигнат докато не се прочетат всички данни, DMA-то се шашкаше и четеше двойно, а именно:

1. ADC-то прочита 2 семпъла и вдига флага
2. DMA0 прочита семпъла от ADCBUF0, ама флага си остава вдигнат, и си записва следващ ивент.
3. DMA1 прочита семпъла от ADCBUF1, и флага на ADC-то пада
4. DMA0 прочита втори път ADCBUF0, щото си е записало ивента докато DMA1 чете.

при следващото четене наред е DMA1, и горното се повтаря в огледален ред.

Като забелязах че като вдигна приоритета на даден канал, той започва да се чете нормално, го 'лъзнах по следния начин:
Код:
    mcuADCStop();
    DmaChnOpen(DMA_CHANNEL0,DMA_CHN_PRI1, DMA_OPEN_DEFAULT);
    DmaChnSetEventControl(DMA_CHANNEL0, DMA_EV_START_IRQ_EN | DMA_EV_START_IRQ(_ADC_IRQ));
    DmaChnSetTxfer(DMA_CHANNEL0,(void*)&ADC1BUF0,(void*)VBuff,4,sizeof(VBuff),2);
    DmaChnWriteEvEnableFlags(DMA_CHANNEL0, DMA_EV_CELL_DONE);
    DmaChnEnable(DMA_CHANNEL0);

    DmaChnOpen(DMA_CHANNEL1,DMA_CHN_PRI0, DMA_OPEN_DEFAULT);
    DmaChnSetEventControl(DMA_CHANNEL1, DMA_EV_START_IRQ_EN | DMA_EV_START_IRQ(_ADC_IRQ));
    DmaChnSetTxfer(DMA_CHANNEL1,(void*)&ADC1BUF1,(void*)IBuff,4,sizeof(IBuff),4);
    DmaChnWriteEvEnableFlags(DMA_CHANNEL1, 0);
    DmaChnEnable(DMA_CHANNEL1);

    SetChanADC10(ADCH_VIN);// | (ADCH_VSHUNT<<8));
    OpenADC10(\
            ADC_MODULE_ON | ADC_IDLE_STOP | ADC_FORMAT_INTG32 | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON | ADC_SAMP_ON , \
            ADC_VREF_EXT_EXT | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_2 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF, \
            ADC_SAMPLE_TIME_31 | ADC_CONV_CLK_PB | ADC_CONV_CLK_35Tcy2, \
            ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN14_ANA, \
            SKIP_SCAN_ALL ^ (ADCH_VIN_SCAN | ADCH_VSHUNT_SCAN));
    AD1CON1bits.CLRASAM = 0;


А именно - зададох приоритет на първи канал по-висок от естествения, и вместо това му сложих дължина на cell трансфера 2 вместо 4. И поне доколкото мопга да преценя се случва следното:

1. ADC-то чете 2 семпъла и вдига флага.
2. DMA0 прочита 2 байта от общо четирите на ADCBUF0, това обаче е достатъчно за да укаже на ADC-то че ADCBUF0 е прочетен. Флага обаче остава вдигнат заради все още непрочетения ADCBUF1
3. DMA1 прочита 4-те байта от ADCBUF1, ADC-то сваля флага.
4. DMA0, понеже си е записало ивента, прочите останалите 2 байта от 4-те

При следващ ивент от ADC-то обаче, понеже сум сложил приоритет на DMA0, първо започва да чете той, вместо DMA1 и горното се повратя в съшия ред, вместо огледален.

Сега ще видя дали ще мога да го излъжа за 3 канала.

Дано някому е полезно. Из форумите се мъдрят разни писания за chaining, но това така и не успях да го подкарам.

Страница 1 от 1 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/