If you are writing firmware for an ESP32, Arduino, or STM32, you need to map human-readable hex values to machine-level binary bits. The direct answer for the core 4-bit mapping is: 0x0=0000, 0x1=0001, 0x2=0010, 0x3=0011, 0x4=0100, 0x5=0101, 0x6=0110, 0x7=0111, 0x8=1000, 0x9=1001, 0xA=1010, 0xB=1011, 0xC=1100, 0xD=1101, 0xE=1110, 0xF=1111. Hexadecimal (base-16) is used in datasheets because it compresses 32-bit memory addresses into readable 8-character strings, while binary (base-2) is used in code because it visually maps 1:1 to physical GPIO pins and register bit-fields.

The Master Hexadecimal to Binary Lookup Table

The following table provides the foundational 4-bit nibble conversions, alongside the most common 8-bit register masks used in embedded C. This data aligns with the base definitions in ISO/IEC 80000-2 (Quantities and units — Mathematics) and uses the literal prefixes defined in the ISO/IEC 9899:2018 (C17) standard (0x for hex, 0b for binary).

How to read this table: The Hex Nibble column is what you will see in I2C scanner outputs and datasheet memory maps. The Binary Equivalent column is what you type into your IDE when performing bitwise AND/OR operations. The Common Register Mask row shows how these nibbles combine to form 8-bit bytes for masking specific hardware ports. Bookmark the quick-jump rows (0x0, 0x5, 0xA, 0xF) as they represent the boundary states (all off, alternating, all on) most frequently used in hardware debugging.
Hex Nibble (0x) Binary (0b) Decimal Common 8-Bit Mask / Use Case
0x0000000x00 (Clear all bits / Port LOW)
0x1000110x01 (Set Bit 0 / LSB)
0x2001020x02 (Set Bit 1)
0x3001130x03 (Mask lower 2 bits)
0x4010040x04 (Set Bit 2)
0x5010150x55 (01010101 - Alternating low-high test pattern)
0x6011060x06 (Mask bits 1 and 2)
0x7011170x07 (Mask lower 3 bits)
0x8100080x80 (Set Bit 7 / MSB)
0x9100190x99 (10011001 - Edge trigger test pattern)
0xA1010100xAA (10101010 - Alternating high-low test pattern)
0xB1011110x0B (Mask bits 0, 1, and 3)
0xC1100120x0C (Mask upper 2 bits of nibble)
0xD1101130x0D (Carriage Return in ASCII hex)
0xE1110140x0E (Mask bits 1, 2, and 3)
0xF1111150xFF (11111111 - Set all bits / Port HIGH)

Which Column Applies to Your Installation (Firmware Context)

Just as an electrician must choose the correct ampacity column based on insulation temperature rating, an embedded developer must choose the correct numerical base based on the hardware interface they are configuring. Using the wrong base leads to unreadable code and off-by-one bit errors.

Representation Best Applied To When to Avoid
Hexadecimal (0x) I2C addresses (e.g., 0x3C for SSD1306), SPI command bytes, memory pointers, and color codes (RGB565). When configuring individual GPIO pins or calculating PWM duty cycle percentages.
Binary (0b) Direct register manipulation, bit-masking, GPIO port state definitions (e.g., 0b00000100 for Pin 2). Math operations, timer prescaler calculations, or any value exceeding 8 bits (becomes visually overwhelming).
Decimal PWM duty cycles, ADC thresholds, baud rates (e.g., 115200), and array indexing. When interacting with hardware registers where specific bit positions dictate configuration states.

The Rule of Thumb: If the datasheet defines a value by its bit positions (e.g., "Bit 4: Enable Clock"), use binary. If the datasheet defines a value as a whole byte command (e.g., "Send 0xA5 to reset"), use hex. For a deeper look at how microcontrollers handle these literals at the compiler level, refer to the C++ Reference on Bitwise Operators.

How Bit-Masking and Shifting 'Derate' (Modify) the Base Value

In wire sizing, derating rows modify the base ampacity based on ambient temperature and bundling. In register mapping, bit-shifting and masking modify the base hex value to fit it into a specific bit-field without corrupting adjacent configuration bits. You rarely write a raw hex value directly to a 32-bit control register; you must shift it to the correct positional weight.

Worked Numeric Example:
Suppose you are configuring the ESP32 GPIO_OUT_W1TS_REG (GPIO Output Set Register). You want to set GPIO 5 HIGH.
1. Your base value is 0x1 (binary 0b0001).
2. If you write 0x1 directly to the register, you will accidentally set GPIO 0 HIGH, not GPIO 5.
3. You must 'derate' (shift) the base value by 5 positions: 0x1 << 5.
4. The modified value becomes 0x20 (binary 0b00100000).
5. To ensure you don't clear other pins, you use a bitwise OR: REG_WRITE(GPIO_OUT_W1TS_REG, (0x1 << 5));. For more on ESP32 register mapping, see the Espressif ESP-IDF GPIO Documentation.

Similarly, when reading a specific field from a status register, you use a hex mask to isolate the bits, then shift them back down. If a 32-bit register stores a 4-bit motor speed value in bits 8 through 11, you apply the mask 0x0F00 (binary 0000 1111 0000 0000), perform a bitwise AND, and right-shift by 8 (>> 8) to extract the base 0x0 to 0xF value.

What the Table Cannot Tell You

A static hexadecimal to binary conversion table is mathematically absolute, but it lacks the hardware context required to prevent catastrophic firmware bugs. Here is what the table leaves out:

  • Endianness (Byte Order): The table converts a single byte or nibble. It does not tell you how a 16-bit or 32-bit hex value (like 0x12345678) is stored in memory. An ARM Cortex-M4 (Little-Endian) will store 0x78 at the lowest memory address, while a network packet (Big-Endian) expects 0x12 first. Sending a 16-bit hex command over SPI without checking the sensor's endianness will result in reversed byte orders and rejected commands.
  • Signed vs. Unsigned (Two's Complement): The table shows 0xFF as 11111111 (decimal 255). However, if that 8-bit register is read into a signed int8_t variable in C, 0xFF represents -1. The table cannot warn you that casting a hex ADC reading into a signed integer will yield negative numbers for any value above 0x7F.
  • Register Width Boundaries: Writing 0xFFFF to a 16-bit timer register sets it to maximum. Writing 0xFFFF to an 8-bit port register will truncate the upper byte, resulting in 0xFF. Always verify the physical width of the hardware register in the datasheet before assuming your hex literal will fit.

Keep this table bookmarked for quick I2C address decoding and bit-mask generation, but always cross-reference your specific microcontroller's reference manual for endianness and register width constraints before compiling.