S7-300 Memory Architecture Overview
The Siemens SIMATIC S7-300 PLC organizes memory into distinct address areas, each with specific roles. Understanding these areas is essential before writing any program in STEP 7 V5.x. The primary memory areas include:
- Process Image Input (I) and Output (Q): Cyclically updated I/O from the signal modules
- Bit Memory (M) / Merker: General-purpose scratchpad memory for program-internal use
- Data Blocks (DB): User-defined data storage with structured or unorganized formats
- Temporary Local Data (L): Stack memory scoped to logic blocks (OB, FB, FC)
- Timers (T) and Counters (C): Dedicated timer/counter words
The Bit Memory area (M) is the working scratchpad the CPU uses to retain intermediate calculation results, mode flags, handshaking bits, and scaling buffers across scan cycles. Unlike the Process Image, M memory is not refreshed from physical inputs; it is purely internal and persists across the OB1 scan until overwritten by logic. Values stored in M memory are not preserved through a power cycle unless explicitly configured as retentive in HW Config.
The memory area is subdivided into bit, byte, word, and double-word granularities. STEP 7 (and S7-300/400 in general) addresses memory with a single flat byte address space for M memory starting at MB0. Words and double-words overlay this byte space. This is the root cause of the most common programming confusion: knowing which MB, MW, and MD refer to the same physical bits.
Bit Memory (M / Merker) Address Space
The M area is the "flag" or "marker" area of the S7-300 CPU. Each bit address is written as M<byte>.<bit>, for example M 10.0 through M 10.7 for the eight bits of MB10. Every byte is addressable; every word is addressable; every double-word is addressable. STEP 7 does not impose word-alignment on word addresses for S7-300, but alignment at even byte addresses is strongly recommended to avoid endianness confusion during cross-CPU migration.
The total size of the M area is CPU-dependent and must be verified before declaring any address. Referring to the official SIMATIC S7-300 CPU 31xC and CPU 31x Reference Manual and the per-CPU technical data sheets in the Siemens Industry Online Support, representative M-area sizes for the standard CPUs are:
| CPU Model | Order Number (MLFB) | Bit Memory (M) Size | Range |
|---|---|---|---|
| CPU 312 | 6ES7 312-1AE14-0AB0 | 128 bytes | MB0 – MB127 |
| CPU 314 | 6ES7 314-1AG14-0AB0 | 256 bytes | MB0 – MB255 |
| CPU 315-2 DP | 6ES7 315-2AH14-0AB0 | 2048 bytes | MB0 – MB2047 |
| CPU 315-2 PN/DP | 6ES7 315-2EH14-0AB0 | 2048 bytes | MB0 – MB2047 |
| CPU 317-2 DP | 6ES7 317-2AK14-0AB0 | 4096 bytes | MB0 – MB4095 |
| CPU 319-3 PN/DP | 6ES7 318-3EL01-0AB0 | 8192 bytes | MB0 – MB8191 |
Attempting to download a program that references an M address outside the CPU's range triggers the SF (System Fault) LED, and the CPU enters STOP with a programming error logged in the diagnostic buffer. Always verify the address range either through the CPU's hardware configuration in STEP 7 (HW Config) or by reading the online diagnostic buffer before commissioning.
Memory Byte (MB) — 8-bit Granularity
An MB address holds exactly 8 bits of data. MB addresses are the fundamental addressing unit in the S7-300: every word and double-word is built from consecutive MB addresses. When the STEP 7 editor displays an MB value, it shows the low byte of ACCU1 and discards the high byte.
Common uses for MB variables:
- Storing individual boolean flags (
M 10.0,M 10.1, …,M 10.7) - Buffering one byte of a serial protocol or a barcode scanner result
- Temporary 8-bit counter overflow detection
- Byte-level handshaking with FC/FB parameters declared as BYTE
- Status-byte aggregation for HMI polling (8 flags in one read)
Typical STEP 7 STL operations involving MB:
A I 0.0 // AND input 0.0
AN I 0.1 // AND-NOT input 0.1
= M 10.0 // Assign result to memory bit 10.0
L MB 20 // Load memory byte 20 into ACCU1 (low byte)
T MB 30 // Transfer ACCU1 low byte to memory byte 30
L B#16#0F // Load constant byte 0x0F
T MB 40 // Mask nibble into MB40
Note that when an MB address is loaded into ACCU1, only the low byte of the accumulator (bits 0–7) is written; the high byte (bits 8–15) of ACCU1 is not affected unless explicitly cleared with a 16-bit load first. This can cause subtle bugs when subsequently loading a word and adding it to the previous MB residue.
Memory Word (MW) — 16-bit Granularity
An MW address holds 16 bits of data and occupies two consecutive MB addresses. The notation MW n corresponds to bytes MB n and MB n+1. On S7-300 CPUs, byte MB n is the high byte and MB n+1 is the low byte of the word. This is opposite to Intel-style little-endian ordering and is a frequent source of integration bugs when exchanging data with PC systems.
Common uses for MW variables:
- 16-bit integer arithmetic (
INTdata type, range -32768 to +32767) - Counter preset values and current values read from the C area
- Analog input buffer pre-scaling (0–27648 raw counts from 6ES7 analog modules)
- Indexing and pointer-style addressing using
P#M 100.0constructs - Status word for motor/valve feedback (16 flags packed into one word)
STEP 7 STL word operations:
L MW 20 // Load 16-bit value from MW20 into ACCU1
L +500 // Load constant +500
+I // Integer add ACCU1 + ACCU2
T MW 30 // Store result to MW30
L MW 40 // Load word
SRW 3 // Shift right word by 3 positions
T MW 50 // Store shifted value
L MW 60 // Load word
L MW 62 // Load second word
OW // OR words
T MW 64 // Store ORed result
For real (floating-point) values, the same memory may be read as a 32-bit entity; therefore MW addresses do not, by themselves, contain REAL data. REALs always require a 32-bit container (MD or two consecutive MWs read together as a DWord). Interpreting a 16-bit word as a REAL will read 16 bits of garbage from the next two bytes and almost always result in an invalid floating-point number.
Memory Double Word (MD) — 32-bit Granularity
An MD address holds 32 bits and occupies four consecutive MB addresses. The notation MD n covers bytes MB n, MB n+1, MB n+2, MB n+3. The S7-300 byte order for MD is: MB n = highest byte, MB n+3 = lowest byte. MD addresses are used for:
- 32-bit integer values (
DINT, range -2147483648 to +2147483647) - IEEE 754 single-precision floating-point (
REAL, ±3.402823E+38, ~7 significant digits) - Dual-word operations combining bit flags and status data
- Address-pointer arithmetic (P#M x.y adders via +D / +AR1)
- Time-tick counters in OB35 / OB1 cycle stamping (cycle counter)
- 32-bit TIME values (e.g.,
T#5sas a DINT in milliseconds)
STEP 7 STL double-word operations:
L MD 100 // Load 32-bit REAL into ACCU1
L 1.5E+002 // Load 150.0 real
*R // Multiply reals (REAL * REAL)
T MD 200 // Store 32-bit REAL result
L MD 50 // Load DINT
L L#1 // Load 32-bit constant
+D // DINT addition
T MD 60 // Store DINT result
L MD 70 // Load DINT
ABS // Absolute value
T MD 72 // Store absolute value
When the same memory is interpreted as MD200, both MW200 and MW202 are also addressable individually, but mixing of these views must respect the overlap rules in the next section. In particular, reading MW202 after writing MD200 returns the lower 16 bits of the 32-bit value, while reading MW200 returns the upper 16 bits — which differs from the byte-by-byte MB view because of byte-order swap.
Address Overlap Rules and the Critical Overlap Table
Because MB, MW, and MD all map to the same underlying byte space, overlapping addresses refer to the same physical bits. This is a feature (for efficient packing) but is also the most common source of subtle bugs in S7-300 programs. The overlap pattern is straightforward:
| Granularity | Address | Underlying Bytes | Underlying Words |
|---|---|---|---|
| Byte | MB10 | MB10 | — |
| Byte | MB11 | MB11 | — |
| Word | MW10 | MB10 (high), MB11 (low) | MW10 |
| Word | MW11 | MB11 (high), MB12 (low) | MW11 |
| DWord | MD10 | MB10, MB11, MB12, MB13 | MW10 (high), MW12 (low) |
| DWord | MD11 | MB11, MB12, MB13, MB14 | MW11 (high), MW13 (low) |
Concrete consequences:
- If
MW10= 16#1234, thenMB10= 16#12 andMB11= 16#34. - If
MD10= 16#12345678, thenMB10= 16#12,MB11= 16#34,MB12= 16#56,MB13= 16#78. - Writing to
MW10altersMB10andMB11, which may corrupt a separate flag inM 10.xorM 11.x. - Writing to
M 12.0altersMB12, which is the third byte ofMD10; a subsequent REAL read of MD10 will produce a corrupted floating-point value.
Best practice: Reserve 16-byte (or larger) address blocks for exclusive use by a single granularity. For example, use MW0–MW9 (bytes MB0–MB19) only as words, MB20–MB49 only as bytes, and MD50–MD99 only as double-words. This isolation prevents silent corruption from overlapping writes and is mandatory when the M area is shared between multiple FC/FB blocks developed by different engineers.
STEP 7 does not enforce non-overlap; the programmer is responsible for partitioning the M area. Cross-block consistency must be maintained by documentation and project-wide standards, not by the compiler.
Using MB, MW, MD in STEP 7 Programs
The three sizes are not interchangeable. They exist because S7-300 CPUs natively operate on different operand sizes. The math coprocessor (or integrated CPU logic) performs integer operations on 16- or 32-bit operands and floating-point operations on 32-bit IEEE 754 reals. Choosing the wrong size causes truncation, sign extension, or precision loss.
Selection guideline:
| Operation Type | Use | Size | Typical STEP 7 Instruction |
|---|---|---|---|
| Single-bit latch or flag | M | 1 bit | S M 10.0, R M 10.1 |
| Boolean byte transfer | MB | 8 bits | L MB 20, T MB 21 |
| 16-bit integer math / counter value | MW | 16 bits | L MW 30, +I, T MW 32 |
| 32-bit integer math | MD | 32 bits | L MD 100, L L#100, +D, T MD 104 |
| Floating-point math | MD | 32 bits | L MD 200, L 2.5, *R, T MD 204 |
| Pointer arithmetic | MD | 32 bits | L P#M 100.0, +D, LAR1 |
| TIME / DINT duration | MD | 32 bits | L MD 300, L L#5000, +D, T MD 304 |
When declaring function block parameters in the variable table of an FB or FC, the data type determines the memory layout at the call site:
-
BOOL→ 1 bit, packed into a byte at the parameter boundary -
BYTE→ 8 bits (MB) -
INT,WORD→ 16 bits (MW) -
DINT,DWORD,REAL,TIME→ 32 bits (MD)
Checking CPU Performance Data for Valid Ranges
STEP 7 exposes the actual address range of every memory area through the online CPU properties. This is the most reliable way to confirm what your specific CPU supports, especially after a hardware upgrade or a project migration between CPU models. Per-CPU range information is also available in the S7-300 CPU 31x Technical Data manual on the Siemens Industry Online Support portal.
Procedure:
- Connect to the target CPU via MPI / PROFIBUS / PROFINET.
- In SIMATIC Manager, right-click the S7 program and select Target System → Edit or use the menu PLC → CPU Messages / Diagnostics.
- If the station is not listed, open Online → Accessible Nodes to browse the MPI/PROFIBUS network, then open the online view of the station.
- Open PLC → Module Information (or Diagnostics → Module Information) and select the Performance Data tab.
- Read the values for Merker (Bit Memory), Counter, Timer, I/O, DB, and Local Data.
- Compare the actual Merker byte count to the maximum M address used in the offline program; flag any discrepancy before download.
The Performance Data dialog also reports Number of Merker bytes and Remainder of Merker (system-reserved bits used by the operating system, such as clock memory bits and bit memory for HMI coordination). For example, a CPU 315-2 PN/DP may report 2048 bytes of Merker, but the last byte is reserved by the operating system, leaving 2047 effective bytes.
Common Applications: Math, Comparison, and Analog Scaling
The MB/MW/MD hierarchy is the foundation for almost every arithmetic and signal-processing block in STEP 7. The most common patterns are:
Integer addition / subtraction
Network 1: Add MW100 and MW102, store in MW104
L MW 100
L MW 102
+I
T MW 104
16-bit comparison
Network 1: If MW200 > 500, set M 50.0
L MW 200
L +500
>I
= M 50.0
32-bit DINT comparison
Network 1: If MD300 > L#100000, set M 60.0
L MD 300
L L#100000
>D
= M 60.0
Floating-point scaling (linear)
Linear scaling from a raw 0–27648 analog input to engineering units 0.0–100.0:
Network 1: Scale AI raw value to engineering unit
L PIW 304 // Process image analog input, channel 0
ITD // Convert INT to DINT
DTR // Convert DINT to REAL
L 1.000000e+002 // 100.0 upper scale
*R // Multiply
L 2.764800e+004 // 27648 raw max
/R // Divide
T MD 500 // Store REAL in MD500
ROUND // Round to DINT for HMI display
T MW 510 // Store as INT for display
Analog scaling with FC105 (S7-300 standard library)
Siemens ships the "Standard Library → TI-S7 Converting Blocks" with FC105 (SCALE) and FC106 (UNSCALE). These FBs take a 16-bit raw input and a Hi/Lo engineering range, returning a scaled REAL in the OUT MD parameter. The full block interface is documented in the STEP 7 V5.5 Programming and Operating Manual.
CALL FC 105
IN := PIW304
HI_LIM := 1.000000e+002
LO_LIM := 0.000000e+000
BIPOLAR := FALSE
RET_VAL := MW200
OUT := MD300
Best Practices for Memory Allocation
For a plant with multiple S7-300 CPUs and a long service life, a documented memory map is essential. The following checklist applies:
- Reserve a fixed M-area range per program section. Document in the project header which MWs/MDs belong to which FC/FB. A typical scheme: M0.0–M0.7 for clock memory; MB1–MB9 for HMI handshaking flags; MW10–MW49 for FC10x process values; MW50–MW99 for FC20x alarms; MD100–MD199 for FC30x REAL math; MD200–MD249 for FC40x setpoints.
- Avoid overlap between MB and MW usage. If a byte flag uses M 100.0–M 107.7 (MB100–MB107), do not also reference MW100 or MW102 in another FC.
- Use even byte addresses for MW and MD. Although S7-300 permits odd addresses, starting at even addresses removes endianness ambiguity and improves readability.
- Reserve the first few bytes for handshaking with HMI / WinCC. Typically M0.0–M0.7 are clock memory bits (configurable in HW Config → CPU Properties → Clock Memory), used as 10 Hz / 5 Hz / 2 Hz / 1 Hz / 0.5 Hz / 0.2 Hz / 0.1 Hz blink flags.
- Prefer data blocks (DB) for application data. M memory is global and easy to accidentally overwrite; DBs can be instance-DB (per FB) or shared-DB (global) and can be structured with UDTs for type safety.
-
Use symbolic addressing. Define symbols in the S7 program's Symbol Table (e.g.,
Motor1_Run= M 50.0) and avoid raw absolute addresses in the code body. This makes the program self-documenting and reduces migration effort. - Document clock memory bits and retention. Non-retentive M bits are cleared on power cycle; retentive M bits persist. Configure retentive ranges in HW Config → CPU Properties → Retentive Memory. Always include an OB100 (warm restart) routine to initialize critical M flags to known states.
- Avoid M memory for production data. Recipe values, totals, and production counters belong in a DB so they can be backed up and downloaded without recompiling the program.
Troubleshooting Memory Addressing Errors
| Symptom | Root Cause | Resolution |
|---|---|---|
| CPU in STOP, SF LED on, diagnostic buffer: "Addressing error" | Program references M address outside CPU range | Verify range in Module Information → Performance Data; remove or relocate offending operand |
| Counter value changes unexpectedly | MW counter overlap with MB bit-flag usage | Reserve MW ranges exclusively; do not mix granularities in same byte region |
| Math result shows wrong sign | 16-bit signed overflow interpreted as unsigned | Use DINT (32-bit) or apply sign-mask logic; verify INT range -32768..+32767 |
| REAL math produces 0.0 or garbage | MD used as REAL not initialized (residual RAM value) | Initialize MD with T 0.000000e+000 before use; check for proper DTR conversion |
| FC105 RET_VAL shows 7FFF (overflow) | Raw input exceeds HI_LIM range | Re-scale HI_LIM/LO_LIM or clamp input signal |
| Symbol not found / undefined reference | Symbol Table entry missing or mismatched | Open Symbol Table → search → reassign address; rebuild program |
| Online value differs from expected value after download | Retentive bits retained old state | Perform CPU memory reset (MRES) or use "Initialize M" OB100 routine |
| Word load produces inverted high/low byte | Endianness confusion with PC target | Apply TAW (swap bytes) before transfer to communication buffer |
| OB1 runs but outputs stay false | Bit M overwritten by later MW write to same byte | Re-partition memory map; move flags to non-overlapping byte region |
For S7-300 hardware configuration and retentive memory settings, consult the SIMATIC S7-300 CPU 31xC and CPU 31x Reference Manual on Siemens Industry Online Support.
Migration Note: From S7-300 to S7-1500
If the plant eventually migrates from S7-300 to a SIMATIC S7-1500 controller, M memory behavior changes. S7-1500 supports symbolic addressing throughout, retains the M area, but defaults to optimized (symbolic-only) block access. Absolute MB/MW/MD addressing still works for global M memory but requires disabling optimized access on the consuming block. New projects on TIA Portal should plan a DB-based architecture (global DB or instance DB) instead of relying on M flags. The STEP 7 V5.5 Programming and Operating Manual covers transition details.
What is the difference between MB, MW, and MD in STEP 7?
MB is an 8-bit memory byte, MW is a 16-bit memory word occupying two consecutive bytes, and MD is a 32-bit memory double word occupying four consecutive bytes. They map to the same underlying byte space in the S7-300 bit-memory (M / Merker) area and differ only in operand size and the STEP 7 instructions that consume them.
How do I find the maximum M address for my S7-300 CPU?
Connect online and open PLC → Module Information → Performance Data, or read the per-CPU technical data sheet on the Siemens Industry Online Support. Typical ranges are MB0–MB127 (CPU 312), MB0–MB255 (CPU 314), MB0–MB2047 (CPU 315-2 DP / PN/DP), and MB0–MB4095 (CPU 317-2 DP).
Can MW10 and MB11 overlap without issues?
Yes, MW10 = MB10 (high) + MB11 (low) by design. The overlap is intentional, but the programmer must ensure that writing to MW10 does not corrupt a flag stored at M 11.x. Reserve separate ranges for word and byte usage to avoid silent data corruption, and document the partitioning in the Symbol Table.
Which memory type should I use for floating-point math?
Use MD (32-bit) with REAL data type. MW holds only 16-bit integers and cannot store a REAL value. Load operations using "L MD x" with the *R, /R, +R, -R operators operate on 32-bit IEEE 754 reals. For 64-bit double precision on newer CPUs, use DB-based LREAL variables instead.
Why does my S7-300 CPU go to STOP after downloading a new program?
Most commonly, the program references an M address outside the CPU's permitted range, or the offline and online blocks have a structural mismatch. Read the diagnostic buffer with PLC → Module Information → Diagnostic Buffer; the error code will name the offending block (OB/FB/FC/DB) and the invalid address.
How do I clear or initialize M memory after a power cycle?
Non-retentive M bits are automatically cleared by the CPU on power-up. For retentive M bits, either perform an MRES (memory reset) on the CPU or write an OB100 warm-restart routine that initializes the required M flags and words to known values. Configure the retentive range in HW Config → CPU Properties → Retentive Memory before commissioning.