Импровизированный частотомер из контроллера PLL

Когда-то я описывал простенький измерятор LC. Вот ещё один «приборчик» из этой серии.

Первый запуск)

Он неточен, неудобен и небыстр, зато неспешно собирается из подручных деталек за пол часика)

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


В основе «прибора» — микросхемка LM7001. Вот её краткое описание.

LM7001 — контроллер PLL, предназначеный для синтезаторов частоты радиовещательных приёмников.

Микросхемку можно найти на платах от музыкальных центров, автомагнитол и прочего хлама. Можно и купить — она достаточно распространённая и недорогая.

Блок-схема LM7001

Точного принципа работы микросхемки я не знаю. В общих словах — высокочастотный сигнал с гетеродина приёмника усиливается, подаётся на 14-разрядный счётчик — делитель частоты. Полученная частота сравнивается с образцовой. Разностные импульсы подаются на выход микросхемки. Если входная частота выше образцовой, сдвиг фазы будет увеличиваться и коэффициент заполнения выходных импульсов — расти, чем больше различаются частоты — тем быстрее. Если входная частота ниже образцовой — всё наоборот. Разностные импульсы пропускаются через активный ФНЧ и полученное напряжение используется для подстройки гетеродина. За счёт стабилизированной кварцем образцовой частоты, подстройка гетеродина получается очень точной.

Для нашего девайса важна парочка особенностей работы этой микросхемки — во-первых, сравнение частот всегда происходит корректно, проще говоря, за счёт хитрого частотно-фазового детектора, микросхемка никогда не спутает 1 МГц, 2 МГц и 4 МГц. Во-вторых, даже если при изменении управляющего напряжения на выходе фильтра, входная частота не изменится, управляющее напряжение дойдёт до уровня насыщения и «остановится».

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

Схемка показометра

В микросхемку встроен 24-битный сдвиговый регистр, загружаемый по трёхпроводной последовательной шине. При загрузке регистра нужно «поднять» линию CE, данные записываются по нарастанию на линии CL.

Регистр LM7001

D0-D13 — коэффициент, на который делится входная частота.
R0-R2 — выбор образцовой частоты.
S — выбор входа AMin (при S = 0) или FMin (при S = 1), я использовал только вход FMin.

Значение, с которым мы сравниваем нашу входную частоту — это образцовая частота, устанавливаемая битами R0-R2, умноженная на коэффициент деления входной частоты, устанавливаемый битами D0-D13.

Так что, если мы выставим значение выше входной частоты — через некоторое время получим единичку на ножке PD2 контроллера, если же выставим ниже — то нолик.

Чем ниже образцовая частота (которая по задумке разработчиков микросхемки отвечала бы за шаг настройки приёмника), тем точнее мы сможем выставить значение для сравнения. Но, поскольку делитель всего лишь 14-битный, то, например, при образцовой частоте в 1 кГц, максимальная частота, которую мы сможем выбрать — 16,383 МГц. Чем выше измеряемая частота, тем больший шаг получаем…

// максимально возможная входная частота для каждого делителя опорной частоты
#define MAX_FREQ_7200  (uint32_t)((uint64_t)LM7001_XTAL * 16383 / 7200)
#define MAX_FREQ_1440  (uint32_t)((uint64_t)LM7001_XTAL * 16383 / 1440)
#define MAX_FREQ_800   (uint32_t)((uint64_t)LM7001_XTAL * 16383 / 800)
#define MAX_FREQ_720   (uint32_t)((uint64_t)LM7001_XTAL * 16383 / 720)
#define MAX_FREQ_288   (uint32_t)((uint64_t)LM7001_XTAL * 16383 / 288)
#define MAX_FREQ_144   (uint32_t)((uint64_t)LM7001_XTAL * 16383 / 144)
#define MAX_FREQ_72    (uint32_t)((uint64_t)LM7001_XTAL * 16383 / 72)

// установка частоты для сравнения
void set_lm7001_freq(uint32_t freq)
{
    uint32_t ref_freq;
    int divisor;
    uint8_t flags = LM7001_S;

    if(freq <= MAX_FREQ_7200) {
        ref_freq = LM7001_XTAL / 7200;
        flags |= LM7001_REF_7200;
    } else if(freq <= MAX_FREQ_1440) {
        ref_freq = LM7001_XTAL / 1440;
        flags |= LM7001_REF_1440;
    } else if(freq <= MAX_FREQ_800) {
        ref_freq = LM7001_XTAL / 800;
        flags |= LM7001_REF_800;
    } else if(freq <= MAX_FREQ_720) {
        ref_freq = LM7001_XTAL / 720;
        flags |= LM7001_REF_720;
    } else if(freq <= MAX_FREQ_288) {
        ref_freq = LM7001_XTAL / 288;
        flags |= LM7001_REF_288;
    } else if(freq <= MAX_FREQ_144) {
        ref_freq = LM7001_XTAL / 144;
        flags |= LM7001_REF_144;
    } else {
        ref_freq = LM7001_XTAL / 72;
        flags |= LM7001_REF_72;
    }

    divisor = freq / ref_freq;
    lm7001_write(divisor, flags);
}

Значение с ножки PD2 я читаю трижды, с небольшой задержкой, с мажорированием — на всякий случай.

uint8_t sample_test_pin()
{
    uint8_t n = 0;
    
    if(TEST_PIN & TEST_BIT)
        n++;
    _delay_ms(5);
    if(TEST_PIN & TEST_BIT)
        n++;
    _delay_ms(15);
    if(TEST_PIN & TEST_BIT)
        n++;
    return (n >= 2);
}

Кроме того — уровень на ножке PD2 устанавливается не мгновенно — тем медленней, чем меньше отличается «загаданная» частота от настоящей входной. При различии в килогерц это может занять пару секунд. Чтобы ускорить сравнение частоты, я решил провести два дополнительных сравнения на небольшом расстоянии от основной точки. Если эта точка окажется близкой к входной частоте и уровень на ножке PD2 установиться не успеет — две дополнительные точки должны оказаться на достаточном расстоянии от входной частоты, и сравнение в них пройдёт правильно. При этом результат сравнения в них окажется различным, что будет означать — нужно провести сравнение в основной точке с достаточной задержкой.

window — это просто ширина диапазона, в котором мы ищем частоту.

int8_t compare_freq(uint32_t freq, uint32_t window)
{
    uint8_t a, b, c;

    if(window >= 20000UL) {
        if(window >= 50000UL) {
            set_lm7001_freq(freq - 15000);
            _delay_ms(100);
            a = sample_test_pin();
            set_lm7001_freq(freq);
            _delay_ms(100);
            b = sample_test_pin();
            set_lm7001_freq(freq + 15000);
            _delay_ms(100);
            c = sample_test_pin();
        } else {
            set_lm7001_freq(freq - 5000);
            _delay_ms(500);
            a = sample_test_pin();
            set_lm7001_freq(freq);
            _delay_ms(500);
            b = sample_test_pin();
            set_lm7001_freq(freq + 5000);
            _delay_ms(500);
            c = sample_test_pin();
        }
        if(a == b && b == c) {
            return (a ? 1 : -1);
        }
    }

    set_lm7001_freq(freq);
    _delay_ms(3500);
    return (sample_test_pin() ? 1 : -1);
}

Сама процедура измерения.

uint32_t measure()
{
	uint8_t pass_count = 16;
	uint32_t up = 200e6;
	uint32_t down = 500000;
	uint32_t freq;
	int8_t result;

	lcd_goto(0, 1);
	lcd_print("                ");

	lcd_goto(0, 1);

	// under
	if(compare_freq(down, up - down) > 0)
		return 0;

	// over
	if(compare_freq(up, up - down) < 0)
		return 0xffffffff;

	while(pass_count--) {
		freq = (up + down) / 2;
		result = compare_freq(freq, up - down);

		if(result > 0)
			up = freq;
		else
			down = freq;

		lcd_print("#");
	}

	return (up + down) / 2;
}

Измерение может занять секунд 30, так что в нижней строчке рисуется прогрессбар из «решёточек».

Девайс может быть полезен, например, для проверки радиомикрофончиков, гетеродинов приёмников.

Испытание  с радиомикрофончиком

Подвернулся под руку этот радиомикрофончик. Справа — контрольный приёмник, принимающий от него сигнал. Частоту я мерял на эмиттере транзистора модулятора (он через резистор подключен к земле).

По даташиту LM7001, полоса пропускания по входу FMin — от 5 до 130 МГц. Но микросхемка спокойно работает и в приёмниках двухметрового радиолюбительского диапазона — 144-146 МГц. Думаю, может и больше)

Минимальная частота, которую получилось надёжно измерить девайсиком — 500 кГц.

Входная ёмкость — 2 pF, напряжение — 0,1..1,5 Вольт. Для большего входного напряжения придётся поставить делитель.
Файлы в топике: LM7001.zip, lm7001-counter.zip

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

RSS свернуть / развернуть
ой, пуксинг. px-2r?
0
Ага, после твоего обзора заказал)
0
))

puxing программирование
0
да-да, я так же колхозил))
0
А провод с зажимчиками, торчащий из осцилографа — это самоделка или от провода откушен щуп? В зависимости от ответа возникли вопросы:
1. Где взял разъем, чтобы в осцил влез?
2. Зачем было так издеваться над проводом, откусывая ему щуп? Ведь сам щуп умеет цепляться как и эти напаянные крючки…
0
Это готовый вот такой проводок, его две штучки шло в комплекте.
0
В комплекте? У меня в комплекте 2 щупа… Поэтому и удивился откуда такой проводок взялся…
0
Сиды их первое время не ложили.
0
Извращенский частотомер
Да уж, извращеньице…
0
  • avatar
  • mzw
  • 22 июля 2012, 11:39
Ну, переименовал… :/
0
Применяли подобное на частотах чуть повыше, 200...500 МГц. Прескалером служила LMX1601 с выводом поделенной частоты на FoLD, есть там такой режим (она вообще-то до 1100 МГц работает).
0
У меня тоже такая микросхема лежит, думал сделать на ее основе синтезатор частоты для стерео-передатчика, да тогда опыта было маловато, передатчик сделал на BA1404, а синтезатор нет, может попозже соберусь. А там и ваши наработки пригодятся…
0
Измерение может занять секунд 30, так что в нижней строчке рисуется прогрессбар из «решёточек».
Что-то не то. Синтезатор на десятки МГц перестраивается за считанные мс. Так что в самом худшем случае время на определение частоты таким способом должно быть на порядок меньше указанного в статье.
0
  • avatar
  • Flash
  • 17 августа 2015, 11:09
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.