Всем здрасте! Пришел наконец таки ко мне камень(STM32F205), вместо последнего спаленного, и возобновил я свои изыскания!
Соответственно запускаю блок ацп в интерливед трипл моде. Цель - получить частоту дискретизации 6МГц.
Практически все копирую из моего же примера для RegSimult mode, который работает замечательно. Делаю небольшие поправки в инициализации.
Дма пашет, АЦП преобразовывает. Значит получаю следующий дамп, подав на вход соответствующего канала питание. (тут разбито на 3 колонки так как 3 АЦП должны отрабатывать по очереди)
Как видно, верные значения, чередуются с неверными(подчеркнуто красным) попарно, кроме того, неверные значения повторяются (шумы в паре нижних бит имеются, что указывает на аналоговое происхождение ) от эксперимента к эксперименту и не зависят от поданного на вход сигнала, будь то GND или VCC. Собственно это и есть пункт моего недопонимания.
Если у кого есть мысли по поводу этой проблемы, пожалуйста - поделитесь!
А теперь собственно код:
Инициализация ПДП:
Код:
void dma_config_for_triple_ADC_mode(uint16_t buffsize)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
DMA_DeInit(DMA2_Stream0);
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &ADC->CDR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &adc_buffer[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = buffsize*3-2;//ARRAY_LENGHT(adc_buffer);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
DMA_Cmd(DMA2_Stream0, ENABLE);
}
DMA_InitStructure.DMA_BufferSize = buffsize*3-2; возможно подсказка к пониманию недуга.
В этой строчке -2 поставлено для синхронизации фазы верных/неверных значений от эксперимента к эксперименту. То есть, если поставить buffsize*3 как по идее и надо делать, то несмотря на перенициализацию АЦП и DMA фаза плывет.
Далее инициализация АЦП:
Код:
uint8_t ADC_config_TripleMode_Interl(int index)
{
uint8_t Channel; // index = 0 : ADC_in_6 ; PA6 // index = 1 : ADC_in_7 ; PA7
uint16_t Pin;
if (index==0) {
Channel = ADC_Channel_6;
Pin = GPIO_Pin_6;
} else if (index==1){
Channel = ADC_Channel_7;
Pin = GPIO_Pin_7;
} else return 0;
//настройка пинов АЦП
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); // а надо ли тактировать аналоговый вход???
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = Pin;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;
GPIO_Init(GPIOA, &GPIO_InitStruct);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3,ENABLE);
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Resolution = 12;
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //ENABLE; // пофиг как последовательность повторяется от 1 до 16 или 1долбит
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Init(ADC2, &ADC_InitStructure);
ADC_Init(ADC3, &ADC_InitStructure);
uint16_t i; //прописываем один и тот же канал во все 3 АЦП
for (i=1; i<17; i++) {
ADC_RegularChannelConfig( ADC1,Channel,i,ADC_SampleTime_15Cycles);//ADC_SampleTime_3Cycles (can be 15, 28, 56, 84, 112, 144, 480 cycles)
ADC_RegularChannelConfig( ADC2,Channel,i,ADC_SampleTime_15Cycles);//30mhz /15= 2mhz
ADC_RegularChannelConfig( ADC3,Channel,i,ADC_SampleTime_15Cycles);
};
// конфигурируем трипл мод
ADC_CommonInitTypeDef ADC_CommonStructure;
ADC_CommonStructure.ADC_Mode = ADC_TripleMode_Interl;
ADC_CommonStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; //Disabled,1,2,3
ADC_CommonStructure.ADC_Prescaler = ADC_Prescaler_Div2; //2,4,6,8 60mhz/2=30mhz
ADC_CommonStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_17Cycles; // опрос каждого АЦП через 15 циклов. Смещение между измерениями в каждом АЦП 5 циклов как раз
ADC_CommonInit(&ADC_CommonStructure);
ADC_DMARequestAfterLastTransferCmd(ADC1, DISABLE); // на всякий случай исключаем левые запросы
ADC_DMARequestAfterLastTransferCmd(ADC2, DISABLE); // хотя наверняка это делается автоматически на уровне железа.
ADC_DMARequestAfterLastTransferCmd(ADC3, DISABLE); //
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
return 0;
}
Ну и собственно сама процедура сбора окна данных:
Код:
void ADC_multi_test_TripleMode_Inter(void)
{
ADC_config_TripleMode_Interl(0);
dma_config_for_triple_ADC_mode(1024);
ADC_Cmd(ADC1, ENABLE);
ADC_Cmd(ADC2, ENABLE);
ADC_Cmd(ADC3, ENABLE);
ADCstate = 0; // сбрасывем флаг
ADC_SoftwareStartConv(ADC1);
while(DMA_GetCurrDataCounter(DMA2_Stream0)>0){
}; // так вот незатейливо ждем окончания ДМА
ADC_Cmd(ADC1, DISABLE); //экономим электричество
ADC_Cmd(ADC2, DISABLE);
ADC_Cmd(ADC3, DISABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, DISABLE);
}