Перейти к содержанию
    

Запуск инжектированых каналов АЦП от события таймера на STM32

Мне нужно следить за состоянием двух аналоговых входов и при "резком" изменеии сигнала начать его обработку.

 

Частота опроса невысокая - пару сотен герц.

Я решил использовать инжектированые каналы, чтобы не программировать DMA.

 

Запуск АЦП по прерыванию таймера (переполенение) работает.

 

Решил запуск АЦП производить без участия процессора используя событие

"ADC_ExternalTrigInjecConv_T1_CC4"

 

Прерывание по окончанию обработки инжектированых каналдо не происходит.

 

Код настройки АЦП:

// Настроить АЦП для штатного съема данных с инжектирваными каналами
// Этот АЦП будет следить за входными сигналами с синхронного детектора
void start_work_sample(unsigned short target_freq)
{
  ADC_InitTypeDef ADC_InitStructure;
  
  RCC_ADCCLKConfig(RCC_PCLK2_Div6);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
  
  // ADC configuration
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 4; 
  ADC_Init(ADC3, &ADC_InitStructure);
  
  
   ADC_InjectedSequencerLengthConfig(ADC3, 2);
   ADC_InjectedChannelConfig(ADC3, ADC_X, 1,  DEFAULT_ADC_SAMPLE_TIME);
   ADC_InjectedChannelConfig(ADC3, ADC_Y, 2,  DEFAULT_ADC_SAMPLE_TIME);


  // калибровка
  ADC_Cmd(ADC3, ENABLE);

  ADC_ResetCalibration(ADC3);
   while(ADC_GetResetCalibrationStatus(ADC3));
  ADC_StartCalibration(ADC3);
   while(ADC_GetCalibrationStatus(ADC3));


  //Выключаем триггер.
ADC_ExternalTrigInjectedConvConfig(ADC3, ADC_ExternalTrigInjecConv_T1_CC4);

// Enable automatic injected conversion start after regular one 
ADC_AutoInjectedConvCmd(ADC1, ENABLE);

//Включили прерывания с инжекторного канала по окончании преобразования.
ADC_ITConfig(ADC3, ADC_IT_JEOC, ENABLE);

  // вычисляем коэффициенты для частоты оцифровки запускаем таймер
  unsigned short presc_value, half_period_value;
  
  calc_presc(target_freq, &presc_value, &half_period_value);
  main_met_det_timer_init(presc_value, half_period_value);
}
 

 

Код настройки таймера:

// Инициализация таймера управления АЦП для реальной работы детектора
void main_met_det_timer_init(int prescaller, int period)
{
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

  // Enable Timer1 clock and release reset
  RCC_APB1PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
  RCC_APB1PeriphResetCmd(RCC_APB2Periph_TIM1, DISABLE);
    
  TIM_InternalClockConfig(TIM1);

  // Time base configuration
  TIM_TimeBaseStructure.TIM_Prescaler = prescaller;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_Period = period*2 -1; // 0xFF; // 8 bit resolution
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

  
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputState_Disable;
  TIM_OCInitStructure.TIM_Pulse = period;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
  
  TIM_OC4Init(TIM1,&TIM_OCInitStructure);
  
  // Double buffered
  
  TIM_ARRPreloadConfig(TIM1, ENABLE);
  TIM1->CCR4 = period;
  
  // TIM counter enable
  TIM_Cmd(TIM1, ENABLE);

// TIM2->DIER |= TIM_DIER_UIE;    // прерывание по обновлению
//  NVIC_EnableIRQ(TIM2_IRQn);        // прерывание по таймеру2
//  NVIC_SetPriority(TIM2_IRQn, 1);    // приоритет 
}
 
Изменено пользователем haker_fox
Уточнил название темы, добавил теги, переместил в нужный раздел.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я не знаю этих библиотек, но насколько смог убедиться по F100 - должен быть включен выход таймера. То есть предположу, что в этой строке

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;
}

надо написать _Enable

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я не знаю этих библиотек, но насколько смог убедиться по F100 - должен быть включен выход таймера. То есть предположу, что в этой строкенадо написать _Enable

Подтверждаю, для запуска по CCx event должна быть включена и переключаться соответствующая нога.

Альтернативный вариант запуска - по событию TRGO event, оно происходит "внутри" таймера.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

должна быть включена и переключаться соответствующая нога.
Нет, физическую ногу подключать через соответствующую альтернативную функцию не обязательно, но вот выход модуля Capture должен быть включен.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я не знаю этих библиотек, но насколько смог убедиться по F100 - должен быть включен выход таймера. То есть предположу, что в этой строкенадо написать _Enable

 

Не помогло.

Выкрутился по другому.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В коде настройки АЦП не вижу строки

ADC_ExternalTrigInjectedConvEdgeConfig(ADC1, ADC_ExternalTrigInjecConvEdge_RisingFalling);

- именно она с параметром отличным от ADC_ExternalTrigInjecConvEdge_None

включает срабатывание АЦП по внешнему триггеру и тогда на F446 АЦП по ADC_ExternalTrigInjecConv_T3_CC2 у меня работает.

 

А вот по ADC_ExternalTrigInjecConv_T1_CC4 - ни в какую. Хотя в дебуге видно что CC4IF меняется, да и прерывание по нему срабатывает, а вот АЦП не запускается.

Хотя если сделать

TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

то один раз конверсия производилась.

 

Выкручиваться дополнительным таймером не хочется. Кто-нибудь с такой проблемой сталкивался?

 

Кстати да, по ADC_ExternalTrigInjecConv_T1_TRGO АЦП запускается. А оно всегда было по TIM_TRGOSource_Update, сейчас попробовал сделать TIM_TRGOSource_OC4Ref - тоже работает. Эффект как от ADC_ExternalTrigInjecConv_T1_CC4, но через TRGO. Странно что без TRGO не получается с первым таймером, а с третьим - получается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...