介绍
网上没有MAX86174的开源驱动,自己对照芯片手册研究了一周,写了一份,移植到项目实测可用,share出来,欢迎工友们讨论~
芯片手册
芯片手册官网可以直接下载:美信官网资料
结合自己的理解,介绍一下需要用到的部分:
MAX86174A 和 MAX86174B
区别就是MAX86174A有两路PPG通道,MAX86174B只有一路。
接口(I2C和SPI)
使用SPI
应用
自行划分了两种模式:血氧模式和心率模式。
硬件设计使用了双PD。
心率模式:开两个绿灯,2个PD采集到的结果分别打到PPG1和PPG2两个通道;
血氧模式:先后打开红灯和红外,2个PD采集的结果都打到PPG1通道;
PD和PP通道选择是可以通过MEASx_PDSEL
寄存器配置的:
应用例程
ppg_task.c
/*------------------------------------------------------------------------------
Section: Includes
------------------------------------------------------------------------------*/
#include <string.h>
#include "nrf_drv_spi.h"
#include "nrf_gpio.h"
#include "MAX86174.h"
#include "FreeRTOS.h"
#include "task.h"
#include "SEGGER_RTT.h"
#include "sys_params.h"
/*------------------------------------------------------------------------------
Section: Macro Definitions
------------------------------------------------------------------------------*/
#define HEART_MODE (1)
#define SPO2_MODE (2)
/*------------------------------------------------------------------------------
Section: Type Definitions
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
Section: Local Variables
------------------------------------------------------------------------------*/
//MAX86174
static uint8_t fifo_buf[PPG_BUFF_LEN]; // 256 fifo, 2 channel 2 pd , 3 bytes per channel
MEASx_enable_cfg_t measx_cfg;
PPG_data_t ppg_data;
/*------------------------------------------------------------------------------
Section: Function Prototypes
------------------------------------------------------------------------------*/
/***************************************************************************
* 描 述 : MAX86174_Init
* 入 参 : 无
* 返回值 :
**************************************************************************/
static void ppg_MAX86174_Init(int mode)
{
SEGGER_RTT_printf(0, "chip ID:[0x%.2x] \r\n", max86174A_read_chipID());
if(mode == HEART_MODE)
{
measx_cfg.meas1_enable = 1;
measx_cfg.meas2_enable = 0;
measx_cfg.meas3_enable = 0;
measx_cfg.meas4_enable = 0;
measx_cfg.meas5_enable = 0;
measx_cfg.meas6_enable = 0;
}
else if(mode == SPO2_MODE)
{
measx_cfg.meas1_enable = 0;
measx_cfg.meas2_enable = 1;
measx_cfg.meas3_enable = 1;
measx_cfg.meas4_enable = 0;
measx_cfg.meas5_enable = 0;
measx_cfg.meas6_enable = 0;
}
max86174A_Init_From_datasheet(&measx_cfg);
}
/***************************************************************************
* 描 述 : MAX86174_Test
* 入 参 : 无
* 返回值 :
**************************************************************************/
static void ppg_MAX86174_Test(void)
{
ppg_var_t para_ppg;
memset(fifo_buf, 0 ,sizeof(fifo_buf));
// if(nrf_gpio_pin_read(SPI_AFE_INTB_PIN) == 0)
if(max86174A_FIFO_data_ready())
{
ppg_data.fifo_count = max86174A_read_FIFO_Data(fifo_buf);
// SEGGER_RTT_printf(0, "sample_count:[%d] \n", ppg_data.fifo_count);
// for(int i = 0; i < ppg_data.fifo_count; i++)
// {
// SEGGER_RTT_printf(0, "0x%.2X 0x%.2x 0x%.2x\r\n", fifo_buf[i * 3], fifo_buf[i * 3 + 1], fifo_buf[i * 3 + 2]);
// }
for(int i = 0; i < ppg_data.fifo_count; i++)
{
ppg_data.pd_data = (fifo_buf[i * 3 + 0] << 16) | (fifo_buf[i * 3 + 1] << 8) | (fifo_buf[i * 3 + 2] << 0);
ppg_data.tag = ppg_data.pd_data >> 20;
if(ppg_data.tag != 12)
{
// SEGGER_RTT_printf(0, "tag:[%d] \t ppg:%d \r\n", ppg_data.tag, (ppg_data.pd_data & 0x7ffff));
// 2 channels
if(ppg_data.tag == 0)
{
para_ppg.green_1 = (ppg_data.pd_data & 0x7ffff);
Var_Write(VAR_PPG_GREEN_1, ¶_ppg.green_1, 4);
}
if (ppg_data.tag == 6)
{
para_ppg.green_2 = (ppg_data.pd_data & 0x7ffff);
Var_Write(VAR_PPG_GREEN_2, ¶_ppg.green_2, 4);
}
}
}
}
max86174A_flushFIFO();
}
/**
******************************************************************************
* @brief max86174_thread
******************************************************************************
*/
void ppg_max86174_thread(void * pvParameter)
{
UNUSED_PARAMETER(pvParameter);
//初始化SPI & 初始化PPG模块
SPI_PPG_Init();
ppg_MAX86174_Init(HEART_MODE);
// nrf_gpio_cfg_input(SPI_AFE_INTB_PIN, NRF_GPIO_PIN_NOPULL); //MAX86174 INTB pin cfg
while (true)
{
ppg_MAX86174_Test();
// /* Delay a task for a given number of ticks */
vTaskDelay(1000);
// /* Tasks must be implemented to never return... */
}
}
驱动源码
MAX86174.h
#ifndef _MAX86174_H_
#define _MAX86174_H_
#include <stdint.h>
/*------------------------------------------------------------------------------
Section: Macro Definitions
------------------------------------------------------------------------------*/
#define PPG_BUFF_LEN (256 * 2 * 2 * 3)
//SPI引脚定义
#define SPI_AFE_SS_PIN 16
#define SPI_AFE_SCK_PIN 14
#define SPI_AFE_MISO_PIN 15
#define SPI_AFE_MOSI_PIN 12
#define SPI_AFE_INTB_PIN 24
#define SPI_PPG_CS_LOW nrf_gpio_pin_clear(SPI_AFE_SS_PIN) //片选输出低电平:使能芯片
#define SPI_PPG_CS_HIGH nrf_gpio_pin_set(SPI_AFE_SS_PIN) //片选输出高电平:取消片选
#define SPI_READ_CMD 0x80
#define SPI_WRITE_CMD 0x00
//Chip ID
#define MAX86174_CHIP_ID 0x40
//寄存器地址定义-----
//中断状态寄存器1
#define ADDR_REG_INT_STATUS1 0X00
//中断状态寄存器2
#define ADDR_REG_INT_STATUS2 0X01
//FIFO 队列写指针
#define ADDR_REG_FIFO_WRITE_PTR 0x03
//队列读指针
#define ADDR_REG_FIFO_READ_PTR 0x04
//队列溢出计数器1
#define ADDR_REG_FIFO_OVF_COUNTER_1 0x05
//队列数据计数器2
#define ADDR_REG_FIFO_DATA_COUNTER_2 0x06
//队列数据
#define ADDR_REG_FIFO_DATA 0x07
//队列配置寄存器1
#define ADDR_REG_FIFO_CONFIG1 0x08
//队列配置寄存器2
#define ADDR_REG_FIFO_CONFIG2 0x09
// System control
//系统控制寄存器
#define ADDR_REG_SYS_SYNC 0X10
#define ADDR_REG_SYS_CONFIG_1 0x11
#define ADDR_REG_SYS_CONFIG_2 0x12
#define ADDR_REG_SYS_CONFIG_3 0x13
//PPG Filter setup
#define ADDR_REG_PPG_FILTER_SETUP 0x14
//光电二极管偏置寄存器
#define ADDR_REG_PHOTO_DIODE_BIAS 0x15
#define ADDR_REG_PIN_FUNCTIONAL_CONFIG 0x16
#define ADDR_REG_OUTPUT_PIN_CONFIG 0x17
#define ADDR_REG_I2C_BOARDCAST 0x18
//PPG Frame Rate Clock
#define ADDR_REG_FR_CLK_FREQ_SELECT 0x1A
#define ADDR_REG_FR_CLK_DIVIDER_MSB 0x1B
#define ADDR_REG_FR_CLK_DIVIDER_LSB 0x1C
//PPG MEAS1 Setup
#define ADDR_REG_MEAS1_SELECT 0x20
#define ADDR_REG_MEAS1_CONFIG_1 0x21
#define ADDR_REG_MEAS1_CONFIG_2 0x22
#define ADDR_REG_MEAS1_CONFIG_3 0x23
#define ADDR_REG_MEAS1_CONFIG_4 0x24
#define ADDR_REG_MEAS1_LEDA_CURRENT 0x25
#define ADDR_REG_MEAS1_LEDB_CURRENT 0x26
//PPG MEAS2 Setup
#define ADDR_REG_MEAS2_SELECT 0x28
#define ADDR_REG_MEAS2_CONFIG_1 0x29
#define ADDR_REG_MEAS2_CONFIG_2 0x2A
#define ADDR_REG_MEAS2_CONFIG_3 0x2B
#define ADDR_REG_MEAS2_CONFIG_4 0x2C
#define ADDR_REG_MEAS2_LEDA_CURRENT 0x2D
#define ADDR_REG_MEAS2_LEDB_CURRENT 0x2E
//PPG MEAS3 Setup
#define ADDR_REG_MEAS3_SELECT 0x30
#define ADDR_REG_MEAS3_CONFIG_1 0x31
#define ADDR_REG_MEAS3_CONFIG_2 0x32
#define ADDR_REG_MEAS3_CONFIG_3 0x33
#define ADDR_REG_MEAS3_CONFIG_4 0x34
#define ADDR_REG_MEAS3_LEDA_CURRENT 0x35
#define ADDR_REG_MEAS3_LEDB_CURRENT 0x36
//PPG MEAS4 Setup
#define ADDR_REG_MEAS4_SELECT 0x38
#define ADDR_REG_MEAS4_CONFIG_1 0x39
#define ADDR_REG_MEAS4_CONFIG_2 0x3A
#define ADDR_REG_MEAS4_CONFIG_3 0x3B
#define ADDR_REG_MEAS4_CONFIG_4 0x3C
#define ADDR_REG_MEAS4_LEDA_CURRENT 0x3D
#define ADDR_REG_MEAS4_LEDB_CURRENT 0x3E
//PPG MEAS5 Setup
#define ADDR_REG_MEAS5_SELECT 0x40
#define ADDR_REG_MEAS5_CONFIG_1 0x41
#define ADDR_REG_MEAS5_CONFIG_2 0x42
#define ADDR_REG_MEAS5_CONFIG_3 0x43
#define ADDR_REG_MEAS5_CONFIG_4 0x44
#define ADDR_REG_MEAS5_LEDA_CURRENT 0x45
#define ADDR_REG_MEAS5_LEDB_CURRENT 0x46
//PPG MEAS6 Setup
#define ADDR_REG_MEAS6_SELECT 0x48
#define ADDR_REG_MEAS6_CONFIG_1 0x49
#define ADDR_REG_MEAS6_CONFIG_2 0x4A
#define ADDR_REG_MEAS6_CONFIG_3 0x4B
#define ADDR_REG_MEAS6_CONFIG_4 0x4C
#define ADDR_REG_MEAS6_LEDA_CURRENT 0x4D
#define ADDR_REG_MEAS6_LEDB_CURRENT 0x4E
//PPG Threshold Interrupts
#define ADDR_REG_THRESHOLD_MEAS_SEL 0x50
#define ADDR_REG_THRESHOLD_HYST 0x51
#define ADDR_REG_PPG_HI_THRESHOLD_1 0x52
#define ADDR_REG_PPG_LO_THRESHOLD_1 0x53
#define ADDR_REG_PPG_HI_THRESHOLD_2 0x54
#define ADDR_REG_PPG_LO_THRESHOLD_2 0x55
//Interrupt Enables
#define ADDR_REG_INTERRUPT_ENABLE_1 0x58
#define ADDR_REG_INTERRUPT_ENABLE_2 0x59
//part id 寄存器
#define ADDR_REG_PART_ID 0XFF
/*------------------------------------------------------------------------------
Section: Type Definitions
------------------------------------------------------------------------------*/
//中断状态寄存器1 0x00
typedef union
{
struct
{
unsigned char PWR_RDY : 1;
unsigned char THRESH1_HILO : 1;
unsigned char THRESH2_HILO : 1;
unsigned char EXP_OVF : 1;
unsigned char ALC_OVF : 1;
unsigned char FIFO_DATA_RDY : 1;
unsigned char FRAME_RDY : 1;
unsigned char A_FULL : 1;
} bits;
unsigned char byte;
} dsRegIntStatus1;
//中断状态寄存器2 0x01
typedef union
{
struct
{
unsigned char LED1_COMPB : 1;
unsigned char LED2_COMPB : 1;
unsigned char LED3_COMPB : 1;
unsigned char LED4_COMPB : 1;
unsigned char rsv : 3;
unsigned char INVALID_CFG : 1;
} bits;
unsigned char byte;
} dsRegIntStatus2;
// 0X08 FIFO 配置寄存器1
typedef union
{
struct
{
unsigned char FIFO_A_FULL : 8;
} bits;
unsigned char byte;
} dsRegFifoConfig1;
// 0x09 FIFO 配置寄存器2
typedef union
{
struct
{
unsigned char rsv1 : 1;
unsigned char FIFO_RO : 1;
unsigned char A_FULL_TYPE : 1;
unsigned char FIFO_STAT_CLR : 1;
unsigned char FLUSH_FIFO : 1;
unsigned char FIFO_MARK : 1;
unsigned char rsv2 : 2;
} bits;
unsigned char byte;
} dsRegFifoConfig2;
// 0x10 System Sync 寄存器
typedef union
{
struct
{
unsigned char rsv1 : 6;
unsigned char SW_FORCE_SYNC : 1;
unsigned char rsv2 : 1;
} bits;
unsigned char byte;
} dsRegSystemSync;
// 0x11 System config 1 寄存器
typedef union
{
struct
{
unsigned char RESET : 1;
unsigned char SHDN : 1;
unsigned char PPG1_PWRDN : 1;
unsigned char PPG2_PWRDN : 1;
unsigned char SYNC_MODE : 2;
unsigned char rsv : 1;
unsigned char DISABLE_I2C : 1;
} bits;
unsigned char byte;
} dsRegSystemConfig1;
// 0x12 System config 2 寄存器
typedef union
{
struct
{
unsigned char MESA1_EN : 1;
unsigned char MESA2_EN : 1;
unsigned char MESA3_EN : 1;
unsigned char MESA4_EN : 1;
unsigned char MESA5_EN : 1;
unsigned char MESA6_EN : 1;
unsigned char rsv : 2;
} bits;
unsigned char byte;
} dsRegSystemConfig2;
// 0x13 System config 3 寄存器
typedef union
{
struct
{
unsigned char MESA1_CONFIG_SEL : 1;
unsigned char COLLECT_RAW_DATA : 1;
unsigned char PROX_AUTO : 1;
unsigned char PROX_DATA_EN : 1;
unsigned char ALC_DISABLE : 1;
unsigned char rsv : 3;
} bits;
unsigned char byte;
} dsRegSystemConfig3;
// 0x15 System Control Photodiode Bias 寄存器
typedef union
{
struct
{
unsigned char PD1_BIAS : 2;
unsigned char PD2_BIAS : 2;
unsigned char rsv : 4;
} bits;
unsigned char byte;
} dsRegSystemControl_Photodiode_Bias;
// 0x16 pin functional config
typedef union
{
struct
{
unsigned char TRIG_ICFG : 1;
unsigned char INTB_FCFG : 2;
unsigned char rsv : 5;
} bits;
unsigned char byte;
} dsRegPinFunctionalConfig;
// 0x17 Output Pin config
typedef union
{
struct
{
unsigned char TRIGLED4_SEL : 1;
unsigned char INTB_OCFG : 2;
unsigned char rsv : 5;
} bits;
unsigned char byte;
} dsRegOutputPinConfig;
// PPG MEAS1 Setup
// 0x20 PPG MEAS1 SELECT寄存器
typedef union
{
struct
{
unsigned char MEAS1_DRVA : 2;
unsigned char MEAS1_DRVB : 2;
unsigned char rsv1 : 2;
unsigned char MEAS1_AMB : 1;
unsigned char rsv2 : 1;
} bits;
unsigned char byte;
} dsRegppg_meas1_select;
// 0x21 PPG MEAS1 Config1 寄存器
typedef union
{
struct
{
unsigned char MEAS1_AVER : 3;
unsigned char MEAS1_TINT : 2;
unsigned char rsv : 1;
unsigned char MEAS1_PDSEL : 2;
} bits;
unsigned char byte;
} dsRegppg_meas1_config1;
// 0x22 PPG MEAS1 Config2 寄存器
typedef union
{
struct
{
unsigned char MEAS1_PPG1_ADC_RGE : 2;
unsigned char MEAS1_PPG2_ADC_RGE : 2;
unsigned char MEAS1_LED_RGE : 2;
unsigned char MEAS1_FILT_SEL : 1;
unsigned char MEAS1_SINC3_SEL : 1;
} bits;
unsigned char byte;
} dsRegppg_meas1_config2;
// 0x23 PPG MEAS1 Config3 寄存器
typedef union
{
struct
{
unsigned char rsv : 3;
unsigned char MEAS1_LED_SETLNG : 2;
unsigned char MEAS1_PD_SETLNG : 3;
} bits;
unsigned char byte;
} dsRegppg_meas1_config3;
// 0x24 PPG MEAS1 Config4 寄存器
typedef union
{
struct
{
unsigned char MEAS1_PPG1_DACOFF : 3;
unsigned char rsv1 : 1;
unsigned char MEAS1_PPG2_DACOFF : 3;
unsigned char rsv2 : 1;
} bits;
unsigned char byte;
} dsRegppg_meas1_config4;
//MEAS2 MEAS3 ...... 与MEAS1相同
// PPG MEAS2 Setup
// 0x28 PPG MEAS2 SELECT寄存器
typedef union
{
struct
{
unsigned char MEAS2_DRVA : 2;
unsigned char MEAS2_DRVB : 2;
unsigned char rsv1 : 2;
unsigned char MEAS2_AMB : 1;
unsigned char rsv2 : 1;
} bits;
unsigned char byte;
} dsRegppg_meas2_select;
// 0x29 PPG MEAS2 Config1 寄存器
typedef union
{
struct
{
unsigned char MEAS2_AVER : 3;
unsigned char MEAS2_TINT : 2;
unsigned char rsv : 1;
unsigned char MEAS2_PDSEL : 2;
} bits;
unsigned char byte;
} dsRegppg_meas2_config1;
// 0x2A PPG MEAS2 Config2 寄存器
typedef union
{
struct
{
unsigned char MEAS2_PPG1_ADC_RGE : 2;
unsigned char MEAS2_PPG2_ADC_RGE : 2;
unsigned char MEAS2_LED_RGE : 2;
unsigned char MEAS2_FILT_SEL : 1;
unsigned char MEAS2_SINC3_SEL : 1;
} bits;
unsigned char byte;
} dsRegppg_meas2_config2;
// 0x2B PPG MEAS2 Config3 寄存器
typedef union
{
struct
{
unsigned char rsv : 3;
unsigned char MEAS2_LED_SETLNG : 2;
unsigned char MEAS2_PD_SETLNG : 3;
} bits;
unsigned char byte;
} dsRegppg_meas2_config3;
// 0x2C PPG MEAS2 Config4 寄存器
typedef union
{
struct
{
unsigned char MEAS2_PPG1_DACOFF : 3;
unsigned char rsv1 : 1;
unsigned char MEAS2_PPG2_DACOFF : 3;
unsigned char rsv2 : 1;
} bits;
unsigned char byte;
} dsRegppg_meas2_config4;
// PPG MEAS3 Setup
// 0x30 PPG MEAS3 SELECT寄存器
typedef union
{
struct
{
unsigned char MEAS3_DRVA : 2;
unsigned char MEAS3_DRVB : 2;
unsigned char rsv1 : 2;
unsigned char MEAS3_AMB : 1;
unsigned char rsv2 : 1;
} bits;
unsigned char byte;
} dsRegppg_meas3_select;
// 0x31 PPG MEAS3 Config1 寄存器
typedef union
{
struct
{
unsigned char MEAS3_AVER : 3;
unsigned char MEAS3_TINT : 2;
unsigned char rsv : 1;
unsigned char MEAS3_PDSEL : 2;
} bits;
unsigned char byte;
} dsRegppg_meas3_config1;
// 0x32 PPG MEAS3 Config2 寄存器
typedef union
{
struct
{
unsigned char MEAS3_PPG1_ADC_RGE : 2;
unsigned char MEAS3_PPG2_ADC_RGE : 2;
unsigned char MEAS3_LED_RGE : 2;
unsigned char MEAS3_FILT_SEL : 1;
unsigned char MEAS3_SINC3_SEL : 1;
} bits;
unsigned char byte;
} dsRegppg_meas3_config2;
// 0x33 PPG MEAS3 Config3 寄存器
typedef union
{
struct
{
unsigned char rsv : 3;
unsigned char MEAS3_LED_SETLNG : 2;
unsigned char MEAS3_PD_SETLNG : 3;
} bits;
unsigned char byte;
} dsRegppg_meas3_config3;
// 0x34 PPG MEAS3 Config4 寄存器
typedef union
{
struct
{
unsigned char MEAS3_PPG1_DACOFF : 3;
unsigned char rsv1 : 1;
unsigned char MEAS3_PPG2_DACOFF : 3;
unsigned char rsv2 : 1;
} bits;
unsigned char byte;
} dsRegppg_meas3_config4;
// 0x58 Interrupt Enables 1
typedef union
{
struct
{
unsigned char rsv : 1;
unsigned char THRESH1_HILO_EN : 1;
unsigned char THRESH2_HILO_EN : 1;
unsigned char EXP_OVF_EN : 1;
unsigned char ALC_OVF_EN : 1;
unsigned char FIFO_DATA_RDY_EN : 1;
unsigned char FRAME_RDY_EN : 1;
unsigned char A_FULL_EN : 1;
} bits;
unsigned char byte;
} dsRegppg_interrupt_enable1;
typedef struct
{
//中断状态寄存器
dsRegIntStatus1 intStatus1;
dsRegIntStatus2 intStatus2;
// FIFO 配置寄存器1
dsRegFifoConfig1 fifoConfig1;
dsRegFifoConfig2 fifoConfig2;
//系统控制寄存器
dsRegSystemSync sysSync;
dsRegSystemConfig1 sys_cfg1;
dsRegSystemConfig2 sys_cfg2;
dsRegSystemConfig3 sys_cfg3;
//光电二极管偏置寄存器
dsRegSystemControl_Photodiode_Bias pdBias;
dsRegPinFunctionalConfig pin_func_cfg;
dsRegOutputPinConfig output_pin_cfg;
// PPG MEAS1 Setup
dsRegppg_meas1_select meas1_sel;
dsRegppg_meas1_config1 meas1_cfg1;
dsRegppg_meas1_config2 meas1_cfg2;
dsRegppg_meas1_config3 meas1_cfg3;
dsRegppg_meas1_config4 meas1_cfg4;
// PPG MEAS2 Setup
dsRegppg_meas2_select meas2_sel;
dsRegppg_meas2_config1 meas2_cfg1;
dsRegppg_meas2_config2 meas2_cfg2;
dsRegppg_meas2_config3 meas2_cfg3;
dsRegppg_meas2_config4 meas2_cfg4;
// PPG MEAS3 Setup
dsRegppg_meas3_select meas3_sel;
dsRegppg_meas3_config1 meas3_cfg1;
dsRegppg_meas3_config2 meas3_cfg2;
dsRegppg_meas3_config3 meas3_cfg3;
dsRegppg_meas3_config4 meas3_cfg4;
//Interrupt Enables
dsRegppg_interrupt_enable1 int_enable_1;
} dsPPGRegs_t;
typedef struct
{
unsigned char meas1_enable;
unsigned char meas2_enable;
unsigned char meas3_enable;
unsigned char meas4_enable;
unsigned char meas5_enable;
unsigned char meas6_enable;
} MEASx_enable_cfg_t;
typedef struct
{
//采样次数
unsigned short fifo_count;
//曝光读取回来的数据
unsigned char tag;
unsigned int pd_data;
} PPG_data_t;
/*------------------------------------------------------------------------------
Section: Global Function prototypes
------------------------------------------------------------------------------*/
void SPI_PPG_Init(void);
uint8_t max86174A_readReg(uint8_t reg);
void max86174A_flushFIFO(void);
uint8_t max86174A_read_chipID(void);
uint8_t max86174A_FIFO_data_ready(void);
uint16_t max86174A_get_FIFO_count(void);
uint16_t max86174A_read_FIFO_Data(uint8_t* data);
void max86174A_Init_From_datasheet(MEASx_enable_cfg_t *measx_cfg);
#endif
MAX86174.c
/*------------------------------------------------------------------------------
Section: Includes
------------------------------------------------------------------------------*/
#include "MAX86174.h"
#include "nrf_gpio.h"
#include "nrf_drv_spi.h"
#include "SEGGER_RTT.h"
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
/*------------------------------------------------------------------------------
Section: Macro Definitions
------------------------------------------------------------------------------*/
//SPI驱动程序实例ID,ID和外设编号对应,0:SPI0 1:SPI1 2:SPI2
#define SPI_INSTANCE_PPG 0
#define MEAS1_ENABLE 1
#define MEAS2_ENABLE 0
#define MEAS3_ENABLE 0
#define MEAS4_ENABLE 0
#define MEAS5_ENABLE 0
#define MEAS6_ENABLE 0
/*------------------------------------------------------------------------------
Section: Type Definitions
------------------------------------------------------------------------------*/
/* None */
/*------------------------------------------------------------------------------
Section: Global Function prototypes
------------------------------------------------------------------------------*/
/* None */
/*------------------------------------------------------------------------------
Section: Local Function prototypes
------------------------------------------------------------------------------*/
/* None */
/*------------------------------------------------------------------------------
Section: Global Variables
------------------------------------------------------------------------------*/
/* None */
/*------------------------------------------------------------------------------
Section: Local Variables
------------------------------------------------------------------------------*/
dsPPGRegs_t ppgRegs;
//定义名称为spi的SPI驱动程序实例
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE_PPG);
//SPI传输完成标志
static volatile bool spi_ppg_xfer_done;
// //SPI发送缓存数组,使用EasyDMA时一定要定义为static类型
// static uint8_t spi_tx_buf[6];
// //SPI接收缓存数组,使用EasyDMA时一定要定义为static类型
// static uint8_t spi_rx_buf[6];
/*------------------------------------------------------------------------------
Section: Function Definitions
------------------------------------------------------------------------------*/
/***************************************************************************
* 描 述 : spi_ppg_event_handler SPI事件处理函数
* 入 参 :
* 返回值 :
**************************************************************************/
void spi_ppg_event_handler(nrf_drv_spi_evt_t const * p_event, void * p_context)
{
//设置SPI传输完成
spi_ppg_xfer_done = true;
}
/***************************************************************************
* 描 述 : SPI_PPG_Init
* 入 参 :
* 返回值 :
**************************************************************************/
void SPI_PPG_Init(void)
{
//配置用于SPI片选的引脚为输出
nrf_gpio_cfg_output(SPI_AFE_SS_PIN);
//拉低CS
// SPI_PPG_CS_LOW;
SPI_PPG_CS_HIGH;
//使用默认配置参数初始化SPI配置结构体
nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
//重写SPI信号连接的引脚配置
spi_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED;
spi_config.miso_pin = SPI_AFE_MISO_PIN;
spi_config.mosi_pin = SPI_AFE_MOSI_PIN;
spi_config.sck_pin = SPI_AFE_SCK_PIN;
//初始化SPI
APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_ppg_event_handler, NULL));
}
/***************************************************************************
* 描 述 : spi_read_write
* 入 参 :
* 返回值 :
**************************************************************************/
static uint8_t spi_read_write(uint8_t data)
{
uint8_t ret;
//传输完成标志设置为false
spi_ppg_xfer_done = false;
//启动数据传输
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, &data, 1, &ret, 1));
//等待SPI传输完成
while(!spi_ppg_xfer_done);
return ret;
}
// /***************************************************************************
// * 描 述 : max86174A_readReg
// * 入 参 :
// * 返回值 :
// **************************************************************************/
uint8_t max86174A_readReg(uint8_t reg)
{
uint8_t ret;
uint8_t cmd = SPI_READ_CMD;
SPI_PPG_CS_LOW;
spi_read_write(reg);
spi_read_write(cmd);
ret = spi_read_write(0xff);
SPI_PPG_CS_HIGH;
return ret;
}
// /***************************************************************************
// * 描 述 : max86174A_readRegEx
// * 入 参 :
// * 返回值 :
// **************************************************************************/
static uint8_t max86174A_readRegEx(uint8_t reg, uint8_t *buf, uint16_t len)
{
uint16_t i, temp;
uint8_t cmd = SPI_READ_CMD;
SPI_PPG_CS_LOW;
spi_read_write(reg);
spi_read_write(cmd);
for(i = 0; i < len; i++)
{
temp = spi_read_write(0xff);
buf[i] = temp;
}
SPI_PPG_CS_HIGH;
return 1;
}
// /***************************************************************************
// * 描 述 : max86174A_writeReg
// * 入 参 :
// * 返回值 :
// **************************************************************************/
static void max86174A_writeReg(uint8_t reg, uint8_t value)
{
uint8_t cmd = SPI_WRITE_CMD;
SPI_PPG_CS_LOW;
spi_read_write(reg);
spi_read_write(cmd);
spi_read_write(value);
SPI_PPG_CS_HIGH;
}
// /***************************************************************************
// * 描 述 : max86174A_checkReg
// * 入 参 :
// * 返回值 :
// **************************************************************************/
static void max86174A_checkReg(uint8_t reg, uint8_t value)
{
uint8_t read;
uint8_t cmd = SPI_READ_CMD;
SPI_PPG_CS_LOW;
spi_read_write(reg);
spi_read_write(cmd);
read = spi_read_write(0xff);
SPI_PPG_CS_HIGH;
if(value != read)
{
SEGGER_RTT_printf(0, "[write error]addr:0x%.2x \r\n", reg);
}
}
// /***************************************************************************
// * 描 述 : max86174A_reset
// * 入 参 :
// * 返回值 :
// **************************************************************************/
static void max86174A_reset(void)
{
// ppgRegs.sys_cfg1.bits.DISABLE_I2C = 0x00;
// ppgRegs.sys_cfg1.bits.PPG1_PWRDN = 0x00;
// ppgRegs.sys_cfg1.bits.PPG2_PWRDN = 0x00;
ppgRegs.sys_cfg1.bits.RESET = 0x01;
// ppgRegs.sys_cfg1.bits.SHDN = 0x00;
// ppgRegs.sys_cfg1.bits.SYNC_MODE = 0x00;
max86174A_writeReg(ADDR_REG_SYS_CONFIG_1, ppgRegs.sys_cfg1.byte);
}
// /***************************************************************************
// * 描 述 : max86174A_shutdown
// * 入 参 :
// * 返回值 :
// **************************************************************************/
static void max86174A_shutdown(void)
{
ppgRegs.sys_cfg1.bits.SHDN = 0x01;
max86174A_writeReg(ADDR_REG_SYS_CONFIG_1, ppgRegs.sys_cfg1.byte);
}
// /***************************************************************************
// * 描 述 : max86174A_start
// * 入 参 :
// * 返回值 :
// **************************************************************************/
static void max86174A_start(void)
{
ppgRegs.sys_cfg1.bits.SHDN = 0x00;
max86174A_writeReg(ADDR_REG_SYS_CONFIG_1, ppgRegs.sys_cfg1.byte);
}
// /***************************************************************************
// * 描 述 : max86174A_enable_MEAS
// * 入 参 :
// * 返回值 :
// **************************************************************************/
static void max86174A_enable_MEAS(uint8_t meas_1, uint8_t meas_2, uint8_t meas_3, uint8_t meas_4, uint8_t meas_5, uint8_t meas_6)
{
ppgRegs.sys_cfg2.bits.MESA1_EN = meas_1;
ppgRegs.sys_cfg2.bits.MESA2_EN = meas_2;
ppgRegs.sys_cfg2.bits.MESA3_EN = meas_3;
ppgRegs.sys_cfg2.bits.MESA4_EN = meas_4;
ppgRegs.sys_cfg2.bits.MESA5_EN = meas_5;
ppgRegs.sys_cfg2.bits.MESA6_EN = meas_6;
max86174A_writeReg(ADDR_REG_SYS_CONFIG_2, ppgRegs.sys_cfg2.byte);
max86174A_checkReg(ADDR_REG_SYS_CONFIG_2, ppgRegs.sys_cfg2.byte);
}
// /***************************************************************************
// * 描 述 : max86174A_sys_config
// * 入 参 :
// * 返回值 :
// **************************************************************************/
static void max86174A_sys_config(void)
{
ppgRegs.sys_cfg1.bits.DISABLE_I2C = 0x01;
ppgRegs.sys_cfg1.bits.PPG1_PWRDN = 0x00;
ppgRegs.sys_cfg1.bits.PPG2_PWRDN = 0x00;
ppgRegs.sys_cfg1.bits.RESET = 0x00;
ppgRegs.sys_cfg1.bits.SHDN = 0x00;
ppgRegs.sys_cfg1.bits.SYNC_MODE = 0x00;
max86174A_writeReg(ADDR_REG_SYS_CONFIG_1, ppgRegs.sys_cfg1.byte);
max86174A_checkReg(ADDR_REG_SYS_CONFIG_1, ppgRegs.sys_cfg1.byte);
ppgRegs.sys_cfg3.bits.ALC_DISABLE = 0x00;
ppgRegs.sys_cfg3.bits.COLLECT_RAW_DATA = 0x00; //0x00:CDM or FDM 滤掉环境光后的数据放入FIFO; 0x01:原始数据直接放入FIFO;
ppgRegs.sys_cfg3.bits.MESA1_CONFIG_SEL = 0x00;
ppgRegs.sys_cfg3.bits.PROX_AUTO = 0x00;
ppgRegs.sys_cfg3.bits.PROX_DATA_EN = 0x00;
max86174A_writeReg(ADDR_REG_SYS_CONFIG_3, ppgRegs.sys_cfg3.byte);
max86174A_checkReg(ADDR_REG_SYS_CONFIG_3, ppgRegs.sys_cfg3.byte);
}
/***************************************************************************
* 描 述 : max86174A_FIFO_Config
* 入 参 :
* 返回值 :
**************************************************************************/
static void max86174A_FIFO_Config(void)
{
// ppgRegs.fifoConfig1.bits.FIFO_A_FULL = 0;
// max86174A_writeReg(ADDR_REG_FIFO_CONFIG1, ppgRegs.fifoConfig1.byte);
// max86174A_checkReg(ADDR_REG_FIFO_CONFIG1, ppgRegs.fifoConfig1.byte);
ppgRegs.fifoConfig2.bits.FIFO_RO = 0x00; //0x00:lose new 0x01: lose old
ppgRegs.fifoConfig2.bits.A_FULL_TYPE = 0x00;
ppgRegs.fifoConfig2.bits.FIFO_STAT_CLR = 0x01;
ppgRegs.fifoConfig2.bits.FLUSH_FIFO = 0x00;
ppgRegs.fifoConfig2.bits.FIFO_MARK = 0x00;
max86174A_writeReg(ADDR_REG_FIFO_CONFIG2, ppgRegs.fifoConfig2.byte);
max86174A_checkReg(ADDR_REG_FIFO_CONFIG2, ppgRegs.fifoConfig2.byte);
ppgRegs.int_enable_1.bits.A_FULL_EN = 0x00; //The INTB pin is trigged when A_FULL is set to 1
ppgRegs.int_enable_1.bits.ALC_OVF_EN = 0x00;
ppgRegs.int_enable_1.bits.EXP_OVF_EN = 0x00;
ppgRegs.int_enable_1.bits.FIFO_DATA_RDY_EN = 0x00;
ppgRegs.int_enable_1.bits.FRAME_RDY_EN = 0x00;
ppgRegs.int_enable_1.bits.THRESH1_HILO_EN = 0x00;
ppgRegs.int_enable_1.bits.THRESH2_HILO_EN = 0x00;
max86174A_writeReg(ADDR_REG_INTERRUPT_ENABLE_1, ppgRegs.int_enable_1.byte);
max86174A_checkReg(ADDR_REG_INTERRUPT_ENABLE_1, ppgRegs.int_enable_1.byte);
}
/***************************************************************************
* 描 述 : max86174A_PHOTODIODE_BIAS_Config
* 入 参 :
* 返回值 :
**************************************************************************/
static void max86174A_PHOTODIODE_BIAS_Config(void)
{
ppgRegs.pdBias.bits.PD1_BIAS = 0x01;
ppgRegs.pdBias.bits.PD2_BIAS = 0x01;
max86174A_writeReg(ADDR_REG_PHOTO_DIODE_BIAS, ppgRegs.pdBias.byte);
max86174A_checkReg(ADDR_REG_PHOTO_DIODE_BIAS, ppgRegs.pdBias.byte);
}
/***************************************************************************
* 描 述 : max86174A_INTB_Config
* 入 参 :
* 返回值 :
**************************************************************************/
static void max86174A_INTB_Config(void)
{
ppgRegs.pin_func_cfg.bits.INTB_FCFG = 0x01;
ppgRegs.pin_func_cfg.bits.TRIG_ICFG = 0x00;
max86174A_writeReg(ADDR_REG_PIN_FUNCTIONAL_CONFIG, ppgRegs.pin_func_cfg.byte);
max86174A_checkReg(ADDR_REG_PIN_FUNCTIONAL_CONFIG, ppgRegs.pin_func_cfg.byte);
ppgRegs.output_pin_cfg.bits.INTB_OCFG = 0x00;
ppgRegs.output_pin_cfg.bits.TRIGLED4_SEL = 0x01; //0x00:digital input TRIG 0x01:LED4_DRV
max86174A_writeReg(ADDR_REG_OUTPUT_PIN_CONFIG, ppgRegs.output_pin_cfg.byte);
max86174A_checkReg(ADDR_REG_OUTPUT_PIN_CONFIG, ppgRegs.output_pin_cfg.byte);
}
/***************************************************************************
* 描 述 : max86174A_FPS_Config
* 入 参 :
* 返回值 :
**************************************************************************/
static void max86174A_FPS_Config(uint16_t fps)
{
uint16_t FR_CLK_DIV;
FR_CLK_DIV = 32768 / fps;
max86174A_writeReg(ADDR_REG_FR_CLK_DIVIDER_MSB, FR_CLK_DIV >> 8);
max86174A_checkReg(ADDR_REG_FR_CLK_DIVIDER_MSB, FR_CLK_DIV >> 8);
max86174A_writeReg(ADDR_REG_FR_CLK_DIVIDER_LSB, FR_CLK_DIV & 0xff);
max86174A_checkReg(ADDR_REG_FR_CLK_DIVIDER_LSB, FR_CLK_DIV & 0xff);
// set to 1 fps
// max86174A_writeReg(ADDR_REG_FR_CLK_DIVIDER_MSB, 0x7f);
// max86174A_checkReg(ADDR_REG_FR_CLK_DIVIDER_MSB, 0x7f);
// max86174A_writeReg(ADDR_REG_FR_CLK_DIVIDER_LSB, 0xfe);
// max86174A_checkReg(ADDR_REG_FR_CLK_DIVIDER_LSB, 0xfe);
}
/***************************************************************************
* 描 述 : max86174A_MEAS1_Config 使用 Green LED 用于测量心率
* 入 参 :
* 返回值 :
**************************************************************************/
static void max86174A_MEAS1_Config(void)
{
ppgRegs.meas1_sel.bits.MEAS1_AMB = 0x00;
ppgRegs.meas1_sel.bits.MEAS1_DRVA = 0x00; //0x00 0x01:green 0x02:red 0x03:ir
ppgRegs.meas1_sel.bits.MEAS1_DRVB = 0x01;
max86174A_writeReg(ADDR_REG_MEAS1_SELECT, ppgRegs.meas1_sel.byte);
max86174A_checkReg(ADDR_REG_MEAS1_SELECT, ppgRegs.meas1_sel.byte);
ppgRegs.meas1_cfg1.bits.MEAS1_AVER = 0x00;
ppgRegs.meas1_cfg1.bits.MEAS1_TINT = 0x03;
ppgRegs.meas1_cfg1.bits.MEAS1_PDSEL = 0x02;
max86174A_writeReg(ADDR_REG_MEAS1_CONFIG_1, ppgRegs.meas1_cfg1.byte);
max86174A_checkReg(ADDR_REG_MEAS1_CONFIG_1, ppgRegs.meas1_cfg1.byte);
ppgRegs.meas1_cfg2.bits.MEAS1_SINC3_SEL = 0x00;
ppgRegs.meas1_cfg2.bits.MEAS1_FILT_SEL = 0x01;
ppgRegs.meas1_cfg2.bits.MEAS1_LED_RGE = 0x03;
ppgRegs.meas1_cfg2.bits.MEAS1_PPG2_ADC_RGE = 0x00;
ppgRegs.meas1_cfg2.bits.MEAS1_PPG1_ADC_RGE = 0x00;
max86174A_writeReg(ADDR_REG_MEAS1_CONFIG_2, ppgRegs.meas1_cfg2.byte);
max86174A_checkReg(ADDR_REG_MEAS1_CONFIG_2, ppgRegs.meas1_cfg2.byte);
ppgRegs.meas1_cfg3.bits.MEAS1_PD_SETLNG = 0x00;
ppgRegs.meas1_cfg3.bits.MEAS1_LED_SETLNG = 0x03;
max86174A_writeReg(ADDR_REG_MEAS1_CONFIG_3, ppgRegs.meas1_cfg3.byte);
max86174A_checkReg(ADDR_REG_MEAS1_CONFIG_3, ppgRegs.meas1_cfg3.byte);
// ppgRegs.meas1_cfg4.bits.MEAS1_PPG1_DACOFF = 0x00;
// ppgRegs.meas1_cfg4.bits.MEAS1_PPG2_DACOFF = 0x00;
// max86174A_writeReg(ADDR_REG_MEAS1_CONFIG_4, ppgRegs.meas1_cfg4.byte);
// max86174A_checkReg(ADDR_REG_MEAS1_CONFIG_4, ppgRegs.meas1_cfg4.byte);
max86174A_writeReg(ADDR_REG_MEAS1_LEDA_CURRENT, 0x04);
max86174A_checkReg(ADDR_REG_MEAS1_LEDA_CURRENT, 0x04);
max86174A_writeReg(ADDR_REG_MEAS1_LEDB_CURRENT, 0x04);
max86174A_checkReg(ADDR_REG_MEAS1_LEDB_CURRENT, 0x04);
}
/***************************************************************************
* 描 述 : max86174A_MEAS2_Config 使用 IR/red LED 用于测量血氧
* 入 参 :
* 返回值 :
**************************************************************************/
static void max86174A_MEAS2_Config(void)
{
ppgRegs.meas2_sel.bits.MEAS2_AMB = 0x00;
ppgRegs.meas2_sel.bits.MEAS2_DRVA = 0x02; //0x00 0x01:green 0x02:red 0x03:ir
ppgRegs.meas2_sel.bits.MEAS2_DRVB = 0x00;
max86174A_writeReg(ADDR_REG_MEAS2_SELECT, ppgRegs.meas2_sel.byte);
max86174A_checkReg(ADDR_REG_MEAS2_SELECT, ppgRegs.meas2_sel.byte);
ppgRegs.meas2_cfg1.bits.MEAS2_AVER = 0x00;
ppgRegs.meas2_cfg1.bits.MEAS2_TINT = 0x03;
ppgRegs.meas2_cfg1.bits.MEAS2_PDSEL = 0x00;
max86174A_writeReg(ADDR_REG_MEAS2_CONFIG_1, ppgRegs.meas2_cfg1.byte);
max86174A_checkReg(ADDR_REG_MEAS2_CONFIG_1, ppgRegs.meas2_cfg1.byte);
ppgRegs.meas2_cfg2.bits.MEAS2_SINC3_SEL = 0x00;
ppgRegs.meas2_cfg2.bits.MEAS2_FILT_SEL = 0x01;
ppgRegs.meas2_cfg2.bits.MEAS2_LED_RGE = 0x03;
ppgRegs.meas2_cfg2.bits.MEAS2_PPG2_ADC_RGE = 0x00;
ppgRegs.meas2_cfg2.bits.MEAS2_PPG1_ADC_RGE = 0x00;
max86174A_writeReg(ADDR_REG_MEAS2_CONFIG_2, ppgRegs.meas2_cfg2.byte);
max86174A_checkReg(ADDR_REG_MEAS2_CONFIG_2, ppgRegs.meas2_cfg2.byte);
ppgRegs.meas2_cfg3.bits.MEAS2_PD_SETLNG = 0x00;
ppgRegs.meas2_cfg3.bits.MEAS2_LED_SETLNG = 0x00;
max86174A_writeReg(ADDR_REG_MEAS2_CONFIG_3, ppgRegs.meas2_cfg3.byte);
max86174A_checkReg(ADDR_REG_MEAS2_CONFIG_3, ppgRegs.meas2_cfg3.byte);
// ppgRegs.meas2_cfg4.bits.MEAS2_PPG1_DACOFF = 0x00;
// ppgRegs.meas2_cfg4.bits.MEAS2_PPG2_DACOFF = 0x00;
// max86174A_writeReg(ADDR_REG_MEAS2_CONFIG_4, ppgRegs.meas2_cfg4.byte);
// max86174A_checkReg(ADDR_REG_MEAS2_CONFIG_4, ppgRegs.meas2_cfg4.byte);
max86174A_writeReg(ADDR_REG_MEAS2_LEDA_CURRENT, 0x04);
max86174A_checkReg(ADDR_REG_MEAS2_LEDA_CURRENT, 0x04);
max86174A_writeReg(ADDR_REG_MEAS2_LEDB_CURRENT, 0x00);
max86174A_checkReg(ADDR_REG_MEAS2_LEDB_CURRENT, 0x00);
}
/***************************************************************************
* 描 述 : max86174A_MEAS3_Config
* 入 参 :
* 返回值 :
**************************************************************************/
static void max86174A_MEAS3_Config(void)
{
ppgRegs.meas3_sel.bits.MEAS3_AMB = 0x00; //如果启用环境光测量,将忽略LED配置和电流配置
ppgRegs.meas3_sel.bits.MEAS3_DRVA = 0x03;
ppgRegs.meas3_sel.bits.MEAS3_DRVB = 0x00;
max86174A_writeReg(ADDR_REG_MEAS3_SELECT, ppgRegs.meas3_sel.byte);
ppgRegs.meas3_cfg1.bits.MEAS3_AVER = 0x00;
ppgRegs.meas3_cfg1.bits.MEAS3_PDSEL = 0x00;
ppgRegs.meas3_cfg1.bits.MEAS3_TINT = 0x03;
max86174A_writeReg(ADDR_REG_MEAS3_CONFIG_1, ppgRegs.meas3_cfg1.byte);
ppgRegs.meas3_cfg2.bits.MEAS3_SINC3_SEL = 0x00;
ppgRegs.meas3_cfg2.bits.MEAS3_FILT_SEL = 0x01;
ppgRegs.meas3_cfg2.bits.MEAS3_LED_RGE = 0x03;
ppgRegs.meas3_cfg2.bits.MEAS3_PPG2_ADC_RGE = 0x00;
ppgRegs.meas3_cfg2.bits.MEAS3_PPG1_ADC_RGE = 0x00;
max86174A_writeReg(ADDR_REG_MEAS3_CONFIG_2, ppgRegs.meas3_cfg2.byte);
ppgRegs.meas3_cfg3.bits.MEAS3_PD_SETLNG = 0x00;
ppgRegs.meas3_cfg3.bits.MEAS3_LED_SETLNG = 0x00;
max86174A_writeReg(ADDR_REG_MEAS3_CONFIG_3, ppgRegs.meas3_cfg3.byte);
max86174A_writeReg(ADDR_REG_MEAS3_LEDA_CURRENT, 0x01);
max86174A_checkReg(ADDR_REG_MEAS3_LEDA_CURRENT, 0x01);
max86174A_writeReg(ADDR_REG_MEAS3_LEDB_CURRENT, 0x00);
max86174A_checkReg(ADDR_REG_MEAS3_LEDB_CURRENT, 0x00);
}
//---------------------------------------提供给外部的借口----------------------------------------------------
/***************************************************************************
* 描 述 : max86174A_FIFO_Config
* 入 参 :
* 返回值 :
**************************************************************************/
void max86174A_flushFIFO(void)
{
// Empty the FIFO by set the FLUSH_FIFO bit to 1, in register MAX86174A_FIFO_Configuration_2 (0x09)
max86174A_writeReg(ADDR_REG_FIFO_CONFIG2, 0x01 << 4);
}
/***************************************************************************
* 描 述 : max86174A_read_chipID
* 入 参 :
* 返回值 :
**************************************************************************/
uint8_t max86174A_read_chipID(void)
{
uint8_t ret = 0;
uint8_t cmd = SPI_READ_CMD;
SPI_PPG_CS_LOW;
spi_read_write(ADDR_REG_PART_ID);
spi_read_write(cmd);
ret = spi_read_write(0xff);
SPI_PPG_CS_HIGH;
return ret;
}
/***************************************************************************
* 描 述 : max86174A_FIFO_data_ready
* 入 参 :
* 返回值 :
**************************************************************************/
uint8_t max86174A_FIFO_data_ready(void)
{
uint8_t ret;
ret = ((max86174A_readReg(ADDR_REG_INT_STATUS1) >> 5) & 0x01);
// SEGGER_RTT_printf(0, "status 1 rdy bit:%d \r\n", ret);
return ret;
}
/***************************************************************************
* 描 述 : max86174A_get_FIFO_count
* 入 参 :
* 返回值 :
**************************************************************************/
uint16_t max86174A_get_FIFO_count(void)
{
uint16_t fifo_count_msb, fifo_count_lsb, fifo_count;
fifo_count_msb = max86174A_readReg(ADDR_REG_FIFO_OVF_COUNTER_1) & 0x80; //FIFO data count the most significant bit
fifo_count_lsb = max86174A_readReg(ADDR_REG_FIFO_DATA_COUNTER_2); //FIFO data count low 8-bit
fifo_count = ((fifo_count_msb << 1) | fifo_count_lsb);
return fifo_count;
}
/***************************************************************************
* 描 述 : max86174A_Init_From_datasheet
* 入 参 :
* 返回值 :
**************************************************************************/
void max86174A_Init_From_datasheet(MEASx_enable_cfg_t *measx_cfg) //初始化策略来自数据手册
{
//reset
max86174A_reset();
max86174A_shutdown();
//System Configuration
max86174A_enable_MEAS(measx_cfg->meas1_enable,
measx_cfg->meas2_enable,
measx_cfg->meas3_enable,
measx_cfg->meas4_enable,
measx_cfg->meas5_enable,
measx_cfg->meas6_enable);
max86174A_sys_config();
//光电二极管偏置 配置
max86174A_PHOTODIODE_BIAS_Config();
//INTB pin config
max86174A_INTB_Config();
//config PPG frame rate
max86174A_FPS_Config(50);
//Measurement 1 Setup
max86174A_MEAS1_Config(); //use two Green LEDs
// //Measurement 2 Setup
max86174A_MEAS2_Config(); //use Red LED
// //Measurement 3 Setup
max86174A_MEAS3_Config(); //use IR LED
//FIFO config
max86174A_FIFO_Config();
max86174A_flushFIFO();
max86174A_start();
}
/***************************************************************************
* 描 述 : max86174A_read_FIFO_Data
* 入 参 :
* 返回值 :
**************************************************************************/
uint16_t max86174A_read_FIFO_Data(uint8_t* data)
{
// 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)
//Configure the interrupt callback, read the data from FIFO of max86174 after the INTB signals received.
uint16_t fifo_count;
uint8_t overflow_count = 0;
uint16_t avail_count = 0;
max86174A_readReg(ADDR_REG_INT_STATUS1);
max86174A_readReg(ADDR_REG_INT_STATUS2);
overflow_count = (max86174A_readReg(ADDR_REG_FIFO_OVF_COUNTER_1) & 0x7f);
fifo_count = max86174A_get_FIFO_count();
// SEGGER_RTT_printf(0, "[driver]fifo_count:%d | fifo_ovf:%d\n", fifo_count, overflow_count);
if(overflow_count == 0) //no data overflow
{
avail_count = fifo_count;
}
else
{
avail_count = 255; //overflow occurred and data has been lost
}
max86174A_readRegEx(ADDR_REG_FIFO_DATA, data, avail_count * 3);
return fifo_count;
}
能力有限,研究不深;
有问题欢迎留言讨论!
个人邮箱:imxyp9x@163.com