Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Счётчик десятинаносекундных импульсов на STM32F4
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
uu5jkb
Приветствую всех.
Стоит задача вести счёт импульсов, приходящих по пяти каналам. Импульсы уже прямоугольные, сформированные, длительность 10 нс, интервал между импульсами скачет случайным образом, в худшем случае два импульса "слипаются в один". Измерять надо в течение 20 мс, за это время может набежать до 500 тыс. импульсов. По прикидкам, STM32F4 может таткировать свои таймеры 168 МГц и регистрировать импульсы такой длительности. Два 32-разрядных таймеров запустить напрямую, ещё три 16-битных - по прерываниям увеличивать програмный счётчик, чтобы вместилось 500 тыс. импульсов.
Собственно, вопрос: может кто возился с подобным и есть ли какие противопоказания для такого использования СТМ?
Спасибо.
Xenia
Цитата(uu5jkb @ Jun 1 2014, 13:33) *
Импульсы уже прямоугольные, сформированные, длительность 10 нс,... По прикидкам, STM32F4 может таткировать свои таймеры 168 МГц и регистрировать импульсы такой длительности.
Собственно, вопрос: может кто возился с подобным и есть ли какие противопоказания для такого использования СТМ?


На STM32F не считала, но обычно во всех случаях когда счетный вход таймера тактируется, максимальная измеряемая частота достигает лишь половины тактовой частоты. Т.е. для того, чтобы считать меандр, тактирование должно произойти в двух местах - последовательно на разных уровнях (высоком и низком). Иначе таймер не поймет, что это пошел второй импульс, а не продолжается первый.

Если STM32F позволяет считать асинхронно с частотой, превышающей половину тактируемой, то прошу отозваться тех, кому это удалось практически осуществить. Меня такая возможность тоже сильно интересует.
adnega
Цитата(Xenia @ Jun 1 2014, 13:48) *
позволяет считать асинхронно с частотой

А есть ли вообще асинхронные таймеры хоть в каком-то МК. Мне кажется в таком случае невозможно побороть метастабильность.
Взять тот же модуль RTC - танцы еще те.
Кста, это, пожалуй, единственный пример асинронного таймера, но ограничения по частотам наложены суровые.
Вроде в AVR есть асинхронный таймер (для часовых целей?).
jcxz
Цитата(uu5jkb @ Jun 1 2014, 15:33) *
Стоит задача вести счёт импульсов, приходящих по пяти каналам. Импульсы уже прямоугольные, сформированные, длительность 10 нс, интервал между импульсами скачет случайным образом, в худшем случае два импульса "слипаются в один". Измерять надо в течение 20 мс, за это время может набежать до 500 тыс. импульсов. По прикидкам, STM32F4 может таткировать свои таймеры 168 МГц и регистрировать импульсы такой длительности. Два 32-разрядных таймеров запустить напрямую, ещё три 16-битных - по прерываниям увеличивать програмный счётчик, чтобы вместилось 500 тыс. импульсов.
Собственно, вопрос: может кто возился с подобным и есть ли какие противопоказания для такого использования СТМ?

Что-ж Вы кроме как в лоб ничего и придумать не можете? blink.gif

Поставьте на каждый источник импульсов по делителю (D-триггеру). Если таймеры CPU смогут работать на частоте ядра, то такую частоту
они уже посчитать смогут (так как она уже более чем в 2 раза ниже тактовой). А в конце интервала по состоянию уровня после делителя сможете
досчитать последний нечётный импульс.

То что у вас есть "слипшиеся импульсы", говорит что у вас что-то не так спроектировано в системе в целом.
Как вариант решения - ждущий мультибиратор на каждый источник импульсов, с периодом ==10нс и на счётные входы подавать уже выходы
этих мультивибраторов. Т.е. - если вместо импульса длиной 10нсек, придёт что-то более длинное, то мультивибратор успеет за это время сгенерить
не один, а два или более имульсов, в зависимости от длительности.
Другой вариант - в МК сигнал подавать не на счётные входы счётчиков, а на входы разрешения счёта импульсов от внутреннего генератора
(не знаю умеют-ли такое счётчики STM32?).
Но тут наверное нужно чтобы частота этого генератора была кратна длительности ваших импульсов (10нсек).

PS: А почему-бы просто не поставить внешние счётчики и опрашивать их периодически?
A. Fig Lee
Цитата(jcxz @ Jun 1 2014, 07:28) *
Другой вариант - в МК сигнал подавать не на счётные входы счётчиков, а на входы разрешения счёта импульсов от внутреннего генератора
(не знаю умеют-ли такое счётчики STM32?).

Умеют. Вообще лучше конечно такое делать на CPLD. Набрать 5 счетчиков 8 разрядных, например, выход завести на таймеры или даже больше разрядов и на GPIO пины через прерывания считать.
Или на рассыпухе сделать.


Цитата(Xenia @ Jun 1 2014, 05:48) *
Если STM32F позволяет считать асинхронно с частотой, превышающей половину тактируемой, то прошу отозваться тех, кому это удалось практически осуществить. Меня такая возможность тоже сильно интересует.

STM32F103 асинхронно не может, как я понял из figure 122 RM008,
тоже самое для второго режима.

А вот майкрочип может считать асинхронно.
jcxz
Цитата(A. Fig Lee @ Jun 1 2014, 17:40) *
Умеют. Вообще лучше конечно такое делать на CPLD. Набрать 5 счетчиков 8 разрядных, например, выход завести на таймеры или даже больше разрядов и на GPIO пины через прерывания считать.
Или на рассыпухе сделать.

Больше не надо, хватит и 4-х разрядов: счётчики - делители частоты, их выходы переполнения - на таймеры CPU, по завершении интервала счёта (20мсек),
считываем содержимое счётчиков по отдельной шине.
Даже вобще-то и шины отдельной не надо, чтобы не городить много лишних дорог на плате - достаточно одной с GPIO CPU.
После окончания интервала счёта, заводим её через элемент ИЛИ на счётные входы всех счётчиков, даём с CPU 16 импульсов -
таким образом определяем остаток в счётчиках на момент окончания счёта внешних импульсов.
uu5jkb
Цитата(Xenia @ Jun 1 2014, 13:48) *
...максимальная измеряемая частота достигает лишь половины тактовой частоты.

Э, да, как бы очевидная вещь, а я что-то не подумал. Спасибо.

Цитата(jcxz @ Jun 1 2014, 15:28) *
Что-ж Вы кроме как в лоб ничего и придумать не можете? blink.gif

Лентяи мы rolleyes.gif

Цитата(jcxz @ Jun 1 2014, 15:28) *
То что у вас есть "слипшиеся импульсы", говорит что у вас что-то не так спроектировано в системе в целом.

Это нормально, импульсы идут от ФЭУ, а там пришёл фотон или два, или не пришло вообще - не предскажешь.

Цитата(jcxz @ Jun 1 2014, 15:28) *
PS: А почему-бы просто не поставить внешние счётчики и опрашивать их периодически?

Придётся.

Цитата(jcxz @ Jun 1 2014, 15:56) *
Больше не надо, хватит и 4-х разрядов: счётчики - делители частоты, их выходы переполнения - на таймеры CPU, по завершении интервала счёта (20мсек),
считываем содержимое счётчиков по отдельной шине.
Даже вобще-то и шины отдельной не надо, чтобы не городить много лишних дорог на плате - достаточно одной с GPIO CPU.
После окончания интервала счёта, заводим её через элемент ИЛИ на счётные входы всех счётчиков, даём с CPU 16 импульсов -
таким образом определяем остаток в счётчиках на момент окончания счёта внешних импульсов.

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

Подскажите вполне себе доступный 16-битный (или 8-битный, а лучше оба) счётчик, который до таких частот (300-400 МГц минимум) сможет работать.
jcxz
Цитата(uu5jkb @ Jun 1 2014, 19:43) *
Это нормально, импульсы идут от ФЭУ, а там пришёл фотон или два, или не пришло вообще - не предскажешь.

Тогда Вам нужен вариант с ждущим мультивибратором, чтобы такие случаи хотя-бы частично решать.

Цитата(uu5jkb @ Jun 1 2014, 19:43) *
Этой дорогой и пойду, если ничего другого не придумаю. Только импульсы от ФЭУ в перерывах между счётом не исчезают, надо будет регистр поставить, который в нужный момент будет их состояния запоминать.

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

Цитата(uu5jkb @ Jun 1 2014, 19:43) *
Подскажите вполне себе доступный 16-битный (или 8-битный, а лучше оба) счётчик, который до таких частот (300-400 МГц минимум) сможет работать.

Зачем 8бит? Достаточно 4. После деления на 16 для этой частоты таймера CPU уже хватит.
A. Fig Lee
Я бы поначалу глянул, хватит ли таймеров у СТМ32.
Для STM32F103 External могут считать, например, каналы 1 и 2. Причем 1 работает через XOR с другими каналами,
не знаю, можно ли запустить только от канала 1.
Канал 2 может иметь тот же пин для 2х разных таймеров. Например TIM2_CH2/TIM2_CH5..



Цитата(jcxz @ Jun 1 2014, 10:01) *
Тогда Вам нужен вариант с ждущим мультивибратором, чтобы такие случаи хотя-бы частично решать.

Лучше вход тактировать частотой 200 МГц, например..
HHIMERA
Цитата(A. Fig Lee @ Jun 1 2014, 14:52) *
STM32F103 асинхронно не может, как я понял из figure 122 RM008,

А вот майкрочип может считать асинхронно.

И STM может... и STM8 и STM32... по входу ETR...
В этом они ничем от Микрочипа не отличаются...
Golikov A.
CPLD лучше ставить. Всяко лучше чем на рассыпухе собирать, или счетчики ставить. А то и FPGA какую мелкую подтянуть...
SasaVitebsk
Непосредственно по вопросу, если это спасёт, то делитель на ETR МК асинхронный. То есть, предельная частота поступающая на вход может быть выше чем CLK/2.
Но есть и ещё один вопрос. При подключении цепочки таймеров, если нет механизма включения/ отключения входной частоты (счёт на лету), сложно контролировать точность счёта, при переполнении, так как нет механизма параллельной фиксации значений нескольких таймеров.
Короче лучше такую вещь сделать внешей, по отношению к МК. По крайней мере, за минусом последнего таймера в цепочке.
demiurg_spb
Как альтернативный вариант:
Запустить ДМА по первому событию на чтение порта, складывать всё в буфер (да, его размер должен быть достаточным) по прошествии пачки импульсов уже не в реальном времени проводить пост-обработку данных.
PS: Это всего лишь сиюминутная идея.
jcxz
Цитата(SasaVitebsk @ Jun 2 2014, 12:20) *
Но есть и ещё один вопрос. При подключении цепочки таймеров, если нет механизма включения/ отключения входной частоты (счёт на лету), сложно контролировать точность счёта, при переполнении, так как нет механизма параллельной фиксации значений нескольких таймеров.

В чём сложность-то?
Код
uint i, i1, i2 = timerLow;
do {
  i1 = i2;
  i = timerHigh;
  i2 = timerLow;
} while (i1 > i2);
return i << N | i2;


Цитата(demiurg_spb @ Jun 2 2014, 12:53) *
Запустить ДМА по первому событию на чтение порта, складывать всё в буфер (да, его размер должен быть достаточным) по прошествии пачки импульсов уже не в реальном времени проводить пост-обработку данных.

Не хватит быстродействия. Тем более для 5-и каналов работающих на частоте близкой к тактовой CPU.
demiurg_spb
Цитата(jcxz @ Jun 2 2014, 12:02) *
Не хватит быстродействия. Тем более для 5-и каналов работающих на частоте близкой к тактовой CPU.
Количество каналов при таком способе не важно, т.к. за раз читается весь порт сразу и могут быть сохранены состояния аж 16 дискретных каналов ввода.
jcxz
Как это не важно? А как вы их потом разбирать на отдельные счётчики будете если не побитно?
demiurg_spb
Цитата(jcxz @ Jun 2 2014, 12:50) *
Как это не важно? А как вы их потом разбирать на отдельные счётчики будете если не побитно?

Вы наверное не понимаете суть идеи.
При ПОСТ обработке весь разбор происходит.
А при накоплении данных никакой обработки - только чтение состояния параллельного порта ввода и сохранение в массив.
Ведь ТС ясно говорит, что длительность пачки импульсов не превышает 20мс...
При этом, благодаря ДМА и большому объёму ОЗУ, пост обработку можно проводить параллельно с накоплением второго (теневого) буфера...
adnega
Цитата(demiurg_spb @ Jun 2 2014, 13:03) *
При этом, благодаря ДМА и большому объёму ОЗУ, пост обработку можно проводить параллельно с накоплением второго (теневого) буфера...

Не совсем понятна идея, как DMA сможет помочь.
С какой частотой DMA может вычитывать с порта? Явно медленнее FCPU/2.
А память на какой частоте работает (а судя по объему нужна внешняя)? Тоже много бальше FCPU/2?
demiurg_spb
Цитата(adnega @ Jun 2 2014, 13:22) *
Не совсем понятна идея, как DMA сможет помочь.
С какой частотой DMA может вычитывать с порта? Явно медленнее FCPU/2.
А память на какой частоте работает (а судя по объему нужна внешняя)? Тоже много бальше FCPU/2?
Я про то и говорю, что нужно почитать доку и ответить на эти вопросы.
И тогда станет ясно пройдёт эта идея или нет. Кстати по DMA можно и байты читать, тогда, если линии ввода разместить в одном байте регистра ввода, можно в 2 раза выиграть по памяти.
Я не навязываю эту идею, а просто озвучиваю для ТС. Захочет посчитать всё - прекрасно. Я бы с удовольствием ознакомился с результатами.
Посмотрел сам - вроде как 76нс получается для чтения из порта ввода в память при тактовой 144MHz.
Многовато для этой задачи...
_pv
DCMI на вход вроде до FCLK/2 разгоняется.
но всё равно даже 20мс / 10нс это 2 МегаБайта буфер.
так что счётчик-делитель снаружи всё равно нужен.
A. Fig Lee
Цитата(HHIMERA @ Jun 1 2014, 11:51) *
И STM может... и STM8 и STM32... по входу ETR...
В этом они ничем от Микрочипа не отличаются...

Да?
A что означает фраза

Цитата
The delay between the rising edge on ETR and the actual clock of the counter is due to the
resynchronization circuit on the ETRP signal.

на странице 365 RM008?
jcxz
Цитата(demiurg_spb @ Jun 2 2014, 15:03) *
При ПОСТ обработке весь разбор происходит.
А при накоплении данных никакой обработки - только чтение состояния параллельного порта ввода и сохранение в массив.

Вы считаете что DMA работает на частоте, превышающей частоту CPU? biggrin.gif
Для регистрациии 10нс-импульсов потребуется считывать с GPIO с частотой как минимум ==200МГц.
CPU выбранный ТС имеет макс. частоту 168МГц.
И это не учитывая что GPIO обычно работает на частоте в разы ниже частоты ядра; не учитывая скорости памяти
(которая к тому-же внешняя понадобится).

Цитата(demiurg_spb @ Jun 2 2014, 15:03) *
Ведь ТС ясно говорит, что длительность пачки импульсов не превышает 20мс...
При этом, благодаря ДМА и большому объёму ОЗУ, пост обработку можно проводить параллельно с накоплением второго (теневого) буфера...

Где это он такое говорит? Вот его слова:
Цитата(uu5jkb @ Jun 1 2014, 19:43) *
Этой дорогой и пойду, если ничего другого не придумаю. Только импульсы от ФЭУ в перерывах между счётом не исчезают, надо будет регистр поставить, который в нужный момент будет их состояния запоминать.

И какая тут ещё может быть параллельная обработка процессором?

Во! если уж так хочется, то я придумал как можно DMA задействовать rolleyes.gif
ТСу не хвататет таймеров в CPU? Не беда! Заводим один источник импульсов на вход SCLK SPI-порта, переводим его в Slave, максимальная разрядность, настраиваем DMA
на приём с него в одно слово ОЗУ (без инкремента/декремента адреса).
И всё! По окончании интервала счёта считываем содержимое числа оставшихся пересылок DMA-канала, умножаем на разрядность SPI, делим на 2 - получаем число импульсов. cheers.gif
Хотя тут тоже - нужна разрядность SPI хотя-бы 16 (лучше - больше), и желательно - FIFO в SPI. И не забываем про счётчики-делители на входе перед CPU!
A. Fig Lee
А почему проблемы? Потому что не железо подбирается под задачу, а идет попытка впихнуть молотком трудновпихуемое
adnega
Цитата(A. Fig Lee @ Jun 2 2014, 17:56) *
А почему проблемы? Потому что не железо подбирается под задачу, а идет попытка впихнуть молотком трудновпихуемое

Согласен. Но правильно ли мы понимаем задачу?
Насколько я понял:
1. Нужен механизм фиксации импульсов, которые могут приходить с очень маленькой задержкой между собой (эквивалентно макс. 400МГц).
2. Средняя частота импульсов гораздо ниже.
3. Нужно много таких счетных каналов.
4. Точный, с точностью до импульса, счет не нужен, т.к. в таких задачах всегда применяется значительное усреднение.

Если допустимо использование внешних компонентов, то я бы поставил N счетчиков делителей - выходы счетчиков завел на EXTI-прерывания.
HHIMERA
Цитата(A. Fig Lee @ Jun 2 2014, 14:24) *
Да?
A что означает фраза

"Поднимите мне веки!"(С)
И причём здесь асинхронный предделитель к синхронному счётчику???
jcxz
Цитата(adnega @ Jun 2 2014, 20:43) *
4. Точный, с точностью до импульса, счет не нужен, т.к. в таких задачах всегда применяется значительное усреднение.
Если допустимо использование внешних компонентов, то я бы поставил N счетчиков делителей - выходы счетчиков завел на EXTI-прерывания.

Позвольте развить Вашу мысль далее wink.gif
ТС не указал требований по точности счёта. Какая допустимая погрешность в кол-ве импульсов?
А то решение может быть очень простым и сердитым:
Формирователь импульса на каждый канал (нормирует амплитуду и длительность). После него -
обычный аналоговый интегратор, а-ля - RC-цепочка. После - АЦП.
У меня так в стареньком дозиметре сделано. Вроде ещё на K572ПВ чего-то там.
Там тоже импульсы от пролетающих через разрядники гамма-квантов и бета-частиц так считаются.
И хватит даже AVR или MSP430.
Xenia
Цитата(HHIMERA @ Jun 2 2014, 22:33) *
"Поднимите мне веки!"(С)
И причём здесь асинхронный предделитель к синхронному счётчику???


А почему вообще счетчик синхронный? Ведь полным полно микросхем-счетчиков, хотя бы типа К155ИЕ7 sm.gif. И никакой синхронизации для своей работы они не требуют. Отчего вдруг появилась синхронизация, когда в качестве счетчика работает таймер? Считал бы себе, как большинство счетчиков по восходящему фронту.
HHIMERA
Потому что проблема надуманная... Делов то... максимум один вечер...
Корпус LQFP100... чтобы иметь пять таймеров с ETR...
Golikov A.
а как расшифровывается ETR?

A. Fig Lee
Цитата(Golikov A. @ Jun 2 2014, 15:43) *
а как расшифровывается ETR?

External TRigger
Tanya
Цитата(uu5jkb @ Jun 1 2014, 17:43) *
Это нормально, импульсы идут от ФЭУ, а там пришёл фотон или два, или не пришло вообще - не предскажешь.

Если мне память не изменяет... счет фотонов имеет преимущество перед аналоговым интегрированием при скорости импульсов меньше миллиона в секунду.
Или уже не так?
Golikov A.
Цитата
External TRigger

спасибо

Цитата
счет фотонов имеет преимущество перед аналоговым интегрированием при скорости импульсов меньше миллиона в секунду

когда конденсатор дешевле счетчика, мне кажется... При честном счете получается более прозрачный результат, без сомнений и калибровок, это похоже на решение задачи в лоб грубой силой, за счет того что компоненты дешевеют. И я бы реально воткнул бы туда FPGA и все бы спокойнехенько пересчитал...
Tanya
Цитата(Golikov A. @ Jun 3 2014, 08:47) *
когда конденсатор дешевле счетчика, мне кажется... При честном счете получается более прозрачный результат, без сомнений и калибровок, это похоже на решение задачи в лоб грубой силой, за счет того что компоненты дешевеют. И я бы реально воткнул бы туда FPGA и все бы спокойнехенько пересчитал...

Нет. Причина в "наползании или слиянии" импульсов. И счет становится все более нечестным по мере увеличения вероятности наползания. При малых освещенностях основной выигрыш за счет убирания теплового фона - дискриминации импульсов по амплитуде при счете.
demiurg_spb
Цитата(jcxz @ Jun 2 2014, 17:35) *
Вы считаете что DMA работает на частоте, превышающей частоту CPU? biggrin.gif
К чему этот юмор? Конечно не считаю.
Я предварительно оценил максимальную синхронную частоту захвата до 16 каналов дискретного ввода, при использовании DMA в сообщении №19.
И я уверен, что есть ряд задач (например не слишком шустрый логический анализатор), где его можно использовать.
Увы не в этот раз.
Цитата
Где это он такое говорит?
В первом сообщении ТС.
Цитата
И какая тут ещё может быть параллельная обработка процессором?
Такая, о которой я уже три раза вам говорил.
adnega
Цитата(demiurg_spb @ Jun 3 2014, 11:54) *
Я предварительно оценил максимальную синхронную частоту захвата до 16 каналов дискретного ввода, при использовании DMA в сообщении №19.
И я уверен, что есть ряд задач (например не слишком шустрый логический анализатор), где его можно использовать.
Увы не в этот раз.

Кажется, у модуля DCMI больше шансов быть задействованным в логическом анализаторе.
Тот вариант, который предлагаете Вы тоже имеет право на жизнь. Таким образом я успешно реализовал самодиагностику линии CAN (обрыв, КЗ, норма, доминанта), о чем года три назад писал на форуме. Связка TIM, DMA и GPIO на аппаратном уровне как раз в той задаче, когда, работая по прерываниям, уже не успеваешь.
demiurg_spb
Цитата(adnega @ Jun 3 2014, 12:14) *
Кажется, у модуля DCMI больше шансов быть задействованным в логическом анализаторе.
Это здорово!
Цитата
Связка TIM, DMA и GPIO на аппаратном уровне как раз в той задаче, когда, работая по прерываниям, уже не успеваешь.
Любопытно... У Вас не сохранилось ссылочки на ту тему?
Леонид Иванович
10 лет назад решал подобную задачу - делал двухканальный счетчик фотонов (http://www.spetspribor.info/products/laboratory/cnt-202.html). Для получения нулевого мертвого времени использовался метод двух счетчиков. Логика реализована на CPLD. Как мне кажется, использовать дляданной задачи таймеры процессора, это что топором бриться.
adnega
Цитата(demiurg_spb @ Jun 3 2014, 12:27) *
Любопытно... У Вас не сохранилось ссылочки на ту тему?

Тут только назначение. Кста, вы тоже были в той теме)
Тему с аппаратной реализацией пока найти не могу.
jcxz
Цитата(adnega @ Jun 3 2014, 14:14) *
Тот вариант, который предлагаете Вы тоже имеет право на жизнь. Таким образом я успешно реализовал самодиагностику линии CAN (обрыв, КЗ, норма, доминанта), о чем года три назад писал на форуме. Связка TIM, DMA и GPIO на аппаратном уровне как раз в той задаче, когда, работая по прерываниям, уже не успеваешь.

У меня в нескольких проектах на LPC17xx так реализован программный UART (аппаратных не хватает). Не только RX, но и TX.
С честным оверсэмплингом ==16.
И дело не в неуспевании. Зачем лишне грузить CPU?
adnega
Цитата(jcxz @ Jun 3 2014, 13:19) *
У меня в нескольких проектах на LPC17xx так реализован программный UART (аппаратных не хватает). Не только RX, но и TX.
С честным оверсэмплингом ==16.
И дело не в неуспевании. Зачем лишне грузить CPU?

В той задачке, которую решал я работало только на уровне оптимизации по скорости. Как правило нижняя частота на шине CAN некоторыми Phy ограничивается аппаратно. Поэтому тайминги жесткие. Суть проблемы в том, что было предложено решение (пост обработка захваченных данных), которое к данной задаче не очень подходит, но успешно используется в других задачах (мы с Вами привели по реальному примеру).

Теперь, если вернуться к исходной задаче - подсчет импульсов с максимальной пиковой частотой 100МГц (а лучше до 400МГц) при средней частоте (за 20мс) 25МГц без внешних компонентов средствами STM32F40x, то я решения не вижу.
jcxz
Цитата(adnega @ Jun 3 2014, 16:45) *
Теперь, если вернуться к исходной задаче - подсчет импульсов с максимальной пиковой частотой 100МГц (а лучше до 400МГц) при средней частоте (за 20мс) 25МГц без внешних компонентов средствами STM32F40x, то я решения не вижу.

По-моему - это уже даже ТСу ясно biggrin.gif
adnega
Цитата(jcxz @ Jun 3 2014, 19:54) *
По-моему - это уже даже ТСу ясно biggrin.gif

Но если ТС согласится на внешнюю обвязку (придется сфомулировать некоторые критерии: цена, площадь, необходимость прошивки и т.п.), то обсуждение может выйти на новый виток)
Xenia
Цитата(adnega @ Jun 1 2014, 14:11) *
Кста, это, пожалуй, единственный пример асинронного таймера, но ограничения по частотам наложены суровые.
Вроде в AVR есть асинхронный таймер (для часовых целей?).


Воспользуюсь случаем упомянутого всуе AVR поговорить про Х-Мегу. sm.gif Понимаю, что это не совсем правильно в разделе, посвященном ARM, тем более что достичь заданной планки в 10 нс она не может. Тем не менее, здесь содержится идея, которая до сих пор не была упомянута, но могла бы оказаться в нашем деле полезной. Поэтому я сейчас изложу идею в приложении к Х-Меге (мне хорошо знакомой), а специалистов по STM32F попрошу прокомментировать мой пост на предмет возможности переноса этой идеи на STM32F.

Суть идеи в том, что ограничения по рабочей частоте обычно связаны с недостаточностью скорости выборки из флеш-памяти команд, тогда как периферия (и в том числе таймеры!) способна работать на частотах, превышающих номинальную в разы.

Такая возможность зачастую имеется у МК, имеющих встроенный PLL-генератор частоты, синхронизируемый обычным осциллятором (внутренним или внешним). Для этих целей у Х-Меги существует программный множитель (до х31), позволяющий умножать частоту осциллятора. У STM32F, по-видимому, тоже есть такая же возможность, если он работает на частотах 168-180 МГц на кварце, у которого всего 8 МГц.

Помимо PLL-множителя, у Х-Меги есть еще три делителя (A, B и C), через которые частота PLL поступает в CPU и память. Абсолютное большинство пользователей этими делителями не пользуются, т.е. они остаются в положении 1:1 по умолчанию. Т.е. люди сразу умножают частоту кварца или внутреннего RC-осциллятора до рабочей частоты и на этой частоте работают. Однако частоту PLL можно задрать кверху гораздо выше, погасив избыток делителями, чтобы CPU и память по-прежнему получали привычную частоту. Причем это будет не интерлив, когда пропускаются такты, а самый обычный для ядра режим, поскольку ядро не знает, что по дороге частота была повышена в разы, а потом возвращена назад делителями.

А вот таймеры, порты и кое-что еще из периферии можно тактировать той самой высокой промежуточной частотой. При этом "разрешающая частота" таймера может быть увеличена в разы (2-4 раза) против частоты CPU. Ускоряет ли эта идея счет внешних импульсов, я доподлинно не знаю, но то что генерация ШИМ от этого возрастает, ясно написано в руководстве и сопровождается примером программы.

Осталось только выяснить у знающих людей, способен ли STM32F проделывать подобные вещи, т.е. заставить таймеры тактироваться частотой, превышающей номинальную. И если да, то возможно ли этим способом превзойти 180 МГц на таймерах, не занимаясь разгоном ядра?
alexen
Цитата(Xenia @ Jun 4 2014, 00:15) *
ограничения по рабочей частоте обычно связаны с недостаточностью скорости выборки из флеш-памяти команд

При необходимости можно запускать часть кода из SRAM.

Таймеры в STM32F не могут тактироваться от промежуточных частот PLL, предельная частота равна частоте ядра. Можно посмотреть в сторону LPC43xx, там официально до 204 МГц и есть 16-канальный модуль SGPIO, возможно его можно использовать в данной задаче.

Леонид Иванович
Цитата(alexen @ Jun 4 2014, 00:44) *
Таймеры в STM32F не могут тактироваться от промежуточных частот PLL, предельная частота равна частоте ядра.


Например, в F3 таймеры TIM1 и TIM8 могут тактироваться от 144 МГц при частоте ядра 72 МГц.
alexen
Цитата(Леонид Иванович @ Jun 4 2014, 01:53) *
Например, в F3 таймеры TIM1 и TIM8 могут тактироваться от 144 МГц при частоте ядра 72 МГц.

И вправду могут, спасибо за замечание. Не ожидал, что в F3 изменят тактирование таймеров по сравнению с F4.
jcxz
В LPC17xx - частота периферии получается делением частоты ядра. Так что выше - никак.
В LPC177x/178x - для периферии имеется отдельный от ядра делитель. Но всё равно в даташите явно указано:
A 5-bit divider allows a range of frequencies to be used. Note that the peripheral clock rate should not be set higher than the CPU clock rate.
uu5jkb
Убедили. Потратил некторое время на знакомство с ПЛИСинами, сделал usbblaster. Потренировался с квартусом.
Программа получилась следующая:

CODE
module counter4bit(
input wire in0,
input wire in1,
input wire in2,
input wire in3,
input wire in4,
input wire reset,
input wire enable,
input wire read,
input wire[3:0] adr,
output reg[7:0] out8bit
);
reg[23:0] counter0;
reg[23:0] counter1;
reg[23:0] counter2;
reg[23:0] counter3;
reg[23:0] counter4;

always @ (posedge in0)
begin : COUNTER0
if (reset == 1'b0)
begin
counter0 <= 0;
end
else if (enable == 1'b1)
begin
counter0 <= counter0 + 1;
end
end

always @ (posedge in1)
begin : COUNTER1
if (reset == 1'b0)
begin
counter1 <= 0;
end
else if (enable == 1'b1)
begin
counter1 <= counter1 + 1;
end
end

always @ (posedge in2)
begin : COUNTER2
if (reset == 1'b0)
begin
counter2 <= 0;
end
else if (enable == 1'b1)
begin
counter2 <= counter2 + 1;
end
end

always @ (posedge in3)
begin : COUNTER3
if (reset == 1'b0)
begin
counter3 <= 0;
end
else if (enable == 1'b1)
begin
counter3 <= counter3 + 1;
end
end

always @ (posedge in4)
begin : COUNTER4
if (reset == 1'b0)
begin
counter4 <= 0;
end
else if (enable == 1'b1)
begin
counter4 <= counter4 + 1;
end
end

always @ (posedge read)
begin
case (adr)
0: out8bit <= counter0;
1: out8bit <= (counter0 << 8);
2: out8bit <= (counter0 << 16);
3: out8bit <= counter1;
4: out8bit <= (counter1 << 8);
5: out8bit <= (counter1 << 16);
6: out8bit <= counter2;
7: out8bit <= (counter2 << 8);
8: out8bit <= (counter2 << 16);
9: out8bit <= counter3;
10: out8bit <= (counter3 << 8);
11: out8bit <= (counter3 << 16);
12: out8bit <= counter4;
13: out8bit <= (counter4 << 8);
14: out8bit <= (counter4 << 16);
endcase
end

endmodule


Несколько идиотских впросов:
1. В коде всё более-менее или есть какие-то страшные принципиальные ошибки?
2. Каким образом выбирать пины входов и выходов, чтобы задержка была минимальной, квартус какие-то намеки делает, что могло бы быть и быстрее.
3. Правильно ли делать такую синхронизацию по каждому из входов или, например, лучше сделать глобальный клок с частотой около 300 МГц и по каждому клоку смотреть состояние всех ног.
4. Счётчик на 24-бита - это есть гут или не гут, в даташитах же все упоминают про 16-битный при описании быстродействия. Резко ли падает скорость с увеличнием разрядности счётчика?
5. Как лучше сделать ногу ресет. При импульсе на счетных входах если ресет в нуле - сброс счётчика, а как бы сделать сброс в отсутствие импкльсов на входах. Пробовал, например, по posedge ресета сбрасывать все счетные регистры в ноль - квартус матерился, как я понял, из-за того, что значения регистров могут устанавливаться в двух местах - по ресету и по счёту, поэтому возникает конфликт.
6. Совсем идиотский: как сделать модуль "счетчик" и вставить пять счетчиком в этот большой модуль вместо пяти раз always @ (posedge in_)?

ПЛИСина - сплд epm240t100c5n.

Спасибо
Golikov A.
Ну...
код ничего для начальной курсовой.
1. Капитальная ошибка.
always @(poasedge in1) - эта конструкция заводит сигнал in1 на клоки триггера. И вот тут есть засада. Если у вас in идет на клоковую ногу (специальные ноги ПЛИС), то все не плохо. А если нет, то синтезатор потянет сначала этот сигнал на так называемое клоковое дерево, а только потом на триггера, это создает достаточно большую задержку между фронтом и тем как фронт дойдет до триггера... это может и все убить, и частоту снизить, и глюки вызывать если не хватит констраинов
2. В ПЛИС есть такая хрень как метастабильность. Всегда есть шанс что вы по клоку поймаете момент переключения триггера, а так же есть шанс что сигнал не успеет дойти до разных частей ПЛИС, то есть если у вас
Код
always @(posedge clk1)
begin
   reg <= reg + 1;
end

и код
Код
always @(posedge clk2)
begin
  if(reg == 1)
    begin
       A<=2;
       B<=3;
    end
end

то при некоторых сочетания положения clk1 и clk2 у вас может быть что угодно. Иногда А защелкниться а В нет, Иногда в них будет мусор, если они ловят какие-то меняющиеся сигналы....
Потому считается гораздо правильнее и проще на начальных этапах все делать на одном общем клоке. Тогда большую часть неприятностей берет на себя синтезатор, и отследит всю фигню.. Чтобы избежать метастабильность надо вход пропускать через цепочку 2 триггеров.
то есть ваш код должен быть таким
CODE
reg in1_0 = 0;
reg in2_0 = 0;
reg in3_0 = 0;
reg in1_1 = 0;
reg in2_1 = 0;
reg in3_1 = 0;
reg in1_2 = 0;
reg in2_2 = 0;
reg in3_2 = 0;




reg in1_reg = 0;
reg in2_reg = 0;
reg in3_reg = 0;

always @(posedge clk or posedge reset)
begin
//убираем метастабильность
reg in1_0 <= in1;
reg in2_0 <= in2;
reg in3_0 <= in3;
reg in1_1 <= reg_in1_0;
reg in2_1 <= reg_in2_0;
reg in3_1 <= reg_in3_0;
//для отловки фронта
reg in1_2 <= reg_in1_1;
reg in2_2 <= reg_in2_1;
reg in3_2 <= reg_in3_1;

//ловим фронты сигнала
if((reg_in1_2 == 1'b0)&&(reg_in1_1 == 1'b1))
in1_reg <= in1_reg + 1'b1;
if((reg_in2_2 == 1'b0)&&(reg_in2_1 == 1'b1))
in2_reg <= in2_reg + 1'b1;
//ловим фронты сигнала
if((reg_in3_2 == 1'b0)&&(reg_in3_1 == 1'b1))
in3_reg <= in3_reg + 1'b1;


if(reset == 1'b1)
begin
in1_reg <= 0;
in2_reg <= 0;
in3_reg <= 0;
end
end

размер счетчика влияет на максимальную частоту с которой счетчик может считать, о том получается или нет работать на желаемой вам частоте. Плис класса спартан 6 тащит на частоте 100-200 мГц, 64 битные регистры, виртексы еще больше, что может ваша CPLD хрен знает....
При этом частота падает и по мере загрузки плис кодом, чем больше блок тем медленнее...
ресет бывает синхронный и асинхронный, первый работает по клоку внешнему, другой по фронту самого ресета
первый описывается так
Код
always @(posedge clk)
begin
    if(reset == 1'b1)
     ....
end

то есть каждый клок, пока ресет в 1 он выполняется и сбрасывает регистры.
второй описывается так
Код
always @(posedge clk or posedge reset)
begin
    if(reset == 1'b1)
        ....
end


работает по фронту сигнала ресет, заводиться прям на специальные ножки блоков внутри плис, вроде как на фронты клока кладет...
да важно знать что в верилоге последняя строка выполняется приоритетно то есть описание вида
Код
always @(posedge clk)
begin
    A<= A + 1'b1;
    
    if(reset1 == 1'b1)
       A<= 1;
    
    if(reset2 == 1'b1)
       A<=2;
end

работает как запись вида
Код
always @(posedge clk)
begin
    if(reset2 == 1'b1)
       A<=2;
    else  if(reset1 == 1'b1)
       A<= 1;
    else
    A<= A + 1'b1;
end

но читается первый вариант проще..
ну и последние конечно же можно делать инстансы
Код
module InOut(
       clk,    
       in,
       Out
);
input clk;
input in;
output reg Out = 0;

always @(posedge clk)
  begin
      Out <= in;
  end

endmodule


а в основном коде
Код
InOut InOutInst
(
   .clk(g_clk),
   .in(in_1),
   .Out(out_1)
)
InOut InOutInst2
(
   .clk(g_clk),
   .in(in_2),
   .Out(out_2)
)

а в целом отправляйтесь в раздел ПЛИС, там есть iosifik а у него есть курс молодого бойца, в целом он полезен%) ну или пишите в личку если что)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.