PRU_CTU_CONST чем отличается от PRU_CTU - у первого уставка константная, у второго - можно менять с хоста
соответственно различный расход ОЗУ и поведение
У PRU0 всего 2 выхода. остальные 2 на PRU1. И их вот так развели :(
Вид для печати
ПЛК в данном режиме при отсутствии деления выдаёт ровно 500кГц.
А поведение при смене порядка не менялось, т.к. данный алгоритм не меняет поведение при смене порядка. А в других случаях возможно.
Т.е. PRU1 работает с выходом DO1 и DO2
А PRU0 -работает с выходом DO3 и DO4.
Попробую.
По поводу PRU_CTU_CONST
Вход счетчика так же BYTE?
Его каким образом определять?
Простым входом?
Я пытался его привязать к программе, не пропускает MAKE_PRES, ошибку пишет.
Основная проблема - нужно больше импульсов, а выставлять каскадом счетчики - некрасиво, и память жрут, как я понял.
1. Да, обычным входом, байт. В примере, ЕМНИП, был пример задания константы.
2. Памяти, конечно, не 4 гига, но для достаточно комплексной программы хватит, каскадируйте.
Сейчас в демке представлены самые быстрые варианты ФБ на основе регистровой памяти. Т.к. используются байтовые связи (опять же для скорости), то доступно 25*4 связей.
Связь это выход ФБ или внутренняя переменная, как в ФБ RTRIG и CTU, к примеру.
Они тоже доступны как выходы.
Количество задействованной памяти можно посмотреть в промежуточном текстовом файле со связями.
Первые 2 регистра для временных нужд, отсчёт начинается с 2-го.
Логику можно использовать не только TRUE/FALSE, но и байтовые маски и т.п.
Я уже разобрался, но правды ради, где?
http://www.owen.ru/forum/attachment....id=24496&stc=1
Описания блоков сильно бы помогли.
Как и примеры.
Как?
Так не работает:
http://www.owen.ru/forum/attachment....id=24497&stc=1
2#0000_0001 тоже не работает.
Пример во вложении.
А AND с константами не работает. Этот вариант
Как выполнить сброс счетчика? На блоках я вижу только тактовый вход и уставку, входа сброса нет.
И как быть, если мне нужен формат счета DWORD?
Вообще, хотелось бы иметь такую конструкцию:
Вложение 24530
Возможно ли?
это демка. тут нет всех возможных блоков, однако из лог. элементов можно собрать что угодно.
В теме про ПР и учебниках по электронике есть примеры реализации.
Товарищи, планирую бета-тест новой версии библиотеки ФБ для PRU.
Требуется Ваша помощь в тестировании.
Требования:
1. знание основ схемотехники (отличать OR от AND)
2. некоторое свободное время для тестирования
3. умение описать ошибку
Множество новых ФБ.
Нужны добровольцы на:
1. Описать работу ФБ
2. Проверить правильность работы на реальном ПЛК
3. Написать код на языке ST в библиотеке, чтобы можно было использовать симуляцию.
Я готов :)
1. http://www.owen.ru/forum/showthread....l=1#post197840
2. Тоже не проблема
3. До конца не ясно, нужен код для ФБ и п.1? Для проверки его на ПЛК?
А ФБ для управление ШД (http://www.owen.ru/forum/showthread....l=1#post197840) сделали ?
По п.3 - нужен код на ST, чтобы можно было воспользоваться режимом симуляции кодесиса.
Это сложная задача, требуется реверс-инжиниринг кода с ассемблера в ST.
Все добровольцы присылайте на почту мне свои координаты. plc_prog@owen.ru
На следующей неделе разошлю пакет для тестирования.
Если кто-то видит в себе силы в программировании кода ФБ (ассемблер, машинные коды, метаязык), могут попробовать написать свой ФБ под свои задачи. Укажите это в данных, я пришлю вам расширенный инструментарий
У меня свободного времени практически нет для написания сложных ФБ.
Добрый день!
Подскажите - работы остановились?
Жду библиотеку для ШД.
Интересно, а есть кто-то кроме меня (ну, кроме сотрудников ОВЕН), кто "работает над PRU"?
0) До августа Владислав в отпуске. Всего неделя осталась. Будем держаться.
Не знаю как у других, а у меня так: я вторую неделю жду договор от юристов Овен. Кирилл Валюнин предупредил, что это дело небыстрое, и, надеюсь, про меня не забыли (а, возможно, ждут Владислава).
1) Владислав прислал пакет с "pru beta 2", но там снова только BOOL функции. Т.е. блоков для работы с INT/WORD нет.
2) В присланных материалах не было инструмента, который позволял бы создавать свои ФБ. Как раз тут ждём юристов.
Мой план пока прежний -- сделать поддержку PRU в Hardella IDE.
А вот можно по-подробнее о том, какие именно функции нужны?
Я видел #30 "Генерация импульсов должна начинаться по фронту ENABLE, а заканчиваться либо после формирования заданного количества импульсов, либо если ENABLE перейдет в ноль. READY устанавливается в TRUE по окончанию формирования пачки импульсов и сбрасывается в FALSE по фронту ENABLE..."
Это всё или нужно ещё что-то?
Появилась минутка, сделал блок на ST.
Получается, для генерации следующей пачки импульсов нужно передёрнуть вход enable (сделать enable==false, дождаться пока ready перейдёт в false, потом передать enable=true и тогда пойдёт вторая пачка). Это то, что ожидалось?
По поводу изменения частоты импульсов: текущий подход к программированию PRU предполагает, что PRU выполняется своим циклом, поэтому тут я сделал "переключение сигнала out при каждом цикле PRU". Норм? Или делитель какой-то нужен?
Или с такой стороны: нормально ли, если для изменения частоты меандра нужно перезаливать PRU программу?
Нужны ли меандры разной частоты по разным выходам?
Код:FUNCTION_BLOCK PRU_GENER_BURST
VAR_INPUT
enable : BOOL;
quantity : WORD;
END_VAR
VAR_OUTPUT
out : BOOL;
ready : BOOL;
END_VAR
VAR
qtyLeft : WORD;
END_VAR
IF enable THEN
IF qtyLeft > 0 THEN
(* Идёт генерация *)
qtyLeft := qtyLeft - 1;
ELSIF ready THEN
(* Всё сгенерировали, ждём пока передёрнут enable для следующего включения *)
ELSE
(* Поступила команда на включение *)
qtyLeft := quantity * 2;
END_IF;
ELSE
(* Выключаемся *)
qtyLeft := 0;
END_IF;
ready := qtyLeft = 0;
(* Если всё сделали, то out выключится. Если пачка ещё генерируется, то младший бит и есть меандр *)
out := qtyLeft.0;
END_FUNCTION_BLOCK
Цикл можно менять, в т.ч. и на ходу, для этого предполагается использовать семейство FB START, START_CONST и START_VAR
Если же период генерации на порядки больше цикла PRU - нужен внешний делитель сигнала тактирования
1. Для генерации следующей пачки импульсов нужно вход Enable перевести в false, при этом Ready автоматически должен сброситься в false.
2. Для изменения частоты меандра перезаливать PRU программу конечно не надо, должна быть возможность оперативной смены частоты по входу PERIOD.
В общем, ждём что скажет Владислав.
Собственно, 2 вопроса:
1) Норм ли получился блок (я в почте переслал реализацию на ассемблере)
2) Можно ли мне выкладывать обновлённые библиотеки, или это только через ОВЕН
Я снова в командировках -- пишу "по приборам", вернее, без ПЛК.
Поэтому было бы хорошо, если бы
3) Кто-нибудь попробовал этот самый блок PRU_GENER_BURST
4) Рассказали как тестировать, если в хозяйстве из быстродействующего только ПЛК110 1шт и есть. Осциллографа у меня нет, мультиметра тоже нет, "населена роботами".
Замыкать быстрый вход на быстрый выход и делать программу, которая сама себя проверяет?
Либо, опять же, нужно чтобы какой-нибудь обладатель "быстрого счётчика импульсов" проверил.
И да и нет.
Если есть ST код, то его можно вручную перевести на PRU-понятный ассемблер.
Но
1) ST код нужен и для общего понимания, и для того, чтобы в КДС эмуляция работала
2) Переводить ST на ассемблер проще, чем сразу писать на asm
Примерно так (я исключил половину строк-комментариев, которые нужны для связки PRU-КДС. Привет Владиславу, если можно со спец комментариями выкладывать, то могу и с ними):
Код:.origin 0
.entrypoint __INIT_PROGRAM
;include "standart_classes.m"
#include "Defs.h"
#define enableIn R1.b0
#define quantityIn R1.w0
#define out R1.b0
#define readyOut R1.b0
#define qtyLeft R1.w0
;FB_WORKTIME=9
;FB_NAME=PRU_GENER_BURST
__INIT_PROGRAM:
QBEQ _NEED_STOP, enableIn, 0 //% если сказали выключатьс_, идём выключатьс_
QBEQ _BURST_DONE, qtyLeft, 0 //% если импульсы кончились, идём ждать передёргивани_ enable
SUB qtyLeft, qtyLeft, 1 //% минус импульс
QBA _FINISH_5TICK //%
_BURST_DONE: ; 3-ий такт
QBEQ _FINISH_4TICK, readyOut, 1 //% пока ready не сбросилось, ждём передёргивани_ enable
LSL qtyLeft, quantityIn, 1 //% qtyLeft := quantity * 2
QBA _FINISH_6TICK //%
_NEED_STOP: ; 2-ой такт
LDI qtyLeft, 0 //% останавливаемс_ -- обнул_ем qtyLeft
_FINISH_3TICK: ; 3ий такт
ADD temp, temp, 0 //% NOP
_FINISH_4TICK: ; 4ый такт
ADD temp, temp, 0 //% NOP
_FINISH_5TICK: ; 5ый такт
ADD temp, temp, 0 //% NOP
_FINISH_6TICK: ; 6ый такт
MIN temp.w0, qtyLeft, 1 //% Смотрим, осталось ли что генерировать
XOR readyOut, temp.b0, 0 //% readyOut := MIN(qtyLeft, 1) XOR 1 == qtyLeft = 0
ADD temp.w0, qtyLeft, 0 //% загружаем qtyLeft в регистр, чтобы потом считать младший бит
AND out, temp.b0, 1 //% out := qtyLeft.0
Пока ПЛК нет под рукой, решил сделать нехитрый компилятор ST -> PRU.asm.
Так что, +100500 к скорости написания PRU блоков.
Вот так выглядит:
Вложение 26068
Сделал ещё "1 процент": эмулятор PRU процессора.
Останется его скрестить со средой разработки PRU программ, и можно без ПЛК отлаживаться.
https://github.com/vlsi/pru-emulator...rTest.java#L50
Кажется скоро появится первый приличный ФБ для управления ШД. Если все получится, то следующим шагом, по моему, должно быть разработка более продвинутого ФБ. Я имею ввиду ФБ, в котором осуществляется плавный разгон и торможение ШД. Это реализовано во всех буржуйских ПЛК, которые управляют ШД. Вот ссылка на статью, в которой изложен этот вопрос: http://electroprivod.ru/akseleration.htm
Скоро vladimirisitnikov закончит разработку ФБ для управления ШД. Было бы не плохо если фирма "ОВЕН" профинансирует изготовления стенда для натурных испытаний системы управления ШД на базе ПЛК110 М02. Кроме ПЛК понадобятся ШД, драйвер ШД, источник питания на 36 или 48 вольт. Затраты небольшие. Схему электрическую принципиальную + перечень элементов могу представить.
Посмотрел-покрутил имеющиеся PRU блоки, и сделал свой компилятор.
В имеющихся блоках мне не понравилось то, что для одного только сложения нужна куча _разных_ блоков: "сложение BYTE+BYTE, WORD+BYTE, WORD+WORD". Но это ещё не всё, ведь, для сложения двух переменных и сложения переменной с константой тоже разные блоки нужны. На мой взгляд, это слишком сложно. Если сложение, то должен быть просто блок сложения.
Описывать в своей среде разновидности "PRU_ADD", "PRU_ADD_CONST", "PRU_ADD_BYTE_CONST" и правила выбора это была бы та ещё песня.
Понятно, что какие-то блоки всё равно проще на ассемблере писать (например, чтение входов-выходов, работа с host), поэтому сделал ассемблерные вставки в ST.
Всё нижеупомянутое получается одной кнопкой, без привлечения bat файлов, exe файлов и т.п.
Собственно, до сборки финального PRU0.prg (файла, который заливается в ПЛК) осталось сделать обработку ассемблерных инструкций работы с памятью: LBCO/SBCO и LBBO/SBBO. Там ничего сложного нет, просто нужно немного времени.
Пример программы:
Вложение 26227
Вот промежуточный ассемблер.
Тут особенность, что команда QBLT label, src, 42 означает "branch to label if 42 < src" (по крайней мере, так говорится в документации на процессор)
Вложение 26228
PRU, разумеется, с переменными работать не умеет, поэтому назначаем регистры.
Вложение 26229
И превращаем в java код (ну, чтобы генерировать файл для заливки в ПЛК и/или запускать эмулятор PRU)
Вложение 26230
Вот, например, блок чтения 1-го входа. Описали 1 раз -- и уже можно использовать в программе.
Присмотрелся -- тут ошибка. Должно, конечно, быть LSR Q, R31.dw, 21 (регистр b0 байтовый и в нём никак 21 бит не влезет). Но сама ошибка не влияет на суть (лень картинки переделывать)
Вложение 26226
Попробуем что-нибудь посложнее.
Напишем на ST PRU_CTU_WORD (ну, как в стандарте 61131 через RTRIG):
Вложение 26220
И сделаем цикл, в котором подаём IN1 на вход CTU и младшие 2 бита счётчика выводим на OUT1 и OUT2.
Вложение 26221
На ассемблере получается такая дичь. Компилятор подставил все-все переменные и вызовы блоков в финальную программу и превратил в ассемблер. При желании понять можно, но на ST всё-таки гораздо понятнее.
Вложение 26232
Из интересного:
1) Видно, что распределитель регистров (liveness analysis + linear scan register allocation) догадался переиспользовал регистр R1.b3 по ходу программы. Например, в самом конце где записываются OUT1 и OUT2 видно, что сам записываемый бит хранится как раз в R1.b3.
2) Особых оптимизаций сейчас нет. Например, a:=b; может приводить к выделению временного регистра для a (это видно на "бесполезной" команде в начале вызова RTRIG: ADD R2.b0, R1.b3, 0). Но если уж нужны будут оптимизации -- посмотрим потом. Как-никак, а SSA (я про Static single assignment form) за 1-2 дня не сделать.
PRU0.prg и PRU1.prg это файлы программ PRU. И да, они, по расширению, совпадают с prg 2-го КоДеСис-а.
prg отлично формируются уже представленным ПО из имеющихся или заново создаваемых ФБ.
Проблема в "уже представленном ПО" в том, что для задействования "уже представленного" нужно:
1) Создать схему программы в КДС (неудобно) или в формате КДС_CFC.exp (не реализовано)
2) Очень внимательно следить за использованием ADD vs ADD_CONST vs ADD_WORD_CONST. Вот тут "представленное ПО" крайне тяжело ложится на IDE. Сделать, конечно, всё можно, но я никак не хочу делать 100500 copy-paste'ов, описывающих разновидности ADD/SUB и т.п.
Вот фрагмент моего компилятора, описывающий команды "a := b OP c", где OP это сложение, вычитание и т.п:
Вложение 26249
Вложение 26251
И ещё пара блоков (Instruction здесь это объект, описывающий ассемблерную команду. Например, XOR, AND выше это и есть Instruction с аргументами), которые превращают "ассемблер" в нужные вызовы Java:
Вложение 26250
Тут нет никакого взрыва комбинаций "ADD vs ADD_CONST vs ADD_WORD_CONST".
Вышеупомянутый код без проблем компилирует сложение BYTE/WORD/DWORD.
Конечно, мне хотелось бы уйти от unsigned типов, но я уж лучше сначала сделаю рабочий блок ШД, а заниматься знаковыми типами и т.п. потом.
"Компилировать в формат КДС_CFC.exp" неудобно. Да и у меня нет никакого желания откладывать "обкатку блока ШД" до момента, как я научусь генерировать КДС_CFC.exp формат.
Объективно:
1) Компилировать в бинарный формат PRU я могу уже сейчас. Как-никак, а команды, которые выполняет PRU процессор гораздо ближе к ST, чем к графическому языку
2) Компилировать графический язык в ST гораздо проще, чем наоборот. Поэтому, вариант развития "сначала сделать ST -> PRU0.prg компилятор", потом добавить "графический -> ST" выглядит более понятным и позволит не ждать 2018-го года до первого тестирования ШД.
2) Компилировать в формат КДС диаграмм (из ST или из графического языка -- не так важно) только ради того, чтобы использовать "уже представленное ПО" выглядит как отвлекающей задачей, занимающей много времени без видимого результата. Гораздо проще вызвать команду процессора "условный переход", чем превращать разные ветки в CFC.
3) Некоторые блоки становятся ненужными, если компилировать программу целиком. Например, один и тот же код блока CTU_BYTE будет работать как в случае, когда на вход поступает константа, так и в случае, когда на вход переменная. Сам компилятор выберет необходимую команду процессора, и расход регистров/памяти будет зависеть не от имени блока, а от его фактического использования.
И пользователю просто: не нужно задумываться о множестве однотипных блоков, и при написании этого множества блоков не будет copy-paste ошибок.
Поэтому, у меня возник вопрос: "а что, если PRU0.prg генерировать непосредственно из бинарного кода PRU?"
Собственно, вопрос: действительно ли "задействование уже предоставленного ПО" это единственно возможный вариант создания PRU0.prg?
Действительно ли, формат PRU0.prg засекречен, и создание его внешними инструментами недопустимо?
Раз PRU0.prg нет, то будем тестировать блок ШД на эмуляторе.
"enable" будем подавать через "fast IN1", а параметры "количество импульсов" и "частоту импульсов" будем подавать через память PRU.
На мой взгляд, эксперимент удался. Импульсы генерируются, указанная длительность соблюдается.
Хорошо бы, конечно, в железе проверить, но тут не решён вопрос по PRU0.prg.
Попробую "проверенный" способ: кто-нибудь может пошевелить/поспрашивать ОВЕН на предмет возможности генерации PRU0.prg/PRU1.prg файлов из внешних программ?
Собственно, программа обрабатывающая блок ЩД:
Вложение 26283
Ничего хитрого.
Из нового -- блок WAIT_TICK, который делает так, чтобы наш блок ШД вызывался не чаще, чем указанный интервал.
LBCO -- команды, загружающие значения из "памяти PRU" в регистр. В эмуляторе берём и "пишем напрямую в память". Возможно, HOST_TO_PRU/PRU_TO_HOST немного по-другому будут работать, но на суть это не влияет.
В самом блоке WAIT_TICK использован метод УКП (универсального коэффициента подгона):
Вложение 26284
Выглядит жутковато, но тесты проходит: https://github.com/vlsi/pru-emulator...BlockTest.java
В тестах проверяется, что "полезная работа" стартует ровно раз в заданное время в комбинациях "cycleTime от 20 до 100" и "длительность тела цикла от 0 до 5".
Собственно берём наш блок ШД и начинаем его испытывать. Заранее скажу, что предыдущая версия блока оказалась неправильной.
Вот исправления, после которых блок начал проходить тесты:
Вложение 26285
Начинаем с одного импульса и задержки в "35 тактов", и затем после каждой пачки увеличиваем количество импульсов на 1 и длительность тоже на 1.
Т.е. сначала должен получиться 1 импульс длины 35, затем 2 импульса по 36, затем 3 импульса по 37 и так далее.
Для большего разнообразия, вход enable будем активировать после случайной задержки. Так сказать, попробуем застать блок ШД врасплох.
Собственно, результаты теста. Тут через _/‾ и ‾\_ схематично изображены фронты out сигнала.
_/‾33‾\_ означает, что на выходе out была единица 33 такта.
‾\_36_/‾ означает, что на выходе был ноль 36 тактов.
Самая первая цифра -- это задержка от перевода enable в true до фронта out (т.е. задержка того, пока цикл PRU докрутится и запустит генерацию).
Цифра в пределах ожидаемого
cycle: 35, quantity: 1. _15_/‾33‾\_
cycle: 36, quantity: 2. _46_/‾34‾\_36_/‾36‾\_
cycle: 37, quantity: 3. _27_/‾35‾\_37_/‾37‾\_37_/‾37‾\_
cycle: 38, quantity: 4. _22_/‾36‾\_38_/‾38‾\_38_/‾38‾\_38_/‾38‾\_
cycle: 39, quantity: 5. _30_/‾37‾\_39_/‾39‾\_39_/‾39‾\_39_/‾39‾\_39_/‾39‾\_
cycle: 40, quantity: 6. _17_/‾38‾\_40_/‾40‾\_40_/‾40‾\_40_/‾40‾\_40_/‾40‾\_40_/‾40‾\_
cycle: 41, quantity: 7. _26_/‾39‾\_41_/‾41‾\_41_/‾41‾\_41_/‾41‾\_41_/‾41‾\_41_/‾41‾\_41_/‾41‾\_
cycle: 42, quantity: 8. _48_/‾40‾\_42_/‾42‾\_42_/‾42‾\_42_/‾42‾\_42_/‾42‾\_42_/‾42‾\_42_/‾42‾\_42_/‾42‾\_
cycle: 43, quantity: 9. _50_/‾41‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_
cycle: 44, quantity: 10. _14_/‾42‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_
cycle: 45, quantity: 11. _38_/‾43‾\_45_/‾45‾\_45_/‾45‾\_45_/‾45‾\_45_/‾45‾\_45_/‾45‾\_45_/‾45‾\_45_/‾45‾\_45_/‾45‾\_45_/‾45‾\_45_/‾45‾\_
cycle: 46, quantity: 12. _20_/‾44‾\_46_/‾46‾\_46_/‾46‾\_46_/‾46‾\_46_/‾46‾\_46_/‾46‾\_46_/‾46‾\_46_/‾46‾\_46_/‾46‾\_46_/‾46‾\_46_/‾46‾\_46_/‾46‾\_
Если присмотреться, то можно заметить, что длина первого импульса почему-то на 2 такта меньше, чем заданная длительность.
Можно, конечно, раскуривать ассемблер и смотреть где там стоит добавить-убрать такт, но нужно ли? Кого реально парят 2 такта?
Минимально стабильная длина цикла для этой программы составляет 33 такта.
Частота PRU где-то 150-200 МГц, т.е. за одну микросекунду PRU выполняет ~200 команд.
Иными словами, данная программа может генерировать пачки импульсов частоты до 1МГц (выходы вряд ли смогут такое, но не суть).
PS Вот так на ассемблере выглядит финальная программа (на один экран не вместилось, поэтому 3 картинки):
Вложение 26286
Вложение 26287
Вложение 26288
У меня как дополнение к CDS, так и альтернатива.
С одной стороны, моя среда может генерировать КДС проект (это в случае управления простыми, "медленными" выходами), а с другой, она может генерировать бинарный код для TI PRU процессора (ну, того, что используется в ПЛК110 М02) -- т.е. можно писать программы для быстрых входов/выходов.
Вижу, что вы пытались в ответе написать какой-то код: < spf; i++){delay_us(50);}
Можете поправить ответ, чтобы код стало видно?
Вообще говоря, на PRU нет операций деления и, соответственно, квадратного корня, но есть память.
Поэтому, рабочий подход -- рассчитать табличку ускорений и работать по ней.
Доступ к памяти стоит 2-3 такта, т.е. в процессе управления можно просто читать очередную задержку и всё.
Т.е. вся сложность сводится к вычислению таблицы задержек по входным "начальной скорости, максимальной скорости и ускорению"
Вот, похоже, разумные стати по теме ШД: http://www.embedded.com/design/mcus-...s-in-real-time, http://www.atmel.com/images/doc8017.pdf, https://courses.cs.washington.edu/co...Arithmetic.pdf, http://www.orientalmotor.com/product...alculation.pdf
Если задержку делать непосредственно перед записью выходов, то длительности импульсов получаются вообще ровными:
Вложение 26299
Результат:
cycle: 33, quantity: 2. _56_/‾33‾\_33_/‾33‾\_
cycle: 34, quantity: 3. _24_/‾34‾\_34_/‾34‾\_34_/‾34‾\_
cycle: 35, quantity: 4. _41_/‾35‾\_35_/‾35‾\_35_/‾35‾\_35_/‾35‾\_
cycle: 36, quantity: 5. _47_/‾36‾\_36_/‾36‾\_36_/‾36‾\_36_/‾36‾\_36_/‾36‾\_
cycle: 37, quantity: 6. _43_/‾37‾\_37_/‾37‾\_37_/‾37‾\_37_/‾37‾\_37_/‾37‾\_37_/‾37‾\_
cycle: 38, quantity: 7. _39_/‾38‾\_38_/‾38‾\_38_/‾38‾\_38_/‾38‾\_38_/‾38‾\_38_/‾38‾\_38_/‾38‾\_
cycle: 39, quantity: 8. _55_/‾39‾\_39_/‾39‾\_39_/‾39‾\_39_/‾39‾\_39_/‾39‾\_39_/‾39‾\_39_/‾39‾\_39_/‾39‾\_
cycle: 40, quantity: 9. _46_/‾40‾\_40_/‾40‾\_40_/‾40‾\_40_/‾40‾\_40_/‾40‾\_40_/‾40‾\_40_/‾40‾\_40_/‾40‾\_40_/‾40‾\_
cycle: 41, quantity: 10. _51_/‾41‾\_41_/‾41‾\_41_/‾41‾\_41_/‾41‾\_41_/‾41‾\_41_/‾41‾\_41_/‾41‾\_41_/‾41‾\_41_/‾41‾\_41_/‾41‾\_
cycle: 42, quantity: 11. _54_/‾42‾\_42_/‾42‾\_42_/‾42‾\_42_/‾42‾\_42_/‾42‾\_42_/‾42‾\_42_/‾42‾\_42_/‾42‾\_42_/‾42‾\_42_/‾42‾\_42_/‾42‾\_
cycle: 43, quantity: 12. _51_/‾43‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_43_/‾43‾\_
cycle: 44, quantity: 13. _52_/‾44‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_44_/‾44‾\_
Нашёл пример Amtel'а.
Статья: http://www.atmel.com/images/doc8017.pdf (вариант на русском, который, кстати, более подробный: http://avrdoc.narod.ru/index/0-7 )
Код (MIT license == проблем нет): https://code.google.com/archive/p/st...or-controller/
Собственно, нужный код рассчёта задержек между импульсами: https://github.com/rob-smallshire/st...ntr.c#L77-L127
Там они, кстати, памятью не пользуются, а просто на каждом шаге вычисляют длительность очередного импульса.
По моим прикидкам, подобные вычисления будут занимать 300 тактов, т.е. порядка 2 мкс.
Собственно, вопрос: есть ли смысл заморачиваться с памятью и предвычислением, или достаточно, если минимальный импульс будет 3-4 мкс?