📄 tiny_plc.txt
字号:
<reg> must be a COUNTER
CTF 0x30 <reg> <B0> <B1> If previous scan was TRUE and rung
is FALSE, update counter and flags.
Outputs DONE to rung
<reg> must be a COUNTER
TMT 0x32 <reg> <B0> <B1> If rung is TRUE update timer and set
flags else reset timer.
Outputs DONE to rung
<reg> must be a TIMER
TMF 0x34 <reg> <B0> <B1> If rung is FALSE update timer and
set flags else reset timer.
Outputs DONE to rung
<reg> must be a TIMER
RTMT 0x36 <reg> <B0> <B1> If rung is TRUE update timer and set
flags. Outputs DONE to rung
<reg> must be a TIMER
RTMF 0x38 <reg> <B0> <B1> If rung is FALSE update timer and
set flags. Outputs DONE to rung
<reg> must be a TIMER
RESET 0x3a <reg> If rung is TRUE reset timer/counter
<reg> must be a COUNTER or TIMER
INVERT 0x3b invert truth of rung
TinyPLC communications protocol:
The TinyPLC communications protocol is a simple master/slave
protocol (the PC is the master, the processor board is the slave --
message exchanges are only initiated by the master) built on
RS-232 (serial) communications at 9600 baud, 8N1. The baudrate
may be changed by changing the TINYPLC.H file.
The first two bytes of a message are signature bytes,
Byte 0 = 0x55
Byte 1 = 0xaa
The next byte is the command byte. The legal values are:
MSG_RUN = 0x00
MSG_STOP = 0x01
MSG_GETREGS = 0x02 -- only partially implemented
MSG_NUMSTEPS = 0x03 -- only partially implemented
MSG_PROGRAM = 0x04
MSG_PROGSTATUS = 0x05 -- only partially implemented
MSG_ACK = 0x06
The next two bytes are the length of any additional data (little-endian).
This is non-zero only for MSG_NUMSTEPS and MSG_PROGRAM.
RUN message:
The RUN message tells the TinyPLC kernel to set the "soft run" flag,
useful when uploading a new program (which clears the "soft run"
flag).
The complete message is:
55 AA 00 00 00
TinyPLC response: ACK message
STOP message:
The STOP message tells the TinyPLC kernel to clear the "soft run"
flag.
The complete message is:
55 AA 01 00 00
TinyPLC response: ACK message
GETREGS message:
The GETREGS message is intended for debugging / tracing the execution
of a TinyPLC ladder program. It returns the PROGSTATUS information and
the contents of the TinyPLC registers (INPUTS, VARS, COUNTERS, etc).
The complete message is:
55 AA 02 00 00
The response is a set of binary data bytes (little-endian):
1 byte: line truth value
1 byte: run flag (OK to run the current program)
1 byte: debug flag (running with node count, BRK active (see above))
1 byte: program IP, low byte
1 byte: program IP, high byte
1 byte: program valid flag
1 byte: program length, low byte
1 byte: program length, high byte
4 * PLC_MEMORY_LOCS bytes: TinyPLC data registers (little-endian)
I consider this only partially implemented, as PLC.EXE does not support
it, not enough data is returned, and it is not in the "correct" format.
The correct format should be:
55 AA <GETREGS_RESPONSE> <len low> <len high) <databytes>
<checksum low> <checksum high>
NUMSTEPS message:
Set the number of ladder nodes to execute before stopping. Useful
for debugging and tracing.
Message format:
55 AA 03 02 00 <count low> <count high>
I consider this only partiall implemented, as PLC.EXE does not support
it, and it is not in the "correct" format. The correct format should
be:
55 AA 03 04 00 <count low> <count high> <checksum low> <checksum high>
TinyPLC response: ACK message ONLY IF count is not 0
PROGRAM message:
Send a program to the TinyPLC kernel. If valid (checksum is OK),
it is saved in RAM and EEPROM. Note that the length field includes
both the program and the 2 bytes of the checksum.
Message format:
55 AA 04 <len low> <len high> <program...>
<checksum low> <checksum high>
TinyPLC response: ACK message ONLY IF checksum is valid
PROGSTATUS message:
Get status from TinyPLC kernel.
The complete message is:
55 AA 05 00 00
The response is a set of binary data bytes:
1 byte: line truth value
1 byte: run flag (OK to run the current program)
1 byte: debug flag (running with node count, BRK active (see above))
1 byte: program IP, low byte
1 byte: program IP, high byte
1 byte: program valid flag
1 byte: program length, low byte
1 byte: program length, high byte
I consider this only partially implemented, as PLC.EXE does not support
it, not enough data is returned (among other things, TinyPLC kernel
version should be returned, so that PLC.EXE does not try to program
an incompatible kernel), and it is not in the "correct" format.
The correct format should be:
55 AA <PROGSTATUS_RESPONSE> <len low> <len high) <databytes>
<checksum low> <checksum high>
ACK message:
ACK is returned from the TinyPLC kernel to PLC.EXE to acknowledge
a valid message.
The complete message is:
55 AA 06 00 00
General comments:
While TinyPLC works, a number of mistakes were made in it's design
and there was no time to fix them.
For example, when saving / restoring a ladder, the rungs array of
structures is saved. Which includes the element_info structure.
Which includes function pointers. So any trivial change will change
the locations of the functions. Which means that when the saved
ladder is read in, the pointers to functions will point to random
memory. Oops... This has been patched, but it should be really
fixed by making the function pointers in element_info into indices
into an array of function pointers (so the addresses are controlled
by the PLC program, not the contents of a data file).
PLC.EXE referrs to modbus_dataregs. The original plan was to
implement modbus (www.modbus-ida.org) for programming and passing
data regs (and other info) back and forth. But I did not have time
to implement modbus, nor trace / breakpoint facilities. It should
be either fully implemented or removed.
Since TinyPLC was supposed to be a small part of the control system,
it was written to leave most of the system available for the "real"
control system. However, since TinyPLC is standing on it's own, it
can (and probably should) be enlarged to take better advantage of
the hardware. For example, although there is 4K of EEPROM available,
only 1K (plus a few bytes) are allocated to TinyPLC.
Only 256 data registers are used. Part of this is the desire to
keep the RAM footprint small, part of it is the desire to keep the
downloaded ladder program small. More registers means longer
register fields means longer programs. Moreover, the next "logical"
length for a register address is 16-bits, to keep everything on a byte
boundary. For shorter than 16, but more than 8 bit register indices,
since there can be 1, 2, or 3 registers per instruction, where do you
put "extra" bits that do not take up a full register? And it would
make instruction decoding more more complex. However, since there
will not be 64K registers available, slightly more complex logic
is needed to make sure that register indices are in range.
Also note that if you allow more than 256 data registers, you can
easily wind up doubling the size of an otherwise identical program
(more bytes for register addresses), and so would quickly use up all
the extra EEPROM space you are now using.
The software version number of the TinyPLC kernel should be added to
the PROGSTATUS message, and PLC.EXE should read this before downloading
software, to make sure that PLC.EXE and the target TinyPLC kernel are
compatible.
It was planned to allow for animation of the ladder execution in
PLC.EXE -- that's why all objects have both a label and an overlay
(the overlay could be in colors, such as GREEN and RED showing TRUE
and FALSE). However, I didn't have time to write that, so the "hooks"
are present, but not complete. They need to be finished and expanded
for that functionality.
How to get back full information for animation (debugging) of ladder
execution raises some questions -- what information is needed and
how do I get it back? Do I execute one node at a time? That will
give me a running view of the TRUE / FALSE values of the nodes, but
means that execution will be very slow. And, I have only included a
way to gather ALL registers, not selected registers, so it will be
very wasteful to get a full set of registers when only 1 has been
changed at any node.
If you allow multiple nodes to run (the idea of LineStep in the
PLC menu) between updates, you have to find (or compute) the
TRUE / FALSE value of all nodes, which means that you have to
emulate the ladder in PLC.EXE from the previous register data, or
track execution results in the TinyPLC kernel. Both will work,
but will require a lot of programming.
It would be nice to be able to "print" a ladder. This could be
done by haveing show_ladder() write the ladder to a file as an
uncompressed graphic (.BMP, .TIF, .TGA). This would be fairly
simple, though you would have to watch out for file formats that
put the last line of the graphic at the top of the file (.BMP does
this, .TGA has a header option that turns this puts the top line of
the graphic at the top of the file, but it is often ignored by software,
I do not know about .TIF files).
The programs CHAR16X8.EXE and CHAR8X8.EXE are "helper" programs
that change the .CHR files from CHEDIT.EXE (see below) into data
declarations for PLC.EXE. They are used in the format:
CHAR16X8 16X8_LWR.CHR >BIGSTUF
CHAR16X8 16X8_UPR.CHR -U >>BIGSTUF
CHAR8X8 8X8.CHR >SMALSTUF
and then the files BIGSTUF and SMALSTUF are put into BIGCHAR.H
and CHARSET.H in place of the current data declarations.
The program CHEDIT.EXE is something I wrote many (20!) years ago.
Although not widely known, CGA grapics allowed for 128 programmable
characters. The problem was how to get the character data. My
solution was CHEDIT (CHaracter EDITor). CHEDIT is also written in
DeSmet C, and if I come across the source code (it should be
SOMEWHERE), I'll open that up too.
So, when I needed to do text and simple icons in graphics, rather
than reinvent the wheel, I used the work I had done long ago --
already created character sets and the ability to easily create
new characters. Just add some simple STROUT() routines, and my
screen I/O was done.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -