MAX9611 no-OS driver
Supported Devices
Overview
The MAX9611 and MAX9612 are high-side current-sense amplifiers featuring a 12-bit ADC and an op-amp/comparator, ideal for industrial and automotive applications. They support a wide input common-mode voltage range from 0V to 60V and a power supply range from 2.7V to 5.5V. These components allow for programmable full-scale voltage, enhancing measurement precision and sense resistor flexibility. An I2C interface compatible with 1.8V and 3.3V logic levels ensures seamless integration with modern microcontrollers. The MAX9611 provides a noninverting input-output configuration, while the MAX9612 offers an inverting configuration. Both are suitable for automotive temperature ranges of -40°C to +125°C and come in a 3mm x 5mm, 10-pin µMAX® package. Their applications include hybrid automotive power supplies, server backplanes, and telecom cards.
Applications
Hybrid Automotive Power Supplies
Server Backplanes
Base-Station PA Control
Base-Station Feeder Cable Bias-T
Telecom Cards
Battery-Operated Equipment
Operation Modes
Mode Name |
Description |
Configuration Bits |
Typical Use Case |
MAX9611_NORMAL_MODE |
Normal operating mode for MAX9611 |
0x0 |
Used for standard operations of the device without additional processing modes. |
MAX9611_OPAMP_MODE |
Configures the device to operate as an operational amplifier |
0x3 |
When additional signal amplification is required in the current sensing path. |
MAX9611_COMPARATOR_MODE |
Sets device to function as a comparator, including latch behaviors |
0x7 |
Applications needing voltage threshold detection and high-speed signal comparison |
MAX9611_CONF_SENSE_1X |
MUX configuration for 1x sensing gain |
Uses MUX bits |
Basic current sensing operation with standard gain in typical applications. |
MAX9611_CONF_SENSE_4X |
MUX configuration for 4x sensing gain |
Uses MUX bits |
Enhance sensitivity for precise current measurement requiring moderate gain. |
MAX9611_CONF_SENSE_8X |
MUX configuration for 8x sensing gain |
Uses MUX bits |
High gain scenario for weak signal amplification in sensitive current paths. |
MAX9611_CONF_IN_COM_MODE |
Configures for input common mode |
Uses MUX bits |
Situations requiring common-mode signal rejection. |
MAX9611_CONF_OUT_ADC |
Configures to output the ADC value |
Uses MUX bits |
Applications focusing on direct ADC output values for further processing. |
MAX9611_CONF_SET_ADC |
Sets ADC configuration |
Uses MUX bits |
Setting ADC parameters for particular operational needs. |
MAX9611_CONF_TEMP |
Temperature sensing configuration |
Uses MUX bits |
Applications need temperature monitoring alongside current sensing. |
MAX9611_FAST_MODE |
Fast data capturing and processing configuration |
Uses MUX bits |
Critical high-speed data acquisition scenarios where time is of essence. |
Device Configuration
Initialization and Addressing
In MAX9611PMB I2C communication, a bus master initiates communication
with a slave device by issuing a START condition followed by a slave
address. The MAX9611/MAX9612 wait for this condition and, upon
recognizing their address, are ready to exchange data, offering 16
different slave addresses using two address inputs, A1 and A0, with the
least significant bit determining the read/write mode. After receiving
the address, the MAX9611/MAX9612 acknowledge by pulling SDA low for one
clock cycle. The max9611_init
function initializes
a max9611_dev``device by allocating memory, setting up the I2C interface,
and handling errors. It starts by allocating memory for the device
structure and returns an error if the allocation fails. The I2C
interface is then initialized, and if this fails, the allocated memory
is freed, and the error is returned. If successful, the device structure
is assigned to the provided pointer, and the function returns 0. The
MAX9611 driver uses functions like ``max9611_addr_gen
to generate the
I2C slave address, max9611_init
to establish communication and
allocate resources, and max9611_remove
to deallocate resources and clean
up.
Data Operations
To manipulate device registers, the driver offers various functions.
max9611_read
reads from a specified register, ensuring compliance with
valid boundaries, while max9611_write
writes data to registers,
preventing modifications to read-only areas. max9611_reg_update
enables selective update of register contents using a mask and new
values.
Mode Control
Operational mode configuration is performed with max9611_set_mode
and
max9611_get_mode
, which set and retrieve the device mode, supporting
normal, operational amplifier, and comparator modes. max9611_set_mux
and max9611_get_mux
configure and query internal multiplexer settings
for adaptable data capture configurations. max9611_set_lr
configures
the latch/retry (LR) bit in the MAX9611 control register to manage
operational modes. By setting the boolean ‘is_normal’ to true, the
function sets the LR bit to 0, enabling normal operation. Otherwise, it
configures for an alternative mode as detailed in the device datasheet
while the max9611_get_lr
function reads the LR bit state from the
MAX9611’s control register, storing the value in a boolean pointer. This
allows verification of the current operational mode of the device,
ensuring correct mode settings for intended applications.
Delay and Retry
Timing control is essential, and the driver manages this through
max9611_set_delay
and max9611_get_delay
for delay settings, and
max9611_set_retry
and max9611_get_retry
for retry intervals,
ensuring robust I2C communication by allowing operation retries within
specific intervals.
Raw Data Access
Access to raw ADC data is provided by max9611_get_raw
, which retrieves
12-bit data according to the device’s current configuration and capture
mode. This function supports applications requiring precise ADC readings
and in-depth current measurement necessary for high-side current-sensing
tasks.
Shutdown
max9611_shutdown
enables toggling the device’s power state, crucial
for controlling power consumption, by updating control registers based
on a given parameter.
Driver Initialization Example
int ret;
uint8_t mux_conf[] = {
MAX9611_CONF_SENSE_1X,
MAX9611_CONF_SENSE_4X,
MAX9611_CONF_SENSE_8X,
MAX9611_CONF_IN_COM_MODE,
MAX9611_CONF_OUT_ADC,
MAX9611_CONF_SET_ADC,
MAX9611_CONF_TEMP,
MAX9611_FAST_MODE
};
uint8_t mode_conf[] = {
MAX9611_NORMAL_MODE,
MAX9611_OPAMP_MODE,
MAX9611_COMPARATOR_MODE
};
uint8_t delays[] = {
MAX9611_1MS,
MAX9611_100US
};
uint8_t retries[] = {
MAX9611_50MS,
MAX9611_10MS
};
struct max_i2c_init_param max9611_extra = {
.vssel = MXC_GPIO_VSSEL_VDDIOH
};
struct max9611_init_param max9611_ip = {
.i2c_init.device_id = 0,
.i2c_init.max_speed_hz = MAX_I2C_STD_MODE,
.i2c_init.extra = &max9611_extra,
.i2c_init.platform_ops = &max_i2c_ops
};
ret = max9611_addr_gen(&max9611_ip, MAX9611_ZERO_VCC, MAX9611_ZERO_VCC);
if (ret)
return ret;
struct max9611_dev *max9611_device;
ret = max9611_init(&max9611_device, max9611_ip);
if (ret)
return ret;
while (1) {
uint16_t raw_val;
int mux_cnt = 0, mode_cnt = 0, dcnt = 0, rcnt = 0;
for (int i = 0; i < 8; i++) {
enum max9611_mux_conf mux, mux_new;
ret = max9611_get_mux(max9611_device, &mux);
if (ret)
return ret;
ret = max9611_set_mux(max9611_device, mux_conf[i]);
if (ret)
return ret;
ret = max9611_get_mux(max9611_device, &mux_new);
if (ret)
return ret;
ret = max9611_get_raw(max9611_device, &raw_val);
if (ret)
return ret;
if (mux_conf[i] != mux_new)
mux_cnt++;
}
for (int i = 0; i < 3; i++) {
enum max9611_mode_conf mode, mode_new;
ret = max9611_get_mode(max9611_device, &mode);
if (ret)
return ret;
ret = max9611_set_mode(max9611_device, mode_conf[i]);
if (ret)
return ret;
ret = max9611_get_mode(max9611_device, &mode_new);
if (ret)
return ret;
if (mode_conf[i] != mode_new)
mode_cnt++;
}
for (int i = 0; i < 2; i++) {
enum max9611_delay_time dtime, dtime_new;
ret = max9611_get_delay(max9611_device, &dtime);
if (ret)
return ret;
ret = max9611_set_delay(max9611_device, delays[i]);
if (ret)
return ret;
ret = max9611_get_delay(max9611_device, &dtime_new);
if (ret)
return ret;
if (delays[i] != dtime_new)
dcnt++;
}
for (int i = 0; i < 2; i++) {
enum max9611_retry_time rtime, rtime_new;
ret = max9611_get_retry(max9611_device, &rtime);
if (ret)
return ret;
ret = max9611_set_retry(max9611_device, retries[i]);
if (ret)
return ret;
ret = max9611_get_retry(max9611_device, &rtime_new);
if (ret)
return ret;
if (retries[i] != rtime_new)
rcnt++;
}
ret = max9611_shutdown(max9611_device, true);
if (ret)
return ret;
ret = max9611_shutdown(max9611_device, false);
if (ret)
return ret;
}