Частотомер до 1ГГц на STM32

Была необходимость померять частоту около 137МГц, частотомер на такую частоту найти не получилось, ну и решил я сваять свой частотомер с блекджеком и шлюхоми. Посёрфил по просторам интернета, ну типо изучил предметную область, мне подвернулась идея применить делитель частоты. Существует множество проектов измерения частоты на AVR и PIC, а вот на STM мне ни одного и не попалось. Почему я не взял PIC и не использовал готовый проект? Потому что нет отладчика для PIC, использую в основном STM, и есть на чём лепить и экспериментировать.

Делитель частоты

Микросхему для делителя частоты я выбрал из доступных на космодроме. Выбор пал на MC12080-D. Делитель серьёзный при желании можно накрутить коэффициент деления 80, но в этом нет необходимости так-как с увеличением коэффициента растет погрешность. Для наших целей вполне хватит 10. С выхода делителя контроллером так просто ничего не померяешь необходимо согласовывать уровни и приводить сигнал в нормальный вид, то есть в импульсы. Для решения этой проблемы использовал быстродействующий компаратор LMV7219. Чтобы всё вместе заработало, пришлось подстроить Vref опорное напряжение на компараторе, устанавливая это напряжение мы фактически меняем порог переглючения компаратора.

Схема делителя частоты

Диаграмму работы делителя я в даташите не нашёл, ну там ничего особого по приходу 10 импульсов на выходе формируется импульс.
На изображении приведена диаграмма работы компаратора, при достижении входным сигналом отметок Vtrip+ и Vtrip- компаратор переходит в состояние 1 или 0.
Временная диаграмма работы компаратора

Немного о таймерах STM

Я использовал STM32F103C4T6, у него на борту есть три таймера. Один таймер использовал для отсчёта временных интервалов и два таймера для подсчёта импульсов. TIM1 включил режиме мастера с внешним тактированием, TIM2 в режиме slave, тактирования по переполнению TIM1. Общий принцип работы такой, при приходе импульса на внешний вывод тактирования TIM1 он инкрементирует счётный регистр и достигнув значения регистра ARR, разрешает TIM2 инкрементировать свой счётный регистр.

Схема включения таймеров

Когда подключил делитель частоты, оказалось что, он вносит ошибку в измерения для устранения ошибки ввёл поправочный коэффициент, значение которого вычислил экспирементальным путём, измеряя частоту с делителем и без него.

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


 /*variable*/
  unsigned int f = 0;
  uint16_t pulse = 0, r = 0, j=0;
  
  /*const*/
  uint8_t correct = 1180;
  uint32_t arr = 50000;
     
  void InitTimer(void)
  {
      RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;  
      RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
      RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; 
      
      TIM1->SMCR &= ~TIM_SMCR_ETP;       // полярность сигнала, если ETR=0 то сигнал не инвертируется 
      TIM1->SMCR |= TIM_SMCR_ECE;        // Включить режим внешнего тактирования 
      TIM1->CR2 |= TIM_CR2_MMS_1;        // установка режима ведущего таймера
      TIM2->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1 | TIM_SMCR_SMS_2;    // перевести TIM2 в режим “External clock mode 1”
      TIM2->SMCR &= ~TIM_SMCR_ECE;       //Включить режим внешнего тактирования
      TIM1->CNT = 0;                     //Обнулить счётные регистры
      TIM2->CNT = 0;
      TIM1->ARR = 50000;                 //Значение до которого считает первый таймер
      TIM3->PSC	= 128000-1;              //Настраиваем  TIM3 на генерирование временных интервалов
      TIM3->ARR = 2000;                              
      TIM3->DIER = TIM_DIER_UIE;         //разрешить событие от таймера
      TIM2->CR1 = TIM_CR1_CEN;           //разрешаем счет  таймеров
      TIM3->CR1 = TIM_CR1_CEN | TIM_CR1_ARPE;   
      TIM1->CR1 = TIM_CR1_CEN; 
       NVIC_EnableIRQ (TIM3_IRQn);	     
      __enable_irq();	              
  }
  /*Обработчик прерывания*/
  void TIM3_IRQHandler(void)
  {
    if(TIM3->SR & TIM_SR_UIF)
    {
      TIM1->CR1 &= ~TIM_CR1_CEN;
      TIM3->CR1 &= ~TIM_CR1_CEN;
      pulse = TIM1->CNT; 
      r = TIM2->CNT;
      f = (pulse+(r*(correct+arr)));
      Nch_filtr(f);
      pulse = 0;
      f = 0;
      TIM2->CNT = 0;
      TIM1->CNT = 0;
      TIM3->CNT = 0;
      TIM3->SR &= ~TIM_SR_UIF;     
      TIM1->CR1 = TIM_CR1_CEN;
      TIM3->CR1 = TIM_CR1_CEN;
    }
  }
  /*Фильтр*/
  void Nch_filtr(int input_val)
  {
    static int sum_val, i = 0;
    sum_val = sum_val+input_val;
    i++;
    if(i>=3)
    {
      sum_val = sum_val/3;
      LCD_GOTO (16);
      printf ("F=             ");
      LCD_GOTO (19);
      printf ("%d",sum_val);
      i = 0;
      sum_val = 0;
    }
  }
">
  • +1
  • 25 ноября 2012, 13:45
  • sambist1

Комментарии (18)

RSS свернуть / развернуть
неплохо бы добавить описание работы схемы на первом рисунке. ну, хотя бы назначение микросхем
+4
Для полного и быстрого понимания, было бы очень полезно приложить к описанию графическое представление с временными интервалами описывающими принцип. ;) И хоть малейшую блок схему, что меряете и как.
Так как до конца ясен весь принцип, «кто кого тактирует и в какое место» :)
Что касается внешних делителей,… тема сисек не раскрыта тоже.
0
Нужно ведь иметь в виду, что входы таймеров микроконтроллера синхронизированы с тактовой частотой, даже если вход таймера соединён с выводом МК и подсчитывает внешние импульсы.

Схемы нет, даже схемы подвода считаемых импульсов на вход контроллера.
0
Да согласен насчет синхронизации, забыл упомянуть что контроллер работает на 128МГц, немного больше чем ему положено и тактирование таймера происходит с этойже частотой и если завести на частотомер частоту 1ГГц то на МК после делителя будет частота 100МГц. На МК сигнал подводим на вывод TIM1_ETR, в моём камне это 33 ножка.
0
Насколько я помню, таймеры в STM синхронные. Это означает, что даже если сделать тактирование от внешнего источника, все равно переключения будут происходить по сигналу внутреннего тактирования. То есть частота тактирования контроллера должна быть как минимум в 2 раза выше измеряемой частоты. И на частоте 128МГц можно померить только 64 мегагерца * 10 = 640 мегагерц.
0
По-уму, частота должна быть выше в 3 раза. На 2х погрешность измерения большая — пробовал.
0
А ещё нужно удостовериться, что частота кварца возбуждается именно на нужной частоте. Кварцы могут иметь разбросы частот, может возбуждаться и на других частотах. Это надо проверять.
0
Да проверял осциллографом, но чисто ради интереса я сомневаюсь что контроллёр позволит работать системе тактирования на второй или третей гармонике, скорей всего если такие попытки будут то HSE при инициализации вообще не запистится.
0
Внес некоторые корректив, вопервых поставил нормально тег кат, а то он у меня обзац вырезал и добавил диаграмму работы компаратора. И ещё вопросик, как добавить проект к топику, что-то я не разобрался.
0
Как добавить проект — we.easyelectronics.ru/page/about/.
Когда подключил делитель частоты, оказалось что, он вносит ошибку в измерения… посути берёт усреднённое значение нескольких измерений.
так хорошо все начиналось…
как прескаллер может вносить ошибку? это же цифровой делитель, он не может делить на 9.9999, например.
я так понял, измерение частоты выполняется примитивнейшим методом прямого счета — подсчет импульсов за определенный интервал времени?
Отсюда и погрешность.
0
Диаграмму работы делителя я в даташите не нашёл
Стандартная схема
0
Я о временной диаграмме.
0
Почему я не взял PIC и не использовал готовый проект? Потому что нет отладчика для PIC
Весьма странное заявление…

Чего там отлаживать — то?
Берете любой готовый частотомер на PIC (выбирая в основном по типу удобного для вас индикатора), их масса, все давно отлажены, проверены и повторены сотнями и тысячами человек. Без проблем меряют до 50-70МГц с разрешением до герца, погрешность — определяется только погрешностью использованного кварцевого резонатора (обычно порядка 5 знаков без термостата, 6 знаков — с термостатом и предварительной калибровкой).

Ставите на входе любой подходящий делитель (их сейчас полно, с верхней частотой от 300 до 1500 — 2500 МГц), и будет вам «щастье»…

Когда подключил делитель частоты, оказалось что, он вносит ошибку в измерения для устранения ошибки ввёл поправочный коэффициент, значение которого вычислил экспирементальным путём, измеряя частоту с делителем и без него.
Школьники называют это — «подогнать решение задачи под ответ»…
Не факт, что на других частотах результат тоже совпадет.
+1
  • avatar
  • SWG
  • 25 ноября 2012, 22:54
То что Вы советуете школьники называют списать. Молодец автор. Сделал сам.
На радиокоте разгорелась дискуссия — там разобран вариант как увеличить точность. Можете посмотреть и доработать свой частотомер.
Хорошо бы еще разобраться, что это за поправочный коэффициент и откуда он взялся ;)
0
ГГц это хорошо, а с помощью какой бы такой несложной приставкои — измерить длительность между единичным прямым и отраженным импульсом, и с точностью не хуже или около 10пС?
+1
  • avatar
  • valio
  • 10 февраля 2013, 17:01
Ты что, лазерный дальномер делаешь?) Хотя вопрос и меня интересует, да.
0
Это достаточно распространённая задача — например, измерять расстояние до обрыва линии связи
0
На PIC можно для этой цели использовать модуль CTMU. Насколько помню у них даже подобный пример есть.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.