Post Go back to editing

Implementation note for MAX86174A/MAX86174B: “Best-in-Class Optical Pulse Oximeter and Heart-Rate Sensor AFE for Wearable Health”

This blog provides an experience about the implementation of MCU firmware for ADI’s “Best-in-Class Optical Pulse Oximeter and Heart-Rate Sensor AFE for Wearable Health”: MAX86174A

  • Some important points are emphasized.
  • Communication protocol: I2C

Step 1: Create driver files:

  • max86174A.h
  • max86174A.c

Step 2: Define the register’s address using a readable name in max86174A.h

  • Referring to “Register Map” in the datasheet (page 43)


#define MAX86174A_Status_1  0x00

#define MAX86174A_Status_2  0x01

Step 3: implement the necessary functions in max86174A.c

  • The most important communication function (communication): 

    uint32_t max86174A_ readReg (uint8_t reg, uint8_t len);

    // Input is the register address, and the number of bytes that will be read from the register
    // Output is the value in the target register

    void max86174A_writeReg (uint8_t reg, uint8_t *val);

    // Input is the register address, and the pointer that is saving the value to be written, such as an array

  • The configuration functions: 

    void max86174A_reset();

    // Register MAX86174A_System_Configuration_1 (0x11), set RESET bit to 1

    void max86174A_setFs(uint32_t Fs);

    // Register MAX86174A_FR_Clock_Divider_MSB (0x1B), set the value to the corresponding frame rate (fps)

    void max86174A_enable_MEAS(uint8_t Num_MEAS)

    // Set the register MAX86174A_System_Configuration_2, to enable the corresponding MEAS.
    // Also should set the PPG1_PWRDN and PPG2_PWRDN to enable/disable the ADC channels, in register MAX86174A_System_Configuration_1 (0x11), here 0 is enable, 1 is disable

    void max86174A_setLED(uint8_t MEAS_x, uint8_t DRVA, uint8_t DRVA_POW, uint8_t DRVB, uint8_t DRVB_POW)

    // The MEAS_x is the number of the measurement
    // There are two LED drivers for each measurement, select which LEDs are driven in register MAX86174A_MEASx_Selects(0x20+8*MEAS_x),
    // Then set the driving current in MAX86174A_MEASx_LEDA_Current (0x25+8*MEAS_x) and MEAS1_LEDB_Current(0x26+8*MEAS_x), respectively
    // Important: if the LED4 is used, in the register MAX86174A_Output_Pin_Configuration, the TRIGLED4_SEL bit must be set to 1

    void max86174A_setPD(uint8_t MEAS_x, uint8_t ADC_TINT, uint8_t ADC_RGE)

    // Set the ADC integrate time in MAX86174A_MEASx_Configuration_1 (0x21+8*MEAS_x)
    // set ADC range in MAX86174A_MEASx_Configuration_2 (0x22+8*MEAS_x)

    void max86174A_start();

    // In register MAX86174A_System_Configuration_1 (0x11), set SHDN bit to 0 to start running

    void max86174A _stop();

    // In register MAX86174A_System_Configuration_1 (0x11), set SHDN bit to 1 so stop running

    void max86174A_read_FIFO_Data(double* data, uint32_t data_len)

    // The data can only be readout from FIFO, each data is 3 bytes, so for reading one data, should read 3 byte from I2C, the register address is MAX86174A_FIFO_Data_Register (0x07)

    void max86174A_set_interrupt_FIFO(uint8_t val_full)

    // Set the FIFO size in MAX86174A_FIFO_Configuration_1 (0x08), the value in register is the number of empty FIFO, so the number of saved data should be subtracted from 256 (256-val_full)
    // Configure the INTB pin, together with the host MCU, to let the MCU know FIFO is full, in register MAX86174A_Output_Pin_Configuration (0x17)
    // Enable the interrupt signal at INTB pin, to let the host MCU know the FIFO is full, in register MAX86174A_Interrupt_Enable_1 (0x58)

    void max86174A_flushFifo()

    // Empty the FIFO by set the FLUSH_FIFO bit to 1, in register MAX86174A_FIFO_Configuration_2 (0x09)

  • The initialization functions: 

    void max86174A _init_user();

    // This function call the above-defined functions to make the PPG sensor work. Following is my flow for a reference:
    max86174A _stop();
    // MEAS1 and MEAS2 are enabled
    max86174A _enable_MEAS(2); 
    // Set the LED for MEAS1
    max86174A _setLED(0, 0, 10, 0, 10); 
    // Set the PD for MEAS1
    max86174A _setPD(0, 0, 0); 
    // Set the LED for MEAS2
    max86174A _setLED(1, 0, 0, 0, 0); 
    // Set the PD for MEAS2
    max86174A _setPD(1, 0, 0); 
     // Set sampling frequency as 100 fps
    max86174A _setFs(100);
    // Enable an interrupt signal in INTB when there are 250 samples in FIFO
    max86174A _set_interrupt_FIFO(250); 
    // Empty FIFO for initiation
    max86174A _flushFifo(); 
    // Start the MAX86174A
    max86174A _start(); 

Step 4: declare the functions above to the file “max86174A.h”: 

Step 5: Include the file “max86174A.h” in the main.c: 

  • Call max86174A _init_user() in the initiation process
  • Configure the interrupt callback, read the data from FIFO of max86174 after the INTB signals received.


Have fun!


[1] MAX86174A datasheet:

Changed format
[edited by: Jiabin at 6:59 AM (GMT -5) on 17 Feb 2023]
Parents Reply Children
No Data