When you are debugging an I2C bus on an ESP32 or setting GPIO port registers on an ATmega328P, you rarely have the luxury of doing base conversions in your head. You need the exact bit pattern or hex address immediately. The core 0-255 (8-bit) range is the most critical for microcontroller work, governing everything from PWM duty cycles to 7-bit I2C addresses and direct port manipulation.
The 8-Bit Hexadecimal Binary Decimal Table (0x00 to 0xFF)
How to read this table: This reference follows the base notation conventions standardized in ISO/IEC 80000-13 and adopted by C/C++ compilers. The 0x prefix denotes hexadecimal (base-16), and 0b denotes binary (base-2). The "Embedded Use Case" column highlights why that specific numeric boundary matters on the bench. These rows act as bookmark-friendly quick-jumps for the most queried values in microcontroller programming: the zero-state, powers of two (critical for bitwise masking), nibble boundaries, and the 8-bit maximum.
| Decimal | Hexadecimal | Binary | Common Embedded Use Case |
|---|---|---|---|
| 0 | 0x00 | 0b00000000 | GPIO LOW, PWM 0% duty, I2C NACK |
| 1 | 0x01 | 0b00000001 | Bit 0 mask, LSB set |
| 2 | 0x02 | 0b00000010 | Bit 1 mask |
| 4 | 0x04 | 0b00000100 | Bit 2 mask |
| 8 | 0x08 | 0b00001000 | Bit 3 mask |
| 15 | 0x0F | 0b00001111 | Lower nibble mask (0b1111) |
| 16 | 0x10 | 0b00010000 | Bit 4 mask, upper nibble start |
| 31 | 0x1F | 0b00011111 | 5-bit max value (e.g., some DACs) |
| 32 | 0x20 | 0b00100000 | Bit 5 mask, I2C address boundary |
| 60 | 0x3C | 0b00111100 | SSD1306 OLED default I2C address |
| 63 | 0x3F | 0b00111111 | 6-bit max value |
| 64 | 0x40 | 0b01000000 | Bit 6 mask |
| 127 | 0x7F | 0b01111111 | Max 7-bit I2C address, 8-bit signed max |
| 128 | 0x80 | 0b10000000 | Bit 7 mask, MSB set, signed negative flag |
| 255 | 0xFF | 0b11111111 | GPIO HIGH, PWM 100% duty, 8-bit unsigned max |
0xA5 is 0xA0 (160) + 0x05 (5) = 165 decimal. In binary, A is 1010 and 5 is 0101, making 0b10100101.
Which Column Applies to Your Microcontroller Task?
Beginners often memorize conversions without understanding which base is native to the hardware abstraction layer they are using. Here is how to choose the right column for your specific installation or codebase.
| Base System | Best Used For | Hardware / Protocol Examples | Choose This When... |
|---|---|---|---|
| Hexadecimal | Memory mapping, bus addresses, color codes | I2C addresses (0x3C), SPI registers, RGB LEDs (#FF00FF) | You are reading datasheets, configuring I2C/SPI peripherals, or defining color arrays. |
| Binary | Bitwise masking, direct port manipulation | GPIO PORT registers (PORTB), interrupt flags, pin states | You need to set, clear, or toggle specific pins without affecting adjacent pins on the same register. |
| Decimal | Human-readable math, analog scaling, timing | PWM duty cycles (0-255), ADC readings (0-1023), baud rates (115200) | You are calculating physical outputs (voltage, RPM) or passing arguments to high-level API functions like analogWrite(). |
How Bit-Shifting and Protocols Modify the Base Value
In wire sizing, derating factors modify the base ampacity based on temperature and conduit fill. In digital logic and bus protocols, bit-shifting and protocol overhead modify the base numeric value you see in the table. If you do not account for these modifications, your bus will fail to initialize.
The most common trap for hobbyists is the 7-bit vs. 8-bit I2C address shift. The I2C specification defines addresses as 7 bits (ranging from 0x00 to 0x7F). However, the physical bus transmits 8 bits: the 7 address bits followed by a Read/Write (R/W) bit.
- The Base Value: Your SSD1306 OLED datasheet lists the 7-bit address as
0x3C(Decimal 60, Binary0b0111100). - The Modification (Write): To write to the display, the R/W bit is 0. The 7 bits shift left by one position (
0x3C << 1), resulting in0x78(Decimal 120, Binary0b11110000). - The Modification (Read): To read from the display, the R/W bit is 1. The shifted address gets a 1 added to the LSB, resulting in
0x79(Decimal 121).
0x78, not 0x3C. Some libraries (like standard Arduino Wire) expect the 7-bit 0x3C and handle the shift internally. Others (like raw ESP-IDF I2C driver commands or certain Python smbus implementations) might require the shifted 8-bit value. Always check your ESP-IDF I2C documentation or library source code to see which base it expects.
Similarly, bitwise shifts modify values when configuring hardware registers. Setting the 5th bit of a register requires shifting a 1 left by 5 positions (1 << 5), which modifies the base decimal value of 1 into the decimal value of 32 (Hex 0x20). Mastering bitwise operators is mandatory for bare-metal register configuration.
What This Table Cannot Tell You (Endianness and Signed Integers)
While this hexadecimal binary decimal table perfectly maps 8-bit unsigned integers, it deliberately hides the complexities of multi-byte data and negative numbers. When you move beyond single-byte registers, the table falls short in three critical areas:
1. Endianness (Byte Order)
When reading a 16-bit or 24-bit sensor (like the BME280 pressure data or MPU6050 accelerometer axes) over I2C, you receive multiple bytes. The table cannot tell you which byte arrives first. Big-endian systems transmit the Most Significant Byte (MSB) first, while Little-endian systems (like the x86 architecture and many ARM Cortex-M implementations) transmit the Least Significant Byte (LSB) first. If you read 0x1A and 0x05 from a sensor, it could mean 0x1A05 (6661 decimal) or 0x051A (1306 decimal) depending entirely on the sensor's datasheet, not the math.
2. Two's Complement (Signed Integers)
The table lists 0xFF as 255. This is true for a uint8_t (unsigned 8-bit integer). But if your microcontroller variable is an int8_t (signed 8-bit integer), 0xFF represents -1. In two's complement, the Most Significant Bit (MSB) acts as a negative flag. Any hex value from 0x80 to 0xFF will be interpreted as a negative number (-128 to -1) if cast to a signed type. Always verify your variable types in C/C++. If you receive 0xFA from a temperature sensor and store it in a uint8_t, you get 250. If you cast it via (int8_t)0xFA, you correctly get -6.
3. Floating-Point Representation (IEEE 754)
You cannot use this table to decode floating-point numbers. If a sensor outputs a 32-bit float, the binary pattern does not map linearly to decimal values. The IEEE 754 standard divides the 32 bits into a sign bit, an 8-bit exponent, and a 23-bit fraction. A hex value of 0x41200000 translates to the decimal float 10.0, a relationship that requires a dedicated IEEE 754 converter, not a standard base-conversion table.
Keep this 8-bit table bookmarked for your daily GPIO, PWM, and I2C address debugging, but always defer to the specific component datasheet when handling multi-byte, signed, or floating-point data.






