Lynn's Industrial Automation Protocol Tips
Home > Rockwell > PCCC_Tips >
IP-Enable Blog
White Papers
Digi Product Tips
Yahoo Group
Contact Info

The information on this web page is either Lynn's opinion or something Lynn agrees with. He has complete control over its contents. Nothing contained within this pages is approved by or represents the opinion of Digi International, The Modbus Organization, the Modbus-IDA Group, ODVA, or any other organization Lynn is associated with.

AB/PCCC Protocol Tips

Question? What does PCCC stand for?

Answer: PCCC is the 'Application Layer Message Packet' of DF1

It is also referred to as PC-cubed. I'm not sure what it really stands for - a good guess would be Programmable Controller Communication Commands. These are the 'Application Layer Message Packets' as shown in the on-line DF1 Manual Chapter 6. AB people do not include the DST/SRC bytes when they speak of PCCC - these 2 bytes are really the DF1 header attached before a PCCC message.

Basically, PCCC lets you issue legacy poll/response messages to arrays of data. It is the core message that moves easily between DF1, DH485, DH+, AB/Enet and Ethernet/IP with PCCC encapsulation. Each form likely has its own header format.

return to top

Question? Why might SLC500 style messages fail on some PLC?

Answer: SLC500 use the 'Protected Typed Logical Rd/Wr with 3 Address Fields.

These commands have 5 byte-sized parameters: byte count, file number, file type, element number, and sub-element number. The DF1 spec mentions that 3 of these (file number, element & sub-element number) may be 'escaped' with the value 0xFF to expand them to a 3-byte field for values larger than 254. So for example, table number 300 would be coded as the 3 bytes: 0xFF 0x2C 0x01. 0xFF is the escape flag, and 300 is 0x012C represented as little-endian. So far so good, however it appears that AB/Ethernet supports messages larger than DF1, for example 200 words or 400 bytes of data. So when accessing some Ethernet PLC, masters/clients will escape the byte count field to support counts larger than 254 bytes.

One issues is that some smaller or older PLC will not accept these escaped fields in certain cases. Suppose an AB/Ethernet client has the bad habit of always escaping the fields, then a poll of just 10 bytes will come over as 0xFF 0x0A 0x00. This is in theory legal, but if bridging to DF1 even a SLC5/05 that accepts this by Ethernet will reject it on the DF1 port.

So Clients should ONLY use these 3-byte escapes if required - values from 0 to 254 should be sent as singe bytes and not 3-byte sequences.

return to top

Question? How can I send the DST byte with PCCC in Ethernet/IP?

Answer: this depends on the service used.

The normal header for service 0x4B only has info about which client sent the request - it has NO dst info. This is the service normally used by ControlLogix MSG blocks if you just ask it to send a PLC2, PLC3, PLC5, or SLC type message. So these cannot map to DF1 with specific DST bytes. A Digi DS/TS that receives this will assume DST = 1 on the DF1.

Service 0x4C (seen when 2 ENI talk to each other) includes an 8-byte header that appears to include both the SRC & DST info. This allows 2 ENI to "tunnel" DF1 and retain the addressing. If you change the ControlLogix MSG block (of type PLC2-SLC) from 'CIP' to 'CIP with Source Id', then you change it to use this service 0x4C. The 8-byte header (per ControlLogix MSG Block) is of the form AAAA BB CC DDDD EE FF. AAAA is the MSG block field 'Destination Link' as Little-Endian word in the range 0-65535. BB is the MSG block field 'Destination Node' as byte in the range 0-63. DDDD is the MSG block field 'Source Link' as Little-Endian word in the range 0-65535. EE I am assuming would be called the 'Source Node' - but it's not included in the ControlLogix MSG block. CC and FF seem to be 0 - I'd guess they are some form of 'sub-node' address. A Digi DS/TS that receives this service will properly use the DST and SRC info from this header. It prefers the DST/SRC 'node' fields, but uses the low-byte of the DST/SRC 'link' field if the node field is zero.

Since a pair of ENI can tunnel DF1 using service 0x4C, I'd guess you can tweak the DST byte of the DF1 from ControlLogix MSG blocks by using this 'CIP with Source Id' option, but I have NOT tried this yet.

return to top

Question? How is ST data moved on the wire?

Answer: one ST element is moved as a 84-byte structure.

At least on the MicroLogix and SLC500 I've worked on, this is a structure of one little-endian 16-bit 'length' value followed by 82 bytes of string data. The string is usually null-padded, but i do seem to remember one system that used space padding. So if you use a MSG block to move 1 string element to a remote N table, it will overwrite 42 words of data.

Recent work on ControlLogix shows that it moves strings (ST) with a 32-bit 'length' instead. Hmmmm, some major lack of Engineering Control here. Too bad the ControlLogix and Packaged-Controller (SLC/MLgx) groups couldn't have gotten togather and agreed to stick to one design - to use either a 16-bit or 32-bit length field.

return to top

Question? What are some sample PCCC polls?

Answer: Depends on the master/client.

Below XX-XX is the TNS and N7:0 = 0x1234.

Kepware with DF1 encapsulation driver:

  • SLC 5/05 Open read of N7:0, Req=0F 00 XX-XX A2 02 07 89 00 00, Rsp=4F 00 XX-XX 34 12
  • PLC5 Family read of N7:0, Req=0F 00 XX-XX 01 00 00 01 00 06 07 00 02, Rsp=4F 00 XX-XX 34 12

Kepware with AB/Ethernet driver:

  • SLC 5/05 Open read of N7:0, Req=0F 00 XX-XX A2 02 07 89 00 00, Rsp=4F 00 XX-XX 34 12
  • PLC5 Family read of N7:0, Req=0F 00 XX-XX 01 00 00 01 00 06 07 00 02, Rsp=4F 00 XX-XX 34 12

Kepware with ENI driver:

  • SLC5-Open read of N7:0, Req=0F 00 XX XX A2 02 07 89 00 00, Rsp=4F 00 XX XX 34 12
  • ENI-PLC5 read of N7:0, Req=0F 00 XX XX 01 00 00 01 00 06 07 00 02, Rsp=4F 00 XX XX 34 12
  • PLC5-Style read of N7:0 as a word: 0F 00 XX XX A2 02 07 89 00 00

return to top

Question? What are the best commands to use for SLC5/MicroLogix?

Answer: The best commands for SLC5/MicroLogix controllers are:

  • Protected Typed Logical Read with 3-Address Fields (Cmd=0x0F, SubFnc=0xA2)
  • Protected Typed Logical Write with 3-Address Fields (Cmd=0x0F, SubFnc=0xAA)
  • Protected Typed Logical Masked-Write with 3-Address Fields (Cmd=0x0F, SubFnc=0xAB)
  • Protected Typed Logical Read with 2-Address Fields (Cmd=0x0F, SubFnc=0xA1)
  • Protected Typed Logical Write with 2-Address Fields (Cmd=0x0F, SubFnc=0xA9)

Only the first two (0xA2/AA) are documented in the official DF1 protocol specification. The third (0xAB) is not documented but is commonly used by OPC servers; in fact a Rockwell engineer formally sent me details of it when I asked; it is not considered "secret".

The last two (0xA1/A9) are only of value if you're creating a slave driver since a few of Rockwell's software tools assume these are supported. While they are not documented in the DF1 specification, RSLogix5000 outlines support for them as part of its legacy support for PCCC messages. But there is no reason for an OPC server or master to use 0xA1/A9 since support by slaves is not universal. Using SubFnc 0xA1 instead of 0xA2 just drops one unrequired NULL byte from the command, so is of modest value. For example, to read N7:1 your Read command would include the 6 bytes "A2 02 07 89 01 00" for the 3-Address Fields form and only the 5 bytes "A1 02 07 89 01" for the 2-Address Fields form. Big deal, eh? Well, yes - a big deal if you try to use 0xA1 with a slave that doesn't understand 0xA1.

return to top

Question? How do I write single bits on a SLC5/MicroLogix?

Answer: use the undocumented (but well supported) Cmd=0x0F SubFnc=0xAB Masked Write

The command looks much like the documented Protected Typed Logical Write with 3-Address Fields (Cmd=0x0F, SubFnc=0xAA) except you'll find an added 16-bit word of data. So here are examples of each:

  0xAA 02 03 85 00 00 01 00
  0xAB 02 03 85 00 00 01 00 01 00
  0xAB 04 03 85 00 00 01 00 01 00 00 00

The first command (0xAA) in effect clears bits B3:0/1 to B3:0/15 and sets bit B3:0/0. So the entire first word of the B3 table is changed - often not the desired action. In contrast, the second command (0xAB) just sets B3:0/0 to 1 without affecting the other 15 bits of B3:0. Notice that the 16-bit "mask" is not included in the byte count of 2. The third command (0xAB) shows that more than one data word can be sent, but there is always just a single 16-bit mask. The third command would set B3:0/0 to "1" and clear B3:1/0 to "0". If you - for example - desire to set both bits B3:0/0 and B3:1/6 to "1", then you'd need to issue two separate commands since they don't share the same 16-bit mask.

return to top