If you are reading the hexadecimal number 10, it equals 16 in decimal; if you are asking how to write the decimal number 10 in hex, it is 0A. In base-16 numbering, the position of the digit dictates its multiplier, meaning a 1 in the "sixteens" column and a 0 in the "ones" column yields 16. This ambiguity is a frequent trap for hobbyists reading datasheets or writing microcontroller firmware, where mixing up base-10 and base-16 can silently misconfigure hardware registers.
The Core Conversion Table: Hex, Decimal, and Binary
Before writing any low-level firmware or parsing a logic analyzer trace, you need to internalize how bases map to one another. Microcontrollers ultimately operate in binary (base-2), but binary strings are too long for humans to read comfortably. Hexadecimal (base-16) acts as a shorthand, where every single hex digit perfectly represents four binary bits (a nibble).
Here is how the critical values surrounding "10" map across bases, specifically applied to an 8-bit port register like PORTB on an ATmega328P (Arduino Uno):
| Hexadecimal Value | Decimal Value | Binary (8-bit) | ATmega328P PORTB Pin Mapping |
|---|---|---|---|
0x0A |
10 | 0000 1010 |
Pins 9 & 11 HIGH |
0x10 |
16 | 0001 0000 |
Pin 12 HIGH |
0x0F |
15 | 0000 1111 |
Pins 8, 9, 10, 11 HIGH |
0x3F |
63 | 0011 1111 |
All PORTB pins HIGH (except reset) |
0xFF |
255 | 1111 1111 |
All 8 bits HIGH (Port-wide) |
0x0F and 0x10 represent the exact boundary where the lower nibble rolls over into the upper nibble. In memory addressing and bitmasking, crossing from F to 10 is the hex equivalent of crossing from 9 to 10 in decimal.
Worked Numeric Example: Bitmasking and Pin States
To understand what this changes in a real circuit, let us look at direct port manipulation. Using functions like digitalWrite() is safe but slow. When you need to toggle multiple pins simultaneously—such as driving a parallel LCD or a high-speed DAC—you write directly to the hardware registers.
Suppose you are working with an Arduino Uno and want to set physical pin 12 HIGH using the PORTB register. Pin 12 corresponds to bit 4 of PORTB.
The Correct Approach (Hexadecimal)
You need bit 4 to be 1 and all other bits to be 0. In binary, that is 0001 0000. Grouping by nibbles, the lower nibble is 0000 (0 in hex) and the upper nibble is 0001 (1 in hex). Therefore, you write:
PORTB = 0x10;
The compiler reads 0x10 as hexadecimal 10 (decimal 16) and sets exactly the correct pin HIGH.
The Costly Mistake (Decimal)
If you forget the 0x prefix and type:
PORTB = 10;
The compiler reads this as decimal 10. It converts decimal 10 to binary 0000 1010. Instead of turning on pin 12, you have just turned on bits 1 and 3, which correspond to physical pins 9 and 11. If pins 9 and 11 are wired to the enable lines of a motor driver or a sensitive voltage regulator, this silent misconfiguration can cause unexpected hardware behavior or physical damage.
Where You Meet This in Practice: Embedded Systems and Datasheets
The distinction between hex 10 and decimal 10 is not just a math exercise; it dictates how your microcontroller communicates with the outside world. Here is where you will encounter this constantly on the bench:
1. I2C Device Addressing
When scanning an I2C bus, logic analyzers and serial monitors output addresses in hex. The popular PCF8574 I/O expander has a base address of 0x20. If you are configuring an I2C multiplexer or setting address pins, the datasheet will refer to hex values. According to the Texas Instruments PCF8574 datasheet, the address pins (A0, A1, A2) shift the base address. If you attempt to write to address 10 in your code without the 0x prefix, the Wire library will attempt to contact decimal address 10 (hex 0x0A), which is typically reserved for specialized SMBus host notify protocols, resulting in a silent timeout.
2. SPI and Memory Registers
When configuring an ESP32 via the ESP-IDF framework, you often write directly to memory-mapped registers. The Espressif GPIO API documentation heavily utilizes hex masks to configure pin routing matrices. A register might require you to write 0x10 to route a signal to a specific matrix slot. Writing decimal 10 (0x0A) will route the signal to the wrong peripheral matrix slot, causing your PWM or UART signal to simply vanish.
3. Color Codes in RGB LEDs
If you are driving WS2812B (NeoPixel) LEDs, colors are passed as 24-bit hex values. Pure red is 0xFF0000. If a tutorial tells you to use a dim blue value of 10 in hex (0x000010), and you pass decimal 10, the library might interpret it identically in this specific low-byte scenario, but if you are shifting bytes for a 32-bit RGBW LED, base confusion will completely scramble your color wheel.
Common Confusions and Mistakes to Avoid
Even experienced engineers occasionally drop a prefix when tired. Here are the most common traps regarding base-16 and base-10 conversions, and how to engineer them out of your workflow.
0x to force the compiler into base-16.
Confusion 1: The "0x" vs "h" Suffix
In C, C++, and Python, hexadecimal is denoted by the 0x prefix (e.g., 0x10). However, in assembly language or older schematic capture tools, you will often see an h suffix (e.g., 10h). If you copy-paste 10h into an Arduino sketch, the compiler will throw a syntax error. Always translate h suffixes to 0x prefixes when moving from datasheet to IDE.
Confusion 2: ASCII Hex vs. Numeric Hex
When parsing serial data (UART), beginners often confuse the character "1" and "0" with the numeric value 0x10. If a sensor sends the string "10" over serial, it is transmitting two ASCII bytes: 0x31 (for '1') and 0x30 (for '0'). If you try to use that raw serial buffer as a numeric hex mask without parsing it first, your bitwise logic will fail entirely.
Confusion 3: Bitwise Shifting Errors
A common shortcut to generate hex 10 (binary 0001 0000) in code is using the bitwise left-shift operator: 1 << 4. This is mathematically identical to 0x10 and decimal 16. However, if you accidentally type 10 << 4 thinking "10 in hex", you are actually shifting decimal 10 (binary 1010) left by 4 bits, yielding 160 (0xA0). Stick to explicit 0x notation or verified shift macros to maintain readability.
Summary Decision Framework
- Reading a Datasheet Register Map? Assume Hex. Write it in code as
0x... - Calling an Arduino API like
digitalWrite()? Assume Decimal. Pass the physical pin number (e.g.,10). - Configuring an I2C Address? Assume Hex. Use the
0xprefix in your Wire library calls. - Calculating Current/Voltage via Ohm's Law? Assume Decimal. Base-16 has no place in analog circuit math.






