STM32 - частотомер.

Кто любит RISC в жизни, заходим, не стесняемся.
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32 - частотомер.

Сообщение kybin »

Не знаю расчехлится ли кто-то после 2 с лишним лет. Вот код для STM32F0-Discovery. Яркий пример прямого счета (насколько я понял).
Прерывание срабатывает, когда на 1 из 4ёх входов таймера приходит передний фронт. И считается [частота сигнала] = [частота таймера] / [сколько натикало за 1 период]
Примитивно, но работает. Так же работает пример от ST Timer_PWM_Input_mode
Спойлер

Код: Выделить всё

// STM32 TIM2 4 Channel Input Capture STM32F0-Discovery - sourcer32@gmail.com
 
#include "stm32f0xx.h"
#include "stm32f0_discovery.h"
 
//**************************************************************************************
 
void TIM2_Config(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_ICInitTypeDef        TIM_ICInitStructure;
 
  /* TIM2 Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
 
  /* TIM2 Configuration */
  TIM_DeInit(TIM2);
 
  /* Time base configuration */
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / 1000000) - 1; // 1 MHz, from 48 MHz
  TIM_TimeBaseStructure.TIM_Period = 0xFFFFFFFF; // Maximal, TIM2 is 32-bit counter
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
 
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; // Rising/Falling/BothEdge
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICFilter = 0x0;
 
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
  TIM_ICInit(TIM2, &TIM_ICInitStructure);
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
  TIM_ICInit(TIM2, &TIM_ICInitStructure);
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
  TIM_ICInit(TIM2, &TIM_ICInitStructure);
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
  TIM_ICInit(TIM2, &TIM_ICInitStructure);
 
  /* TIM1 enable counter */
  TIM_Cmd(TIM2, ENABLE);
 
  /* Enable the CCx Interrupt Request */
  TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
}
 
//**************************************************************************************
 
volatile uint32_t Freq[4];
 
void TIM2_IRQHandler(void)
{
    uint32_t Current, Delta;
    static uint32_t Last[4];
     
  if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
    {
        /* Clear TIM2_CH1 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
 
        Current = TIM_GetCapture1(TIM2);
        Delta = Current - Last[0];
        Last[0] = Current;
        if (Delta)
            Freq[0] = 1000000 / Delta; // 1MHz clock
         
        // ..
    }
     
  if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)
    {
        /* Clear TIM2_CH2 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
 
        Current = TIM_GetCapture2(TIM2);
        Delta = Current - Last[1];
        Last[1] = Current;
        if (Delta)
            Freq[1] = 1000000 / Delta; // 1MHz clock
         
        // ..
    }
     
  if (TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET)
    {
        /* Clear TIM2_CH3 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);
 
        Current = TIM_GetCapture3(TIM2);
        Delta = Current - Last[2];
        Last[2] = Current;
        if (Delta)
            Freq[2] = 1000000 / Delta; // 1MHz clock
         
        // ..
    }
     
  if (TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET)
    {
        /* Clear TIM2_CH4 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC4);
 
        Current = TIM_GetCapture4(TIM2);
        Delta = Current - Last[3];
        Last[3] = Current;
        if (Delta)
            Freq[3] = 1000000 / Delta; // 1MHz clock
         
        // ..
    }
}
 
//**************************************************************************************
 
void NVIC_Config(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
 
  /* Enable and set TIM2 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}
 
//**************************************************************************************
 
void GPIO_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
 
  /* GPIOA Periph clock enable */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
 
  /* Configure TIM2 input */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
 
  /* Connect TIM pins to AF2 */
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_2); // TIM2_CH1 PA5
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_2); // TIM2_CH2 PA1
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_2); // TIM2_CH3 PA2
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_2); // TIM2_CH4 PA3
}
 
//**************************************************************************************
 
int main(void)
{
  NVIC_Config();
 
  GPIO_Config();
 
  TIM2_Config();
 
  while(1); /* Infinite loop */
}
взято тут

и вот еще очень хорошая статья
Последний раз редактировалось kybin Пн мар 17, 2014 14:21:19, всего редактировалось 2 раза.
Аватара пользователя
balmer
Это не хвост, это антенна
Сообщения: 1433
Зарегистрирован: Вс дек 02, 2012 03:13:48
Откуда: Калининград

Re: STM32 - частотомер.

Сообщение balmer »

У STM32F407 есть "3×12-bit, 2.4 MSPS A/D converters: up to 24 channels and 7.2 MSPS in triple interleaved mode", то есть скорости более чем достаточно для того, чтобы считывать сигнал частотой 100КГц. Тактовой частоты тоже более чем достаточно, чтобы обрабатывать этот сигнал в реальном времени.
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32 - частотомер.

Сообщение kybin »

по-моему АЦП тут ни к чему. У датчика меандр на выходе с переменной частотой.
Аватара пользователя
balmer
Это не хвост, это антенна
Сообщения: 1433
Зарегистрирован: Вс дек 02, 2012 03:13:48
Откуда: Калининград

Re: STM32 - частотомер.

Сообщение balmer »

Да, тогда вообще халява. Настроил таймер и снимай время от времени показания. :)
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: STM32 - частотомер.

Сообщение Леонид Иванович »

Какая там халява - если задача требует точного измерения частоты за короткий интервал времени, то здесь как раз место для Reciprocal Counting, но его для STM32 пока никто красиво не написал.
HHIMERA
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Re: STM32 - частотомер.

Сообщение HHIMERA »

И шо танцору так мешает??? Холст, краски и вперёд!!!
Назови причины невозможности "красивого" написания... слушаем...
"Я не даю готовых решений, я заставляю думать!"(С)
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Re: STM32 - частотомер.

Сообщение dosikus »

HHIMERA писал(а):Назови причины невозможности "красивого" написания... слушаем...


Дык , причина то одна - в SPL этого нету. :)))
Слизать то не у кого ...
HHIMERA
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Re: STM32 - частотомер.

Сообщение HHIMERA »

Дык... хочется услышать... "как танцор картины пишет"... чтобы от "красивого" сразу перейти к "прекрасному"...
"Я не даю готовых решений, я заставляю думать!"(С)
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32 - частотомер.

Сообщение kybin »

Леонид Иванович писал(а):Какая там халява - если задача требует точного измерения частоты за короткий интервал времени, то здесь как раз место для Reciprocal Counting
Я тоже так подумал.
Леонид Иванович писал(а):, но его для STM32 пока никто красиво не написал.
himera хвастал(а)сь.

Леонид Иванович, поделитесь методикой расчета точности.

В общем в процессе. Да, ничего особенно сложного, если почитать Ref.manual. И уже считает.
Кварц у контроллера 8 МГц (нестабильность +-50ppm). Внутри частота умножается до 168 МГц. Там свои ppm'ы. Вопрос: может стоит использовать внешнее тактирование для таймера? Там есть такая возможность (ETR).
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Re: STM32 - частотомер.

Сообщение dosikus »

kybin, HHIMERA не хвастался - он сделал ... :)))
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32 - частотомер.

Сообщение kybin »

dosikus писал(а):kybin, HHIMERA не хвастался - он сделал и работает...

Где? Ты видел?
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Re: STM32 - частотомер.

Сообщение dosikus »

И не только видел . :)))
Сам частотомер на 103 , выхлоп 130МГц с F4 дискавери с MCO ...

Изображение
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32 - частотомер.

Сообщение kybin »

молодцы. И какая у вас точность получилась?
Вы могли бы выложить код.

upd: вижу точность=2E-5. или 0,002% Круто! Даже очень. Это если генератор брать за чистую монету
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: STM32 - частотомер.

Сообщение Леонид Иванович »

HHIMERA писал(а):Назови причины невозможности "красивого" написания... слушаем...


Причина проста. У меня не хватает мозгов такое написать.

kybin писал(а):Да, ничего особенно сложного, если почитать Ref.manual. И уже считает.


Вы уже реализовали Reciprocal Counting? Как Вам это удалось?

kybin писал(а):Кварц у контроллера 8 МГц (нестабильность +-50ppm). Внутри частота умножается до 168 МГц. Там свои ppm'ы. Вопрос: может стоит использовать внешнее тактирование для таймера? Там есть такая возможность (ETR).


PLL дает повышенный фазовый шум, но среднее значение частоты погрешности практически не имеет. Чувствительность частотомера к фазовому шуму обратно пропорциональна интервалу измерения. В общем случае, конечно, лучше обойтись без PLL. Но можно работать и с ней. Другое дело, что обычный кварц в качестве опорного генератора подходит плохо. Нужно взять хотя бы TCXO для тактирования процессора. Внешнее тактирование таймеров не знаю, получится ли применить в таком алгоритме счета. Что касается погрешности, то для метода Reciprocal Counting относительная погрешность не зависит от частоты и равна 1 / (Tизм * Fref), плюс погрешность опорного генератора. Если нужен хороший частотомер, то вряд ли стоит тратить силы по натягиванию этой задачи на STM32, проще взять ПЛИС и на ней сделать всё как надо.
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32 - частотомер.

Сообщение kybin »

Вы уже реализовали Reciprocal Counting? Как Вам это удалось?

В процессе. Технически это возможно. Будет результат отпишусь. А Ххимера сделал. Точный? - достаточно. Жаль делиться не хочет.

Меня беспокоит маленькое время измерения. Но мои первые опыты более-менее. Наверняка ПЛИС будет лучше... Лучше обойтись.
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: STM32 - частотомер.

Сообщение Леонид Иванович »

Если измерительный интервал равен 100 мкс, то при опорной частоте 168 МГц получается относительная погрешность измерения около 0.006%. Конечно, при условии, что удастся реализовать на STM32 метод Reciprocal Counting.
HHIMERA
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Re: STM32 - частотомер.

Сообщение HHIMERA »

kybin писал(а):Жаль делиться не хочет.

Да чем там делиться... чем??? Там инит двух таймеров... в теме всё расписано... дальше чисто формула...
Ну лень мне рыться в своей "помойке"... проверять в железе... править что-то... неинтересно уже...
Всё работает... чтобы там ЛИ не говорил... Работает и на STM32 и на STM8L... и даже на STM8S903...
Я не делал частотомер... я просто проверил идею, возможность... суть Reciprocal Counting... и просто развеял миф что "сделать нельзя"...
"Я не даю готовых решений, я заставляю думать!"(С)
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32 - частотомер.

Сообщение kybin »

Леонид Иванович писал(а):Вы уже реализовали Reciprocal Counting? Как Вам это удалось?.
Да. :music:
И мне не лень будет это выложить и расписать по полочкам. Чтоб и ламеру ясно было :)
Кстати считает хорошо. Хотя возможно баги еще вылезут..
kybin
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Пн мар 17, 2014 10:37:29

Re: STM32 - частотомер.

Сообщение kybin »

Дальнейшее обсуждение переношу в новую тему.
Chettuser

Re: STM32 - частотомер.

Сообщение Chettuser »

[uquote="HHIMERA",url="/forum/viewtopic.php?p=1459610#p1459610"]TIM1 в режиме Master выдавал секундные импульсы на TIM2, который был настроен как Slave mode: External Clock mode 2 + gated mode... TIM2 осуществлял подсчёт импульсов по входу ETR...
В принципе... и всё... Ничего сложного там нет...[/uquote]
А для меня вот непонятно - как настроить одновременно ETR и gate mode? Бит SMS регистра SMCR сделать этого не даст, как я понял это тупо мультиплексор:
Изображение
Автору топика черкнул, но боюсь он уже здесь не появится.
Ответить

Вернуться в «ARM»