Отговори на тема  [ 2 мнения ] 
PIC32MX, ADC + DMA, на 2(като за начало) канала. 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Авг 23, 2005 11:02 am
Мнения: 3070
Местоположение: София
Мнение 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;
}


Пон Мар 20, 2017 12:27 am
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Авг 23, 2005 11:02 am
Мнения: 3070
Местоположение: София
Мнение 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, но това така и не успях да го подкарам.


Пон Мар 20, 2017 7:57 pm
Профил ICQ
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 2 мнения ] 

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 5 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни