Why I2C Needs Pull‑Up Resistors and How to Choose the Right Value
This article explains the open‑drain nature of I2C, why pull‑up resistors are essential for providing a high level, ensuring signal integrity and enabling wired‑AND logic, and offers practical formulas, recommended resistor ranges for different speeds, STM32 configuration examples, and debugging tips.
1. I2C Bus Working Principle
I2C is a half‑duplex, synchronous serial protocol that uses only two wires—SCL (clock) generated by the master and SDA (data) for bidirectional data transfer.
SCL : Clock line driven by the master.
SDA : Data line for transmitting bits.
1.1 Open‑Drain Output Characteristics
I2C devices use open‑drain (or open‑collector) outputs, meaning each GPIO pin contains only an NMOS transistor that can either pull the line low or remain in a high‑impedance state; it cannot actively drive a high level.
1.2 Why Use Open‑Drain?
Open‑drain prevents a short circuit when multiple masters try to drive the bus simultaneously: if one master pulls the line low while another tries to drive it high, the line is simply pulled low without damaging the drivers. This "wired‑AND" behavior enables multi‑master communication and clock stretching.
2. Role of Pull‑Up Resistors
Because open‑drain outputs cannot drive high, external pull‑up resistors connected to VCC pull the bus high when no device is pulling it low.
2.1 Providing a High Level
When all devices are in high‑impedance, the pull‑up resistor raises the bus to VCC, representing logical "1".
Device pulls low → bus is low (0).
No device pulls low → pull‑up raises bus to high (1).
2.2 Ensuring Signal Integrity
The resistor creates a defined charging path for the bus capacitance, allowing fast, stable transitions and preventing the line from floating.
2.3 Enabling Wired‑AND Functionality
Any device pulling low forces the bus low.
Only when all devices release the line does the pull‑up make it high.
This property supports clock stretching and arbitration in multi‑master setups.
3. Selecting Pull‑Up Resistor Values
The value must balance rise time, power consumption, and driver capability.
3.1 Problems with Too Large a Value
Slow charging → sluggish rising edges, limiting communication speed or causing failures.
Weak drive → poor noise immunity.
3.2 Problems with Too Small a Value
Higher static power when devices pull low.
Increased driver stress, possibly exceeding the chip's sink capability.
3.3 Calculation Formula
The RC time constant determines the maximum allowable resistor:
where tr is the allowed rise time and Cbus is the total bus capacitance.
Example: for a 100 pF bus at 400 kbps (Fast mode) with a 300 ns rise‑time limit, the resistor should be less than about 3.5 kΩ.
3.4 Common Recommended Values
Standard mode (100 kbps) : 4.7 kΩ–10 kΩ for short bus, 2.2 kΩ–4.7 kΩ for longer bus.
Fast mode (400 kbps) : 2.2 kΩ–4.7 kΩ for short bus, 1 kΩ–2.2 kΩ for longer bus.
Fast‑plus (1 Mbps) : typically around 1 kΩ.
In practice, 4.7 kΩ is the most commonly used value and works well for many designs.
4. STM32 I2C Configuration Example
Below is a HAL‑based STM32 code snippet that configures I2C1 in fast mode (400 kbps) with external pull‑ups.
I2C_HandleTypeDef hi2c1;
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 400000; // 400 kbps Fast mode
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (i2cHandle->Instance==I2C1)
{
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_I2C1_CLK_ENABLE();
// PB6: I2C1_SCL, PB7: I2C1_SDA
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // Open‑drain
GPIO_InitStruct.Pull = GPIO_NOPULL; // No internal pull‑up
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
}
uint8_t I2C_ReadByte(uint8_t DevAddress, uint8_t RegAddress)
{
uint8_t data;
// Write register address
HAL_I2C_Master_Transmit(&hi2c1, DevAddress, &RegAddress, 1, 100);
// Read data
HAL_I2C_Master_Receive(&hi2c1, DevAddress, &data, 1, 100);
return data;
}Key points: GPIO_MODE_AF_OD: configures open‑drain mode. GPIO_NOPULL: disables internal pull‑ups because external resistors are used.
External pull‑up resistors (typically 4.7 kΩ) must be placed on both SCL and SDA lines.
5. Practical Debugging Experience
5.1 Common Issues and Checks
Forgot to add pull‑up resistors.
Pull‑up value too large.
Excessive bus capacitance.
Solution: Observe SCL/SDA with an oscilloscope and verify rise time.
5.2 Oscilloscope Observation Points
Rise time : must meet protocol limits (Standard < 1000 ns, Fast < 300 ns).
Level amplitude : high ≈ VCC, low ≈ GND.
Signal integrity : clean waveform without ringing or overshoot.
If rise time is too slow, the pull‑up is likely too large or bus capacitance too high; ringing indicates impedance mismatch or interference.
6. Summary
Pull‑up resistors provide the high level required for I2C logic.
They improve signal quality and ensure reliable communication.
They enable the wired‑AND behavior that supports multi‑master operation and clock stretching.
Choosing the resistor value involves balancing communication speed, bus capacitance, and power consumption. A 4.7 kΩ resistor works well for most applications, but designers should verify rise times with an oscilloscope and adjust as needed.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
