цифровая электроника
вычислительная техника
встраиваемые системы

 



Программный счетчик частоты высокого разрешения

Автор: Mike(admin) от 3-10-2014, 07:20

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


Программный счетчик частоты высокого разрешения

Представленный код реализует счетчик частоты на микроконтроллере atmega328p.



/*
timer1 представляет собой расширенный 32-разрядный регистр (16 бит аппаратн. + 16 бит программн.).
Далее fcpu – частота процессора, prescal – значение предделителя
Инкрементирование происходит один раз за:
1 / (fcpu / prescal) <=> prescal / fcpu
Таким образом, переполнение произойдет при:
2^16 * prescal / fcpu
При переполнении tim2 вызывается обработчик прерываний и сохраняет текущее значение tim1 в tim1_cur_counter.
Таким образом, значение tim1, проинтегрированное за весь период tim1
(tim1_ovf_counter * 2^16) + tim1_cur_counter.
timer1 представляет собой 8-разрядный счетчик, инкрементируемый передним фронтом входного сигнала.
*/
static volatile uint8_t tim2_ovf_counter;
static volatile uint8_t tim2_is_ovf;
static volatile uint16_t tim1_cur_counter;

ISR(TIMER2_OVF_vect)
{
  if ((tim2_ovf_counter--) == 0)
  {
    /* отключаем tim1 перед считыванием */
    TCCR1B = 0;
    tim1_cur_counter = TCNT1;

    /* отключаем tim2 */
    TCCR2B = 0;

    tim2_is_ovf = 1;
  }
}
static volatile uint8_t tim1_ovf_counter;

ISR(TIMER1_OVF_vect)
{
  ++tim1_ovf_counter;
}

static void hfc_start(void)
{
  /* разрешение: 1.907349 Гц на итакт */
  /* Максимальная частота fmax: 500 КГц */
  /* время определения: 0.524288 секунд */

  /* отключаем прерывания */
  TIMSK1 = 0;
  TIMSK2 = 0;

  /* обнуляем регистры */
  tim1_ovf_counter = 0;
  tim1_cur_counter = 0;
  tim2_is_ovf = 0;

  /* 0x100 переполнений заполнят 16 бит */
  tim2_ovf_counter = 0xff;

  /* настройка tim2
нормальный режим работы
предделитель 128
разрешаем прерывания по переполнению
*/
  TCNT2 = 0;
  TIMSK2 = 1 << 0;
  TCCR2A = 0;
  TCCR2B = 0;

  /* настройка tim1
вывод t1 (pd5) в качестве источника внешнего сигнала (передний фронт)
*/
  DDRD &= ~(1 << 5);
  TCNT1 = 0;
  TIMSK1 = 1 << 0;
  TCCR1A = 0;
  TCCR1B = 0;


  /* запуск tim1, tim2 */
  TCCR1B = 7 << 0;
  TCCR2B = 5 << 0;
}

static uint8_t hfc_poll(void)
{
  return tim2_is_ovf;
}

static uint32_t hfc_wait(void)
{
/*
Ожидаем переполнения tim1. Возвращаем результирующее значение
16-битного счетчика, которое должно быть умножено на разрешение
по частоте для того, чтобы получить действительное значение частоты.
*/
  while (tim2_is_ovf == 0) ;

  return ((uint32_t)tim1_ovf_counter << 16) | (uint32_t)tim1_cur_counter;
}

static inline uint32_t hfc_start_wait(void)
{
  hfc_start();
  return hfc_wait();
}

static inline double hfc_to_hz(uint32_t counter)
{
  return 1.907349 * (double)counter;
}





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

Комментарии:

Оставить комментарий