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

STM32F103C8T6, АЦП, DMA и таймер

Привет всем.

Пытаюсь оцифровать этим процом переменку из розетки (т.е. просто сделать вольтметр).

Перед тем как попасть в проц, переменка проходит через обычный транс от БП (для развязки), потенциометр для подгонки по диапазон, поднимается на 1.5в вверх, чтобы измерять обе полуволны, а не одну.

О том, зачем так сложно, прошу не задумываться, это часть более сложной конструкции.

 

Виртуальная земля и синусоида из розетки цифруются АЦП проца+таймер+DMA. Эта связка отлажена и работает.

 

АЦП запускаю по Timer 2 CC2 event:

    // ADC1 configuration ------------------------------------------------------
    ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;            // -> CR1 | 0x00060000
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;    // T2, канал 2 --> CR2
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = 2;            // --> ADCx->SQR1
    ADC_Init ( ADC1, &ADC_InitStructure );

 

Настройка таймера TIM2, CCR2:

   /* TIM2 configuration ------------------------------------------------------*/
   // Time Base configuration
   // TIM2 - APB1, 72MHz
   // Ft = Fapb1/(PSC+1) = 72E6/(PSC+1) = 72E6/1800=40000
   TIM_TimeBaseStructInit ( &TIM_TimeBaseStructure );
   TIM_TimeBaseStructure.TIM_Period = 20-1;               // -> ARR - До этого значения считает таймер
   TIM_TimeBaseStructure.TIM_Prescaler = 1800-1;               // -> PSC - делитель частоты шины, Ft = 40kHz
   TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;            //
   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
   TIM_TimeBaseInit ( TIM2, &TIM_TimeBaseStructure );

   // TIM1 channel1 configuration in PWM mode
   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
   TIM_OCInitStructure.TIM_Pulse = 10;                     // CCR2
   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
   TIM_OC2Init ( TIM2, &TIM_OCInitStructure );

 

DMA не привожу, там проблем вроде не заметил.

Проблема только лишь в том, что я планировал получить в буфере не 2 периода частоты 50 Гц, а 20 :biggrin: График из экселя приложил.

 

по моим подсчётам частота запуска АЦП должна быть 40кГц/AAR = 40kHz/2 = 2КГц, но в буфере я вижу 2 периода входной частоты 50 Гц.

Буфер - 1000 значений.

Почему 2, я понять не могу. 2кГц = 2000 значений в секунду, в буфере 1000 значений за 0.5 сек. Это должно быть 500ms/20ms=25 периодов.

Почему у меня их 2? В чём я ошибаюсь?

Что самое интересное, что ради экперимента я пытался пихать в ARR и PSC разные числа - по фигу совершенно, там всегда 2 периода!

 

Сижу над этим уже 3 дня, не могу понять :crying: :smile3046:

В эррате ничего путного не нашёл.

 

Спасибо.

 

PS. Про странную форму графика с какими-то разрывами я уж молчу.

post-7980-1487262236_thumb.png

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


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

Что с тактированием АЦП? Может вы его тактируете настолько медленно, а длительность выборки сделали настолько большой, что АЦП просто не успевает сделать требуемое количество преобразований?

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


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

А что второй канал второго таймера от которого АЦП запускается никак конфигурировать не нужно? Или здесь не вся инициализация? АЦП то запускается не по переполнению таймера, а по событию от второго канала захвата/сравнения.

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


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

Советую сделать для начала без DMA, по прерыванию EOC, и включить останов таймера при входе в отладчик, так гораздо понятнее станет, что происходит.

А, я не знаток Хала, но вы вроде врубили Continuous mode, поэтому АЦП после запуска всегда будет дубасить на максимальной скорости, игнорируя таймер.

Изменено пользователем Timmy

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


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

А, я не знаток Хала, но вы вроде врубили Continuous mode, поэтому АЦП после запуска всегда будет дубасить на максимальной скорости, игнорируя таймер.
:-) Это не HAL это SPL. Но написали вы похоже верно. У меня в ADC+TIM+DMA указано ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

Чтобы узнать реальную частоту таймера я включал прерывания от него и там дергал GPIO.

Еще когда разбирался в работе DMA по точкам останова были непонятные для меня вещи. Причина их была похоже в том что таймер или DMA не сразу останавливались или вовсе не останавливались. В итоге пока данные в дебаггере обновлялись в буфере DMA уже были нащелканы новые данные.

Еще заметил отличие. У меня ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; Сейчас понятия не имею что это значит. У меня было 16 входов АЦП.

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


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

Еще заметил отличие. У меня ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; Сейчас понятия не имею что это значит. У меня было 16 входов АЦП.
Действительно, ТСу тоже надо поставить Independent, это значит, что два АЦП будут работать независимо.

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


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

Чтобы узнать реальную частоту таймера я включал прерывания от него и там дергал GPIO.

Логичнее вывести сигнал напрямую без всяких прерываний через блок сравнения 2, который собственно и запускает АЦП, правда вывести можно не на любой вывод.

 

Действительно, ТСу тоже надо поставить Independent, это значит, что два АЦП будут работать независимо.

Подозреваю, что два АЦП используются для одновременного измерения напряжения и тока, потом считается мощность :) Насколько это корректно сделано не подскажу, ибо всеми этими HALами, SPLами не пользуюсь - напрямую с регистрами проще и понятнее все выходит.

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


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

Сижу над этим уже 3 дня, не могу понять :crying: :smile3046:

PS. Про странную форму графика с какими-то разрывами я уж молчу.

 

Таймер запускает АЦП, который работает до заполнения массива по ДМА уже со своей тактовой частотой, которую Вы должны были выбрать сами. Можно еще время выборки менять...

Если ДМА работает по кругу, то легко объяснить Ваш чудный график.

Что Вы хотели-то?

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


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

вот это

ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

полностью решило проблему, в буфере сразу появилась куча периодов.

Видимо я загнался, глядя в кучу примеров :rolleyes: .

 

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; - по-моему не надо, у меня ж регулярная группа каналов.

 

Подозреваю, что два АЦП используются для одновременного измерения напряжения и тока, потом считается мощность :) Насколько это корректно сделано не подскажу, ибо всеми этими HALами, SPLами не пользуюсь - напрямую с регистрами проще и понятнее все выходит.

Да, совершенно верно. У меня ещё 2 канала тока есть в схеме - всего 4 канала АЦП. Я их просто пока не опрашивал вообще. Чтобы не усложнять картину.

на SPL писал, т.к. подсматривал конфигурацию в старых некубовых примерах от ST.

Может и натравлю на них второй АЦП, не знаю как получится.

 

Сейчас ими и буду заниматься.

 

Спасибо всем большое.

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


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

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; - по-моему не надо, у меня ж регулярная группа каналов.

 

Да, совершенно верно. У меня ещё 2 канала тока есть в схеме - всего 4 канала АЦП. Я их просто пока не опрашивал вообще. Чтобы не усложнять картину.

на SPL писал, т.к. подсматривал конфигурацию в старых некубовых примерах от ST.

Может и натравлю на них второй АЦП, не знаю как получится.

ADC_Mode_Independent - это нужно или не нужно - Вам решать. Там есть такая мода - два АЦП срабатывают почти одновременно с регулируемой задержкой (минимум - полтакта). И ДМА может сразу писать это в один массив.

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


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

ADC_Mode_Independent - это нужно или не нужно - Вам решать. Там есть такая мода - два АЦП срабатывают почти одновременно с регулируемой задержкой (минимум - полтакта). И ДМА может сразу писать это в один массив.

 

Да, спасибо, если я решу ток вторым АЦП измерять, это очень пригодится.

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


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

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

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

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

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

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

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

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

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

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