ASC returns the character's code as a number; decimal 65 and hex 41 are the same byte, so there is nothing to convert. Put the first character's code in each word's high byte and the second in the low byte, then block-move exactly two packed words to the tag start. If the panel shows each pair reversed, swap the H and L selectors.
Your ASC function has been returning the right numbers all along. A character code is one value, and 65 in decimal and 41 in hex are two printouts of the same eight bits, so there is nothing to convert before the string lands in V-memory. The job is layout: two codes per 16-bit word, first character in the high byte, second in the low byte, then one block move that puts the packed words on the tag's start address. For the four-character tag at V1260 and V1261 that move is exactly two words. This article walks the packing lines, works a four-character example through to the numbers the memory monitor should show, and gives checks that tell a byte-order problem apart from a block-move or tag-format problem.
Why does ASC return decimal when your tag wants hex characters?
You do not convert anything: ASC already returns the number the tag needs. The letter A is one code, 65 in decimal and 41 in hex, the same eight bits either way. The real job is placing that code in the right byte of the right word.
The base is only a printout. A memory monitor set to hex shows 41 where a decimal screen shows 65, and the panel's dynamic text object reads neither printout: it reads the byte and renders the character that code names. That is the same behavior behind displaying ASCII from integer words on an HMI, and it is why a tag described as holding "4 ASCII chars in hex" needs no conversion routine. It needs the codes placed two per word.
How do two characters fit into one V-memory word?
Two 8-bit codes share one 16-bit word: the first character goes in the high byte and the second in the low byte, so the word value is first code × 256 + second code. AB packs to 65 × 256 + 66 = 16706.
A V-memory word holds sixteen bits, which is two bytes, and the high byte carries its code at 256 times the weight of the low byte. 16706 prints as 4142 on a hex monitor, and that hex printout is what the tag description was pointing at. One tag spread over consecutive words is a standard arrangement: displaying a PLC float stored in two word registers puts a different kind of value across the same kind of pair.
What do you need before you write the packing loop?
Four things: the tag's start address and character count from the panel (here V1260, four characters), string space in the BASIC program (STRING 2551,254 in the sample program), the two byte selectors H and L, and a block move that lands exactly two words on V1260.
The start address and character count sit in the panel's tag configuration; confirm them first, because the packing has no other source of truth. The module in this job is a BASIC coprocessor, and the sample program allocates string space with STRING 2551,254. H and L are the byte selectors the sample loop uses, high byte and low byte. If the panel rejects the tag address itself, fixing HMI invalid address errors when tagging PLC memory comes first, because a tag that cannot reach V-memory renders nothing you pack.
Which lines pack two characters per word?
Four lines do the packing: a FOR loop steps through the string two characters at a time and writes the first code of each pair with the H selector, the second with the L selector, while one BMOVE line carries the packed words to V-memory.
10 STRING 2551,254 : REM allocate string space (sample line)
20 S="AB12" : REM this job's four-character test value
30 FOR X=1 TO LEN(S) STEP 2 : REM sample loop
32 DPORT((X-1),H)=ASC(S,X) : REM first character of the pair, high byte
34 DPORT((X-1),L)=ASC(S,X+1) : REM second character of the pair, low byte
36 NEXT X
40 BMOVE W,VH(2000),K(LEN(S)) : REM sample's own destination and count
H and L name byte positions inside the word, not number bases: line 32 drops the first character's code into the high byte and line 34 puts the second code into the low byte. The STEP 2 advance is what makes two characters per pass. Keep the displayed string at an even length, because every pass reads positions X and X+1. A four-character value runs the loop twice with two characters on each pass, while an odd length leaves the last pass asking for a character the string does not have, so pad with a trailing space and keep the length fixed.
How does the example play out with the tag at V1260?
The four-character string AB12 becomes two words: V1260 holds 65 × 256 + 66 = 16706 and V1261 holds 49 × 256 + 50 = 12594. The block move writes exactly those two words, and the panel renders AB12.
LEN(S) returns 4, so the loop runs two passes. Pass one writes 65 to DPORT(0,H) and 66 to DPORT(0,L); pass two writes 49 and 50 into the next pair of byte positions. The buffer now holds the words 16706 and 12594, in that order.
The count decides how much moves. The tag spans exactly two words, and four characters at two bytes per word is 4 ÷ 2 = 2 words, so set the move for two words. The sample's count expression K(LEN(S)) evaluates to 4 here, and a count of 4 read in words would move two words beyond V1261 into V1262 and V1263, so make the count match the two-word tag before the move runs in production.
| Item | Value |
|---|---|
| Test string | AB12, four characters |
| Codes in decimal | 65, 66, 49, 50 |
| Codes in hex | 41, 42, 31, 32 |
| V1260 | 65 × 256 + 66 = 16706, printed 4142 in a hex monitor |
| V1261 | 49 × 256 + 50 = 12594, printed 3132 in a hex monitor |
| Panel display | AB12 |
With the destination pointed at the tag start, the panel's dynamic text object, configured for four characters, decodes both words high byte first and shows AB12.
Recommendation: for a four-character tag at V1260, pack with the H selector first and the L selector second, block-move exactly two words to the tag start, and leave the loop and the move untouched. If the rendered characters come back swapped inside each pair, swap the H and L assignments once and retest.
How do you check the result on the panel?
Check in order with a known test value: confirm the two packed words, then the two destination words, and only then read the rendered text, so a wrong display points straight at the layer you skipped.
- Set S to a known four-character test value and confirm LEN(S) returns 4.
- Run the packing loop and read the two buffer words: they must show 16706 and 12594 for AB12.
- Run the block move and read V1260 and V1261: the same two values, word for word.
- Open the panel's tag and confirm the start address V1260, four characters, and the byte order the object decodes.
- Change the string a few times and watch the text update; keep the packing of both words ahead of the move so the panel never renders one new byte beside one old byte.
If the object shows nothing at all, the first suspect is the address, and checking the tag address first when an HMI display shows nothing walks that check in order.
Why do the characters come back swapped or in the wrong order?
Swapped characters inside each pair point at byte order, wrong pairs in the wrong words point at the move or the tag address, and a correct V1260 with wrong text points at the tag's character count or data format.
- Each pair reversed, BA12 for AB12: the panel reads the low byte first. Swap the H and L assignments in lines 32 and 34 and retest; nothing else changes.
- Pairs in each other's places, 12AB: the words themselves traded positions, so compare V1260 and V1261 word for word with the buffer and check the move's destination against the tag start.
- Words correct, text still wrong: the tag is configured for the wrong character count or data format, so set the tag to four characters at V1260.
- Garbage after the fourth character or over neighboring data: the move carried more words than the tag spans, so set the transfer to two words.
Change one layer per test and the memory monitor tells you which layer broke: the codes, the packing, the move or the tag.
Questions
Why do 16706 and 12594 look wrong to a coworker checking in decimal?
Both are right: 16706 and 12594 are the decimal printouts of the same two words a hex monitor shows as 4142 and 3132. The base setting changes the display, never the stored bits. The panel decodes the bytes as AB12 from either screen, so nothing needs rewriting. Agree on one monitor base and move on.
What happens if the live string is longer or shorter than four characters?
The panel reads only the two words the tag spans, so a fifth character packs into a word after V1261 and can overwrite whatever lives there. Pad a shorter value with spaces so LEN stays at 4, and gate the routine on string length before the loop runs. For a longer live string, resize the tag to span the words the string actually needs.
Can the ladder program fill the same tag instead of the BASIC module?
Yes. The layout decides, not the writer: put the first character's code in the high byte and the second in the low byte, compute first code × 256 + second code, then move that value into V1260 and the next pair into V1261. Any source that keeps the byte order the panel decodes renders the same four characters.
Does the panel ever write characters back into V-memory?
Yes. The panel's text entry object lets an operator type characters into the tag registers through a pop-up keypad, and those registers then hold the same two bytes per word. If you pass the entry on to a log or another screen, unpack each word high byte first, the mirror image of the packing loop.
Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.