Спасибо прибористу за тестирование.
Собственно, лучше не скажешь:

Сообщение от
приборист
Поробовал, все заработало.
Скорость на ходу изменяет.
Вечером будет побольше времени потестировать.
Шах и мат?
Собственно, программа:
Код:
PROGRAM PRU_PULSE_GENERATOR
variables:
burst : PRU_GENER_BURST;
enable : BOOL;
cycleLength : WORD;
quantity : DWORD;
ready : BOOL;
qtyLeft : DWORD;
dataReady : BOOL;
controlRegisterAddress : DWORD;
currentCycles : WORD;
body:
(* безопасные значения *)
enable := FALSE;
cycleLength := 100;
quantity := 0;
WHILE TRUE DO
(* собственно полезная работа *)
burst(enable := enable, quantity := quantity);
controlRegisterAddress := 16#700C;
(* Пока есть время, передаём-принимаем данные *)
REPEAT
ASM
LBCO dataReady, 3, 0, 1
END_ASM
IF dataReady THEN
(* Приём *)
ASM
LBCO quantity, 3, 100, 4
LBCO cycleLength, 3, 104, 2
LBCO enable, 3, 108, 1
END_ASM
(* Передача *)
ready := burst.ready;
ASM
SBCO ready, 3, 112, 1
END_ASM
qtyLeft := burst.qtyLeft;
ASM
SBCO qtyLeft, 3, 116, 4
END_ASM
dataReady := FALSE;
ASM
SBCO dataReady, 3, 0, 1
END_ASM
END_IF;
ASM
LBBO currentCycles, controlRegisterAddress, 0, 2
END_ASM
currentCycles := currentCycles + 40;
UNTIL currentCycles < cycleLength
END_REPEAT;
(* Остаток задержки ждём более точно, без приёма-передачи *)
WAIT_TICK(pruCycleLength := cycleLength);
PRU_OUT1(Q := burst.out);
END_WHILE;
END_PROGRAM
Код:
FUNCTION_BLOCK PRU_GENER_BURST
variables:
input enable : BOOL;
input quantity : DWORD;
output out : BOOL;
output ready : BOOL;
retain output qtyLeft : DWORD;
body:
IF enable THEN
IF qtyLeft > 0 THEN
(* Идёт генерация *)
qtyLeft := qtyLeft - 1;
ELSIF ready THEN
(* Всё сгенерировали, ждём пока передёрнут enable для следующего включения *)
ELSE
(* Поступила команда на включение *)
qtyLeft := SHL(quantity, 1);
qtyLeft := qtyLeft - 1;
END_IF;
ready := qtyLeft = 0;
ELSE
(* Выключаемся *)
qtyLeft := 0;
ready := FALSE;
END_IF;
(* Если всё сделали, то out выключится. Если пачка ещё генерируется, то младший бит и есть меандр *)
out := qtyLeft.0;
Код:
FUNCTION_BLOCK WAIT_TICK
variables:
input pruCycleLength : WORD;
cyclesLeft : WORD;
currentCycles : WORD;
controlRegisterAddress : DWORD;
body:
(* 0x00007000..0x00007FFF -- PRU0 Control Registers, 0xC -- cycle count register *)
controlRegisterAddress := 16#700C;
ASM
LBBO currentCycles, controlRegisterAddress, 0, 2 ; Load cycle count, 1+wdcnt*1==2 cycles
END_ASM
currentCycles := currentCycles + 8;
IF pruCycleLength > currentCycles THEN
cyclesLeft := pruCycleLength - currentCycles;
cyclesLeft := cyclesLeft XOR 0;
IF cyclesLeft.0 THEN
cyclesLeft := cyclesLeft XOR 1;
END_IF;
WHILE cyclesLeft <> 0 DO
cyclesLeft := cyclesLeft - 2;
END_WHILE;
ELSE
cyclesLeft := 0;
END_IF;
ASM
SBBO cyclesLeft, controlRegisterAddress, 0, 2 ; Load cycle count, 1+wdcnt*1==2 cycles
END_ASM