Опрашивать 13 каналов за 50 мкс STM32F4 и забирать данные через DMA (168 MHZ Core clock)
Использую регулярные каналы
На данный момент реализовано
TimerTriger
- Код: Выделить всё • Развернуть
 NVIC_InitTypeDef NVT;
 TIM_TimeBaseInitTypeDef T1;
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
 T1.TIM_ClockDivision = TIM_CKD_DIV4 ;//84/4 = 21mhz
 T1.TIM_CounterMode = TIM_CounterMode_Up;
 T1.TIM_Prescaler = 21 - 1;//1 * 10^6 tiks in second = 1 mhz = 1us;
 T1.TIM_Period = 50;// 50 * 10^6 tiks = 50 us ;
 TIM_TimeBaseInit(TIM3,&T1);
 TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
 
 TIM_SetCounter(TIM3, 0);
 TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_Update);
 TIM_Cmd(TIM3,ENABLE);
AЦП
- Код: Выделить всё • Развернуть
 ADC_InitTypeDef ADC_InitStruct;
 ADC_CommonInitTypeDef ADC_CommonInitStruct;
 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); // enable clocking of ADC1
 
 
 ADC_DeInit();
 ADC_CommonInitStruct.ADC_Mode =ADC_Mode_Independent;
 ADC_CommonInitStruct.ADC_Prescaler =ADC_Prescaler_Div8;
 ADC_CommonInitStruct.ADC_DMAAccessMode =ADC_DMAAccessMode_Disabled;
 ADC_CommonInitStruct.ADC_TwoSamplingDelay =ADC_TwoSamplingDelay_20Cycles;
 ADC_CommonInit(&ADC_CommonInitStruct);
 ADC_StructInit(&ADC_InitStruct);
 ADC_InitStruct.ADC_Resolution =ADC_Resolution_12b;
 ADC_InitStruct.ADC_ScanConvMode =ENABLE;
 ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;
 
 ADC_InitStruct.ADC_DataAlign =ADC_DataAlign_Right;;
 ADC_InitStruct.ADC_NbrOfConversion =13;
 ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;
 ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
 
 
 ADC_DiscModeCmd(ADC1,DISABLE);
 ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE);
 ADC_ITConfig(ADC1,ADC_IT_AWD|ADC_IT_JEOC| ADC_IT_OVR,DISABLE);
 ADC_Init(ADC1,&ADC_InitStruct);
 
DMA - Настройка
- Код: Выделить всё • Развернуть
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
 Interupt();
 DMA_InitTypeDef DMA_InitStructure;
 DMA_InitStructure.DMA_Channel = DMA_Channel_0;
 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&DozimetrP.CurrentPerChannel;
 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
 DMA_InitStructure.DMA_BufferSize = 13;
 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_Circular;
 DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh ;
 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_Stream4, &DMA_InitStructure);
 DMA_Cmd( DMA2_Stream4, ENABLE);
 
 DMA_ITConfig(DMA2_Stream4,DMA_IT_TC,ENABLE );
 DMA_ITConfig(DMA2_Stream4,DMA_IT_HT |DMA_IT_TE|DMA_IT_DME| DMA_IT_FE, DISABLE);
 ADC_EOCOnEachRegularChannelCmd(ADC1,DISABLE);//Прерывание после оцифровки всех каналов
 ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
 ADC_DMACmd(ADC1, ENABLE);
DMA - настройка прeываний
- Код: Выделить всё • Развернуть
- NVIC_InitTypeDef NVT;
 
 NVT.NVIC_IRQChannel = DMA2_Stream4_IRQn;
 NVT.NVIC_IRQChannelCmd = ENABLE;
 NVT.NVIC_IRQChannelPreemptionPriority = 1;
 NVT.NVIC_IRQChannelSubPriority = 1;
 NVIC_Init(&NVT);
Обработчик прерывания DMA
- Код: Выделить всё • Развернуть
- if(DMA_GetITStatus(DMA2_Stream4,DMA_IT_TCIF4)!= RESET)
 {
 {
 
 
 
 if(DMA_GetITStatus(DMA2_Stream4,DMA_IT_TCIF4)!= RESET)
 {
 DMA_ITConfig(DMA2_Stream4,DMA_IT_TC,DISABLE );
 DMA_ClearITPendingBit(DMA2_Stream4, DMA_IT_TCIF4);
 static uint16_t Counter;
 DozimetrP.SiMP_CurrentValue =DozimetrP. CurrentPerChannel[9];//Фильтр
 Counter++;
 // //Принудительный захват каналов
 if((DozimetrP.CurrentCommand == FORCE_START_STATIC & DozimetrP.CounterIt < 1024) || Triged == true )
 {Triged = false;
 if( Counter % DozimetrP.OcsParam.ScaleinPixels == 0)
 {
 
 for(int i = 0;i<13;i++)
 {
 DozimetrP.BufferSampler[i].Sample[DozimetrP.CounterIt] = DozimetrP.CurrentPerChannel[i];
 };
 DozimetrP.CounterIt++;
 GPIO_SetBits(GPIOB,GPIO_Pin_6);
 DozimetrP.StatState - InProgress;
 
 }
 }
 else
 {
 
 DozimetrP.CurrentCommand = RESERVED;
 DozimetrP.StatState = Complete;
 }
 
 DozimetrP.SiMP_CurrentValue_with_Filter = (9 * DozimetrP.SiMP_CurrentValue_with_Filter + DozimetrP.SiMP_CurrentValue)/10;
 //экспозиция
 if( DozimetrP.ExpParams.Expostate == InProgress && DozimetrP.ExpParams.ExpoWork == WORK )
 {
 DozimetrP.ExpParams.CountSamplers++;
 for(int i = 0;i<13;i++){
 DozimetrP.SummPerChannel[i] +=DozimetrP.CurrentPerChannel[i];
 }
 }
 
 // //Запуск статистики
 if(DozimetrP.OcsParam.OscState == InProgress && DozimetrP.StaticParams.WorkState == WORK)
 {
 DozimetrP.CounterIt++;
 if(DozimetrP.CounterIt < 1024 && DozimetrP.OcsParam.OscState != TimeOut ){
 DozimetrP.OcsParam.OscState = InProgress ;
 DozimetrP.StatState = InProgres;
 for(int i = 0;i<13;i++)
 {
 if( Counter % DozimetrP.OcsParam.ScaleinPixels == 0){
 DozimetrP.BufferSampler[i].Sample[DozimetrP.CounterIt] = DozimetrP.CurrentPerChannel[i];
 }
 }
 }
 if(DozimetrP.CounterIt == 1024 || DozimetrP.OcsParam.OscState == TimeOut && DozimetrP.StaticParams.WorkState == WORK )//Стоп по таймауту и итерациям
 {
 DozimetrP.OcsParam.OscState = Complete;
 DozimetrP.CounterIt = 0; }
 CheckStatisticTimeOut();
 }
 }
 DMA_ITConfig(DMA2_Stream4,DMA_IT_TC,ENABLE );
Пробовал проделывать тоже самое в прерывание(EOC) ADC результат все равно дублируются каждые 128 выборок
Настройка прерывания ADC
- Код: Выделить всё • Развернуть
- NVIC_InitTypeDef NVT;
 
 NVT.NVIC_IRQChannel = ADC_IRQn;
 NVT.NVIC_IRQChannelCmd = ENABLE;
 NVT.NVIC_IRQChannelPreemptionPriority = 0;
 NVT.NVIC_IRQChannelSubPriority = 0;
 NVIC_Init(&NVT);
Все делал на основе примеров STM32F4 Periph lib.
Вывод в фаил
https://drive.google.com/file/d/0B8cyNZDoDFf1UFkzVnFWWmNfQzQ/view?usp=sharing

