roboforum.ru

Технический форум по робототехнике.

Дублирование данных STM32F4 ADC + DMA +TTRG

Дублирование данных STM32F4 ADC + DMA +TTRG

nixxon86 » 31 окт 2014, 00:24

Задача
Опрашивать 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


Rambler\'s Top100 Mail.ru counter