pca953x: Driver for PCA9530/PCA9533 I2C-bus LED dimmers
The PCA9530 and the PCA9533 are 2-bit and 4-bit I2C LED dimmers with open-drain outputs. Every output is controlled by two bits of the LED selector register:
Value |
Meaning |
|---|---|
|
Output is high-impedance, the LED is off and the pin can be read as an input |
|
Output is driven low, the LED is on |
|
Output is modulated with the rate and the duty cycle of PWM0 |
|
Output is modulated with the rate and the duty cycle of PWM1 |
The two PWM generators are shared by all outputs. The period is
(prescaler + 1) / 152 seconds, between 6.6 ms and 1.684 s, and the duty
cycle is PWM / 256. A short period, above roughly 100 Hz, makes the LED
look dimmed; a long period makes it blink.
Everyday use needs four functions. pca953x_set_brightness() turns a LED
on, dims it or turns it off, the brightness going from 0, dark, to
PCA953X_BRIGHTNESS_MAX, fully lit, and the two extremes switch the output
to the steady modes, so the LED does not toggle at all;
pca953x_get_brightness() reports that value back;
pca953x_blink() lights a LED in pulses with a period in milliseconds and a
brightness on the same scale, and pca953x_get_blink() reports both.
The dimming runs at the shortest period the chip can produce, about 6.6 ms or 152 Hz, which is far above the flicker fusion threshold, so a dimmed LED looks steady rather than blinking. The two generators belong to the chip, not to the outputs, so all dimmed outputs share one brightness and all blinking outputs share one period and one brightness, the last call winning for every output that uses the same generator. Outputs that are switched on or off steadily do not depend on the generators.
The registers remain available for the cases the simple functions do not cover: the modes, the duty cycles, the prescalers and the pin levels belong to the reference below.
ESP-IDF driver for PCA9530/PCA9533 I2C-bus LED dimmers.
Copyright (c) 2026 Ruslan V. Uss unclerus@gmail.com
BSD Licensed as described in the file LICENSE
Defines
- PCA953X_I2C_ADDR_PCA9530_A0_LOW
I2C addresses.
The PCA9530 has one hardware address pin (
A0), and the address depends on its level. The PCA9533/01 and PCA9533/02 versions have fixed addresses. The values are 7-bit addresses, which is what the I2C driver expects; the datasheets show them as 8-bit write addresses with the extra zero bit, so0xc0,0xc2,0xc4and0xc6are the same addresses multiplied by two. PCA9530,A0connected to GND
- PCA953X_I2C_ADDR_PCA9530_A0_HIGH
PCA9530,
A0connected to VDD.
- PCA953X_I2C_ADDR_PCA9533_01
PCA9533/01.
- PCA953X_I2C_ADDR_PCA9533_02
PCA9533/02.
- PCA953X_BRIGHTNESS_MAX
Fully lit brightness.
The duty cycle register holds 8 bits, so the pulses run from 0 to 255, and 256 is the extreme that leaves no low phase at all, which means the output is steady. The brightness functions accept the whole range, from 0, dark, to this value, fully lit.
Enums
- enum pca953x_type_t
Device type.
The two devices share the register map and differ in the number of LED outputs: the PCA9530 has two, the PCA9533 has four.
Values:
- enumerator PCA953X_TYPE_PCA9530
PCA9530, 2 LED outputs.
- enumerator PCA953X_TYPE_PCA9533
PCA9533, 4 LED outputs.
- enum pca953x_mode_t
LED output modes.
The values match the bits of the LED selector register.
Values:
- enumerator PCA953X_MODE_OFF
Output is high-impedance, the LED is off, the pin can be read as an input.
- enumerator PCA953X_MODE_ON
Output is driven low, the LED is on.
- enumerator PCA953X_MODE_PWM0
Output is modulated with the rate and the duty cycle of PWM0.
- enumerator PCA953X_MODE_PWM1
Output is modulated with the rate and the duty cycle of PWM1.
Functions
- esp_err_t pca953x_init_desc(pca953x_t *dev, pca953x_type_t type, uint8_t addr, i2c_port_t port, gpio_num_t sda_gpio, gpio_num_t scl_gpio)
Initialize device descriptor.
Default SCL frequency is 400 kHz.
- Parameters:
dev – Pointer to the device descriptor
type – Device type
addr – I2C address, one of
PCA953X_I2C_ADDR_*port – I2C port number
sda_gpio – SDA GPIO
scl_gpio – SCL GPIO
- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_free_desc(pca953x_t *dev)
Free device descriptor.
- Parameters:
dev – Pointer to the device descriptor
- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif the descriptor is NULL
- esp_err_t pca953x_get_mode(pca953x_t *dev, uint8_t led, pca953x_mode_t *mode)
Get the mode of an LED output.
- Parameters:
dev – Pointer to the device descriptor
led – LED number, 0..1 for PCA9530, 0..3 for PCA9533
mode – [out] Output mode
- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_set_mode(pca953x_t *dev, uint8_t led, pca953x_mode_t mode)
Set the mode of an LED output.
To use a pin as a GPIO input, set its mode to
PCA953X_MODE_OFFand read it with pca953x_get_input().
- Parameters:
dev – Pointer to the device descriptor
led – LED number, 0..1 for PCA9530, 0..3 for PCA9533
mode – Output mode
- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_get_modes(pca953x_t *dev, uint8_t *ls)
Get the LED selector register.
The register holds two bits per LED output, in the same order as pca953x_set_mode() stores them.
- Parameters:
dev – Pointer to the device descriptor
ls – [out] LED selector value
- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_set_modes(pca953x_t *dev, uint8_t ls)
Set the LED selector register.
The reserved bits are written as they are passed, so it is safer to change the outputs one by one with pca953x_set_mode().
- Parameters:
dev – Pointer to the device descriptor
ls – LED selector value
- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_get_prescaler(pca953x_t *dev, uint8_t rate, uint8_t *psc)
Get the prescaler of a PWM rate.
The period of
rateis(prescaler + 1) / 152seconds, so the frequency is between 152 Hz and 0.59 Hz.
- Parameters:
dev – Pointer to the device descriptor
rate – PWM rate, 0 or 1
psc – [out] Prescaler value
- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_set_prescaler(pca953x_t *dev, uint8_t rate, uint8_t psc)
Set the prescaler of a PWM rate.
- Parameters:
dev – Pointer to the device descriptor
rate – PWM rate, 0 or 1
psc – Prescaler value
- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_get_pwm(pca953x_t *dev, uint8_t rate, uint8_t *pwm)
Get the duty cycle of a PWM rate.
- Parameters:
dev – Pointer to the device descriptor
rate – PWM rate, 0 or 1
pwm – [out] Duty cycle, 0..255
- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_set_pwm(pca953x_t *dev, uint8_t rate, uint8_t pwm)
Set the duty cycle of a PWM rate.
The duty cycle is
pwm / 256. When the value is 0, the output is always high and the LED is off. When the period is short enough, above roughly 100 Hz, the LED looks dimmed instead of blinking.
- Parameters:
dev – Pointer to the device descriptor
rate – PWM rate, 0 or 1
pwm – Duty cycle, 0..255
- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_set_blink_period(pca953x_t *dev, uint8_t rate, uint32_t period_ms)
Set the period of a PWM rate in milliseconds.
The period is rounded up to the closest value the prescaler can produce, between 7 ms and 1684 ms. The function changes the prescaler only, the duty cycle is set with pca953x_set_pwm().
- Parameters:
dev – Pointer to the device descriptor
rate – PWM rate, 0 or 1
period_ms – Requested period, milliseconds
- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid or the period is out of range
- esp_err_t pca953x_get_blink_period(pca953x_t *dev, uint8_t rate, uint32_t *period_ms)
Get the period of a PWM rate in milliseconds.
- Parameters:
dev – Pointer to the device descriptor
rate – PWM rate, 0 or 1
period_ms – [out] Period, milliseconds
- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_set_brightness(pca953x_t *dev, uint8_t led, uint16_t brightness)
Set the brightness of a LED.
This is the simple way to light a LED: the brightness goes from 0 to
PCA953X_BRIGHTNESS_MAX, that is, from dark to fully lit. The extremes are absolute and switch the output to the steady modes, so 0 turns the LED off and 256 turns it on, without any toggling. The values in between are the duty cycle of the dimming generator, from 1/256 to 255/256 of the period.No prescaler and no generator has to be chosen: the driver uses the fast generator and sets its period to the shortest one, about 6.6 ms or 152 Hz, which is far above the flicker fusion threshold, so the LED looks steady rather than blinking.
The chip has two duty cycle registers for all its outputs, so the outputs that are dimmed at the same time share the brightness: the last call wins for all of them. Outputs that are switched on or off steadily do not depend on the registers and can be used freely.
- Parameters:
dev – Pointer to the device descriptor
led – LED number, 0..1 for PCA9530, 0..3 for PCA9533
brightness – Brightness, 0 to
PCA953X_BRIGHTNESS_MAX- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_get_brightness(pca953x_t *dev, uint8_t led, uint16_t *brightness)
Get the brightness of a LED.
A LED that is switched off or on steadily reports 0 or
PCA953X_BRIGHTNESS_MAX, a LED that blinks reports the brightness of the pulses.
- Parameters:
dev – Pointer to the device descriptor
led – LED number, 0..1 for PCA9530, 0..3 for PCA9533
brightness – [out] Brightness, 0 to
PCA953X_BRIGHTNESS_MAX- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_blink(pca953x_t *dev, uint8_t led, uint32_t period_ms, uint16_t brightness)
Blink a LED.
The function sets the period and the brightness of the pulses and switches the LED to the slow generator, so one call is enough. The period is rounded up to the closest value the prescaler can produce, between 7 ms and 1684 ms.
The brightness follows the same scale as pca953x_set_brightness(): 0 turns the LED off and
PCA953X_BRIGHTNESS_MAXturns it on steadily, because a pulse that never goes low is not a pulse. The values in between blink.As with pca953x_set_brightness(), the blinking outputs share one period and one brightness, because the chip has a single slow generator.
- Parameters:
dev – Pointer to the device descriptor
led – LED number, 0..1 for PCA9530, 0..3 for PCA9533
period_ms – Period of the blinking, 7 to 1684 ms
brightness – Brightness of the pulses, 0 to
PCA953X_BRIGHTNESS_MAX- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_get_blink(pca953x_t *dev, uint8_t led, uint32_t *period_ms, uint16_t *brightness)
Get the period and the brightness of a blinking LED.
- Parameters:
dev – Pointer to the device descriptor
led – LED number, 0..1 for PCA9530, 0..3 for PCA9533
period_ms – [out] Period of the blinking, milliseconds
brightness – [out] Brightness of the pulses, 0 to
PCA953X_BRIGHTNESS_MAX- Returns:
ESP_OKon successESP_ERR_INVALID_STATEif the LED is not blinkingESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_get_inputs(pca953x_t *dev, uint8_t *levels)
Read the state of all LED pins.
The input register reflects the levels of the pins, so it is useful for the pins that are set to
PCA953X_MODE_OFFand used as GPIO inputs.
- Parameters:
dev – Pointer to the device descriptor
levels – [out] Pin levels, bit
nis the level of LEDn, 1 is high- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- esp_err_t pca953x_get_input(pca953x_t *dev, uint8_t led, bool *level)
Read the state of a LED pin.
- Parameters:
dev – Pointer to the device descriptor
led – LED number, 0..1 for PCA9530, 0..3 for PCA9533
level – [out]
trueif the pin is high- Returns:
ESP_OKon successESP_ERR_INVALID_ARGif an argument is invalid
- struct pca953x_t
#include <pca953x.h>Device descriptor.