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