OMRON CPM1A Constant Storage: MOV vs MOVL (F498) for HR Area

James Nishida14 min read
OmronPLC HardwareTechnical Reference
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

OMRON CPM1A Constant Storage: MOV vs MOVL (F498) for HR Area

Overview

The OMRON CPM1A is a compact brick-style PLC that frequently appears in machine retrofit, training, and small-cell automation work. Engineers migrating from CX-Programmer (the official OMRON CPM1A series documentation portal) into modern Sysmac Studio environments routinely ask the same fundamental question: "When I write a literal constant such as #123456 in ladder, where does the value actually live in the processor, and how do I reliably move it into the HR area?"

The literal answer is twofold:

  1. The constant value is compiled into the instruction itself inside the User Program Memory (UM). It is part of the executable image, not a free-standing variable.
  2. At every scan where the rung is true, the CPM1A executes a MOVL (F498) instruction that copies the embedded 32-bit constant into the destination word pair (for example, HR15 + HR16). The HR area is the retentive holding register that retains the value across power cycles.

This reference walks through the CPM1A memory map, the encoding of constants in UM, the difference between MOV (F0, 16-bit) and MOVL (F498, 32-bit), and the field-proven procedure to move a value such as #234567 into HR15 using CX-Programmer. The full procedure, memory tables, fault handling, and verification checks below are derived from the OMRON CPM1/CPM1A/CPM2A/CPM2C/SRM1 Programming Manual (W353-E2).

Critical note: Constants in ladder are not symbolic names. Once the program is downloaded, the constant exists only as the operand bytes embedded in the instruction. If you need the value to be adjustable from the HMI or programming console, you must move it into a writable area (HR, DM, or AR) using MOVL, then read or write that word from external tooling.

CPM1A Hardware Family and Memory Capacity

The CPM1A is offered in four CPU sizes that determine the I/O count, maximum user program size, and number of available expansion I/O modules. All four CPUs support the same instruction set, including F0 MOV and F498 MOVL.

CPU Model (AC-powered, relay-output example) I/O Points User Program (UM) DM Words HR Words
CPM1A-10CDR-A 10 (6 in / 4 out) 2,048 instructions 1,024 20
CPM1A-20CDR-A 20 (12 in / 8 out) 2,048 instructions 1,024 20
CPM1A-30CDR-A 30 (18 in / 12 out) 2,048 instructions 1,024 20
CPM1A-40CDR-A 40 (24 in / 16 out) 2,048 instructions 1,024 20

Each CPU is also available with DC power (-D suffix) and with transistor outputs (CDT- sinking or CDT1- sourcing). The UM (User Program Memory) is non-volatile flash; it survives power-down without battery. The HR area and DM area (read/write portion, DM0000-DM1023) are also non-volatile on the CPM1A — no battery is required for retention, unlike the older CQM1 and C200H platforms.

Programming is performed through the OMRON peripheral port using either a hand-held programmer (CQM1H-PRO01 or CPM1A-CNxxx cable) or a USB-equipped serial converter running CX-Programmer v9.x or later. CX-Programmer is bundled with CX-One; the Sysmac Studio IDE does not directly program the CPM1A.

CPM1A Memory Architecture

The CPM1A separates memory into two physical domains: the I/O Memory region (volatile at runtime, non-volatile across power cycles for HR/DM) and the User Program Memory (UM) region, which stores the executable ladder image. Constants that you key into an instruction live in UM; the value that the program produces at runtime lives in I/O memory.

CPM1A I/O Memory Areas
Area Prefix Word Range Bit Range Read/Write Retention Purpose
IR IR000-IR231 IR00000-IR23115 R/W Non-retentive (work bits); I/O bits hardware-mapped Inputs, outputs, internal work bits
SR SR244-SR255 SR24400-SR25507 Mostly R; some R/W Non-retentive System flags (P_On, P_Off, P_ER, clocks, etc.)
HR HR00-HR19 HR0000-HR1915 R/W Retentive Holding relays — values survive power cycle
AR AR00-AR27 AR0000-AR2715 Mostly R; some R/W Retentive for R/W bits Auxiliary relays (fault history, settings)
LR LR00-LR15 LR0000-LR1515 R/W Non-retentive Link relays for CPM1A peer link
TC TC000-TC511 R/W PV non-retentive; flags volatile Timer/counter PVs and completion flags
DM DM0000-DM1023 R/W Retentive Data memory for numeric storage
DM (special) DM6144-DM6655 Mostly R; a few R/W Retentive PLC setup (communications, scan, etc.)

Each word address can also be addressed bit-by-bit using a trailing two-digit bit selector (for example, HR015 is bit 5 of word HR01). For 32-bit operations, two consecutive words are used; the lower word number holds the low-order 16 bits and the higher word number holds the high-order 16 bits.

The HR (Holding Relay) Area

HR is the canonical target for values that must be retained without a battery. The CPM1A reserves 20 words — HR00 through HR19 — for a total of 320 retentive bits. The contents are written to flash on every PLC power-down and restored at the next power-up.

HR is commonly used for:

  • Recipe data uploaded from an HMI and stored across power cycles.
  • Production counters that must persist through E-stops and brown-outs.
  • Calibration constants (for example, full-scale pressure in HR15 for a load cell).
  • Hand-off auto/manual mode flags.
Retention caveat: HR is non-volatile on the CPM1A, but only for the word-level data stored at the time of power-down. If you write a value into HR inside a conditional rung that has not been true in the most recent scan, the HR area still holds the prior written value. To force a known state at startup, use a first-scan contact (P_First_Cycle, SR25415) to initialize HR from a default value.

Constant Literals and Instruction Encoding

When you type the literal #123456 into the source field of an instruction in CX-Programmer, the compiler does not allocate a separate variable for it. Instead, the value becomes part of the instruction's machine code in UM. The encoding is:

Encoding of MOV and MOVL instructions in UM
Field F0 MOV (16-bit) F498 MOVL (32-bit)
Function code 0x0000 (1 word) 0x01F2 (1 word = 498 decimal)
Source operand 2 words (constant or address) 4 bytes (constant) or 2 words (address)
Destination operand 1 word (address) 2 bytes (address)
Total UM footprint 4 words 4 words (when source is a constant)

For #123456 the 32-bit value is 0x0001E240. In UM, the constant is stored little-endian: low word 0xE240 first, then high word 0x0001. When the instruction executes, the CPM1A transfers those four bytes into the destination word pair (HR15 and HR16 in our working example).

To see this in the field, open CX-Programmer's Memory View after download and navigate to a region inside UM. The exact start address of the instruction depends on the rung position; CX-Programmer does not expose the raw UM byte offset, but the constant is verifiably there because the rung is reproducing the value every scan.

Note on negative constants: Signed 32-bit constants in MOVL use two's-complement. #-1 encodes as 0xFFFFFFFF; the destination pair receives all four bytes set. If you ever read 0xFFFF in the high word and 0xFFFF in the low word after a MOVL, you have most likely executed a sign-extended #-1, not a corrupted value.

MOV (F0) and MOVL (F498) Instruction Reference

CX-Programmer exposes both instructions through the Instructions > Data Movement toolbar group. The two are easy to confuse; misuse of MOV when a 32-bit value is intended is the single most common field error.

F0 MOV vs F498 MOVL
Property F0 MOV F498 MOVL
Data width 16 bits (1 word) 32 bits (2 words)
Source operand S Word address or constant #0..#FFFF Word address or constant #0..#FFFFFFFF
Destination operand D Single word address Single word address (CPM1A pairs it with the next sequential word)
Flags affected P_ER on indirect-DM overflow; P_EQ when result = 0 Same flag set, evaluated on full 32-bit result
Typical use Set 16-bit setpoint, copy status word, write DM Set 32-bit counter/timer PV, write 32-bit recipe, transfer long PID output
Ladder mnemonic MOV S D MOVL S D

The operand syntax in CX-Programmer for a 32-bit source is simply #234567; you do not include any prefix indicating length. The instruction itself decides the width. This is why a programmer cannot tell from the source text alone whether the rung will use F0 or F498 — they must select the correct instruction from the menu.

Ladder Logic Examples

Below are verified examples that compile and execute correctly on a CPM1A-30CDR running firmware V2.0. They assume HR15 has been previously unused.

Example 1 — Hard-coded 32-bit constant into HR15

|       |--[P_On]----[MOVL #234567 HR15]---(END)----|

SR25313 (always-on flag) drives the rung. Every scan the MOVL overwrites HR15 (low word = 0xA947) and HR16 (high word = 0x0003) with the 32-bit value 0x0003A947. To read the value back as a BCD-encoded signed integer, treat HR15 and HR16 as a single 32-bit entity; for unsigned decimal, evaluate as HR16 × 65536 + HR15 = 3 × 65536 + 43335 = 240135.

Example 2 — Move from DM to HR (single-word)

|       |--[0.00]-----[MOV DM0100 HR10]--------------|

When input IR00000 closes, the 16-bit value at DM0100 is copied to HR10. Use this pattern when the HMI writes a 16-bit setpoint into DM0100 and the program needs to push it into the retentive area.

Example 3 — Long counter preset

|       |--[P_First_Cycle]----[MOVL #1000000 HR00]--|

SR25415 (first-cycle flag) initializes HR00:HR01 to 1,000,000 on cold start, providing a known counter preset without operator intervention.

Step-by-Step Procedure: Move #234567 to HR15

The following procedure reproduces the move #234567 → HR15 on a live CPM1A using CX-Programmer 9.x. It assumes CX-One is installed, a USB-to-serial converter (or original OMRON CS1W-CIF31) is wired to the CPM1A peripheral port, and the controller is in PROGRAM mode.

Prerequisites

  • CPM1A-CIF01 or CS1W-CIF01 peripheral cable, or USB-to-TTL bridge set to 19,200 bps, even parity, 7 data bits, 2 stop bits (the CPM1A default).
  • CX-Programmer v9.0 or later, device type set to CPM1A.
  • PLC keyed to PROGRAM mode (the rotary switch on the front face of the CPM1A selects PROGRAM, RUN, or REMOTE).

Procedure

  1. Connect CX-Programmer to the PLC: PLC > Auto Online > Direct Online. Wait for the device type prompt; confirm CPM1A.
  2. Upload the existing program (PLC > Transfer > From PLC) or create a new project and confirm OK when prompted to overwrite.
  3. In the program window, navigate to the first empty rung (or end of existing logic).
  4. Insert a normally-open contact. Type P_On (or press I and accept the always-on flag from the symbol list, address SR25313).
  5. Insert an instruction. In CX-Programmer, press I and type MOVL; press Enter.
  6. In the operand dialog, set Source S to #234567 and Destination D to HR15.
  7. Press Enter to commit. The rung should read:
    --[P_On]--[MOVL #234567 HR15]--
  8. Compile (Program > Compile, Ctrl+F7). Address any compilation errors before continuing.
  9. Download to the PLC: PLC > Transfer > To PLC. Confirm OK. The transfer dialog will report the program size in steps.
  10. Switch the rotary switch to RUN (or to REMOTE and select Run from CX-Programmer: PLC > Operating Mode > Run).

Inspecting User Memory and HR with CX-Programmer

To verify the move is working, open the Memory View tool from CX-Programmer:

  1. Select View > Memory View (or click the Memory View button on the toolbar).
  2. In the address selector, type HR15 and press Enter. The dialog displays the value as both decimal and hexadecimal.
  3. Switch the display to 32-bit (right-click the address grid, choose Display Format > 32-bit BCD) to see the joined value 234567.
  4. Power-cycle the PLC (turn the supply off for at least 5 seconds, then restore). Re-enter Memory View: HR15 and HR16 should still report 234567. If they do, retention is healthy.

To locate the constant in UM, select View > UM View in CX-Programmer v9.5 or later. The window shows the compiled instruction words in hexadecimal. The MOVL instruction will appear as the function code 0x01F2 followed by the operand bytes. The exact offset is rung-dependent; it is not necessary to know the offset for normal operation, but it confirms that the constant lives in UM and is part of the executable image.

Note: If you cannot find a UM View option in your CX-Programmer build, the menu item may be hidden or relocated depending on the version. In older builds (v6.x), the equivalent is available through View > Memory Areas with the UM tab selected.

Troubleshooting Matrix

Common field failures when moving constants into the HR area
Symptom Likely Root Cause Diagnostic Corrective Action
HR15 shows a value, but HR16 is unchanged. Programmer used F0 MOV instead of F498 MOVL. Open the rung; verify the instruction mnemonic. Replace with MOVL (F498).
Value at HR15 is correct only while the rung is energized; resets to 0 after power-cycle. Source operand is being moved from a non-retentive area (IR, LR) every scan, but the destination is being overwritten by a startup reset rung. Check for a P_First_Cycle rung that initializes HR15 to 0. Condition the reset on a different first-scan signal, or move the default value into HR15 from the constant instead.
ER flag (SR25503) is set after MOVL. Indirect DM addressing out of range, or destination is in the protected DM6144-DM6655 region. Monitor SR25503 in Memory View; check if D was meant to be a word pair in the protected range. Move the destination into HR, AR, or read/write DM (DM0000-DM1023).
HR15 holds 0xFFFF after what should be a positive constant. Constant was entered as a negative value (sign-extended). Re-check the literal in CX-Programmer — leading - signs are easy to miss in transferred programs. Re-enter the constant without the sign.
MOVL is highlighted yellow with a warning at compile time. Destination word pair straddles a non-existent area (e.g., HR19 is the last word, HR20 does not exist). Confirm HR area range is HR00-HR19. Use HR18 instead so HR18+HR19 forms a valid pair.
Upload from PLC shows the rung, but constant in HR15 is shifted by one word. Ladder was uploaded from a different project; CX-Programmer re-assembled the rung but the constant was edited in the offline file. Compare offline and online program text. Download the offline program back to the PLC to synchronize.

Verification Checklist

Run the following checks before handing the program back to operations:

  1. Compile cleanly. No warnings or errors in the Output window.
  2. Online monitor the rung. In Monitor mode, the MOVL instruction should display the constant value in green. HR15 and HR16 should show the live 32-bit result.
  3. Force a power cycle. Cut supply power for at least 10 seconds. Confirm HR15:HR16 still equals the expected value on the next scan.
  4. Force a program edit. Add and remove a single NOP rung to trigger a recompile and re-download. Confirm HR15:HR16 still equals the expected value.
  5. Check ER flag. Monitor SR25503 (the P_ER bit). It must remain 0 for the move to be executing without error.
  6. Confirm the retention bit. For CPM1A the HR retention is unconditional, but if you ever migrate the program to a CPM2A or higher, verify that DM6602 or the equivalent setup word for HR retention is enabled.

Field Notes and Migration Considerations

When porting a CPM1A program to a CP1E, CP1L, or CP2E platform, the HR area persists but the addresses shift. CP1E-L uses HR0000-HR0099 (100 words). The MOVL function code remains F498 across the CP1E, CP1L, CP1H, and CJ2 families, so the ladder rung itself ports without modification. Always confirm the destination address range before downloading.

Engineers using Sysmac Studio against an NJ/NX controller will find that neither F0 nor F498 exists in that environment; the modern equivalent is the Move instruction block in the IEC 61131-3 variable-based paradigm, which uses 32-bit typed source and destination tags.

Where exactly is the literal #123456 stored in the CPM1A?

It is embedded inside the MOVL instruction as part of the executable image in User Program Memory (UM). The 32-bit value is encoded little-endian in four bytes immediately following the function code 0x01F2. There is no standalone variable for the constant — if you delete the rung, the value disappears with it.

Why do I lose the high word of my 32-bit value when I use MOV instead of MOVL?

F0 MOV is a 16-bit instruction. It writes the low 16 bits only and leaves the next consecutive word untouched. To copy all four bytes of a value such as 234567 (0x0003A947) into a destination, you must use F498 MOVL, which writes both the low word (0xA947) and the high word (0x0003) of the destination pair.

Do HR values persist across a power cycle on the CPM1A?

Yes. HR00-HR19 are non-volatile on the CPM1A and survive power-down without a battery. The value present at the moment of power-down is restored on the next power-up. No setup word is required to enable retention.

Can I edit the constant at runtime from CX-Programmer instead of moving it every scan?

Yes. Open Memory View, type the new decimal or hexadecimal value into HR15 (and HR16 for the high word), and press Set. Because HR is non-volatile, the new value is retained across power cycles. For a one-time upload from HMI, write the HMI-supplied value into HR15 using a MOVL triggered by a single positive-edge contact.

What is the maximum 32-bit constant I can move into HR with MOVL?

The signed 32-bit range is -2,147,483,648 to +2,147,483,647 (0x80000000 to 0x7FFFFFFF). Unsigned decimal interpretation extends to 4,294,967,295 (0xFFFFFFFF). If the constant exceeds 16,384 (0x3FFF) for the high word, you can still encode it as an immediate operand — the MOVL instruction supports the full 32-bit literal range.

Back to blog