1

我使用 MCU STM32F4 从 MAX30100 获取 FIFO 数据来测量心率。在收到的信号中,我可以看到心跳,但在样本中也失败了,如下所示:

在此处输入图像描述

我没有过滤器工作,但是当我在 Arduino 板上这样做时,没有过滤器的信号是不同的。我是丢失样品还是正常现象?我做错了什么?

MAX30100 数据表:https ://img.filipeflop.com/files/download/Datasheet_MAX30100.pdf

按照我的代码:

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_device.h"

/* Private define ------------------------------------------------------------*/
// FIFO registers
#define MAX30100_FIFO_W_POINTER      0x02
#define MAX30100_OVF_COUNTER         0x03
#define MAX30100_FIFO_R_POINTER      0x04
#define MAX30100_FIFO_DATA_REG       0x05

// configuration registers
#define MAX30100_MODE_CONFIG         0x06
#define MAX30100_SPO2_CONFIG         0x07
#define MAX30100_LED_CONFIG          0x09

// PART ID registers
#define MAX30100_PART_ID             0xFF

// MAX30100 I2C addresses
#define MAX30100_WADDRESS        0xAE  // 8bit address converted to 7bit + W
#define MAX30100_RADDRESS        0xAF  // 8bit address converted to 7bit + R

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c3;
char buffer[30];
unsigned long ir_buff[16]  = {0}, red_buff[16] = {0};

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C3_Init(void);
uint8_t CDC_Transmit_FS(char* Buf, uint16_t Len);
uint8_t MAX30100_getNumSamp(uint16_t* ir_buff, uint16_t* red_buff);
uint8_t MAX30100_getPartID(void);
void MAX30100_reset(void);
void MAX30100_wakeup(void);
void MAX30100_SetHR (void);
void MAX30100_InitFIFO (void);
void MAX30100_setLEDs(uint8_t ledCurrentRed, uint8_t ledCurrentIr);
void MAX30100_setSR(uint8_t sr);
void MAX30100_setPW (uint8_t pw);
uint8_t MAX30100_read (uint8_t device_register);
void MAX30100_write (uint8_t device_register, uint8_t reg_data);

int main(void)
{
    uint8_t id;
    uint8_t i;
    uint8_t samples;
    uint16_t ir_average = 0;
    uint16_t red_average = 0;

    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_I2C3_Init();
    MX_USB_DEVICE_Init();
    HAL_Delay(10);

    MAX30100_reset();
    id = MAX30100_getPartID();
    if (id == 0x11) //OK

    // Set LED current
    MAX30100_setLEDs(0x07, 0xFF);
    // Set sample rate
    MAX30100_setSR(0x00);
    // Set pulse width
    MAX30100_setPW(0x3);
    // Set heart rate mode
    MAX30100_SetHR ();
    // Set RD and WR pointers to 0x00
    MAX30100_InitFIFO();
    // Wake up
    MAX30100_wakeup();

    while (1)
    {
      // Gets the number  of samples in the FIFO and reads then
      samples = MAX30100_getNumSamp((uint16_t*)ir_buff, (uint16_t*)red_buff);
      if (samples > 0 )
      {
         // we have data in FIFO
         HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,1); //LED ON

         ir_average = 0;
         red_average = 0;

         for (i = 0; i < samples; i++)
         {
             ir_average += (uint16_t)ir_buff[i];
             red_average += (uint16_t)red_buff[i];
         }

         ir_average  /= samples; // calculate the average value for this reading
         red_average /= samples;

         memset(buffer,0,sizeof(buffer));
         sprintf(buffer, "HR: %d,", (uint16_t)ir_average);
         CDC_Transmit_FS((char*)buffer, 20); //print the ir value to CDC
      }
      else
      {
         // There's no data in FIFO
         HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,0); //LED OFF
         HAL_Delay(1); // Wait for samples to be aquired
      }
    }
}

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                          |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
}

static void MX_I2C3_Init(void)
{
  hi2c3.Instance = I2C3;
  hi2c3.Init.ClockSpeed = 400000;
  hi2c3.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c3.Init.OwnAddress1 = 0;
  hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c3.Init.OwnAddress2 = 0;
  hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c3) != HAL_OK)
  {
    Error_Handler();
  }
}

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);

  /*Configure GPIO pins : PC14 PC15 */
  GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

}

// Reads from register 0xFF
// should return 0x11
uint8_t MAX30100_getPartID(void)
{
    uint8_t reg;
   reg =  MAX30100_read (MAX30100_PART_ID);
   return reg;
}

// Resets the MAX30100 IC
void MAX30100_reset(void)
{
   uint8_t reg;
   reg =  MAX30100_read (MAX30100_MODE_CONFIG);
   // RESET bit is B6
   // 0x40 = 0100 0000
   reg = (reg | 0x40); // Set reset bit to 1
   MAX30100_write (MAX30100_MODE_CONFIG, reg);
}

// Wakes up the MAX30100
void MAX30100_wakeup(void)
{
   uint8_t reg;
   reg =  MAX30100_read (MAX30100_MODE_CONFIG);
   reg = reg & 0x7F; // Set SHDN bit to 0
   MAX30100_write (MAX30100_MODE_CONFIG, reg);
}

// Sets Heart rate mode
// This means MODE{2:0} = 0b010 (or 0x02 in hexadecimal)
void MAX30100_SetHR (void)
{
   uint8_t reg;
   reg =  MAX30100_read (MAX30100_MODE_CONFIG);
   // RESET bit is B7
   // First we clear bits 2:0
   reg = reg & 0xF8;
   // Then we set bits 2:0 to 0x02
   reg = reg | 0x02;
   MAX30100_write (MAX30100_MODE_CONFIG, reg);
}

// Initializes FIFO
// Sets RD and WR pointers to 0
// Clears OVF
void MAX30100_InitFIFO (void)
{
   MAX30100_write (MAX30100_FIFO_W_POINTER, 0x00);
   MAX30100_write (MAX30100_FIFO_R_POINTER, 0x00);
   MAX30100_write (MAX30100_OVF_COUNTER, 0x00);
}

// Sets LED currents
void MAX30100_setLEDs(uint8_t ledCurrentRed, uint8_t ledCurrentIr)
{
   uint8_t reg;
   reg = ( ledCurrentRed << 4 ) | ledCurrentIr;
   MAX30100_write (MAX30100_LED_CONFIG, reg);
}

// Sets sample rate
// sample rate is bits 4:2 of register MAX30100_SPO2_CONFIG
// bitmask is 0xE3
void MAX30100_setSR (uint8_t sr)
{
   uint8_t reg;
   reg =  MAX30100_read (MAX30100_SPO2_CONFIG);
   reg = reg & 0xE3;
   reg = reg | (sr << 2);
   MAX30100_write (MAX30100_SPO2_CONFIG, reg);
}

// Sets pulse width
// sample rate is bits 1:0 of register MAX30100_SPO2_CONFIG
void MAX30100_setPW (uint8_t pw)
{
   uint8_t reg;
   reg =  MAX30100_read (MAX30100_SPO2_CONFIG);
   reg = reg & 0xFC;
   reg = reg | pw;
   MAX30100_write (MAX30100_SPO2_CONFIG, reg);
}

// Gets number of samples in FIFO and read then
uint8_t MAX30100_getNumSamp(uint16_t* ir_buff, uint16_t* red_buff)
{
    uint8_t wreg;
    uint8_t rreg;
    uint8_t sampleNum;
    uint8_t samples[4];
    wreg = MAX30100_read (MAX30100_FIFO_W_POINTER);
    rreg = MAX30100_read (MAX30100_FIFO_R_POINTER);
    sampleNum = (abs( 16 + wreg - rreg ) % 16);

    if(sampleNum > 0)
    {
        //HAL_I2C_Mem_Read(&hi2c3,MAX30100_RADDRESS,MAX30100_FIFO_DATA_REG,4,(uint8_t*)samples,1,1000);
        HAL_I2C_Mem_Read(&hi2c3,MAX30100_RADDRESS,MAX30100_FIFO_DATA_REG,1,&samples[0],1,250);
        HAL_I2C_Mem_Read(&hi2c3,MAX30100_RADDRESS,MAX30100_FIFO_DATA_REG,1,&samples[1],1,250);
        HAL_I2C_Mem_Read(&hi2c3,MAX30100_RADDRESS,MAX30100_FIFO_DATA_REG,1,&samples[2],1,250);
        HAL_I2C_Mem_Read(&hi2c3,MAX30100_RADDRESS,MAX30100_FIFO_DATA_REG,1,&samples[3],1,250);

        *(ir_buff) =  (uint16_t)samples[1];
        *(ir_buff++) |= (uint16_t)samples[0] << 8;
        *(red_buff) = (uint16_t)samples[3];
        *(red_buff++) |=  (uint16_t) samples[2] << 8;
        //HAL_Delay(7); // just test
    }

    return sampleNum;
}

// My I2C read and write functions
uint8_t MAX30100_read (uint8_t device_register )
{
   uint8_t read_data;
   HAL_I2C_Mem_Read(&hi2c3,MAX30100_RADDRESS,device_register,I2C_MEMADD_SIZE_8BIT,&read_data,1,250);
   return read_data;
}

void MAX30100_write (uint8_t device_register, uint8_t reg_data)
{
   HAL_I2C_Mem_Write(&hi2c3,MAX30100_WADDRESS,device_register,I2C_MEMADD_SIZE_8BIT,&reg_data,1,250);
}
4

0 回答 0