STM32F4-从max30100丢失FIFO数据样本

STM32F4-从max30100丢失FIFO数据样本,stm32,fifo,stm32f4,heartrate,Stm32,Fifo,Stm32f4,Heartrate,我正在使用MCU STM32F4从MAX30100获取FIFO数据,以测量心率。在接收到的信号中,我可以看到心跳,但在样本中也出现了故障,如下所示: 我没有一个滤波器工作,但没有滤波器的信号是不同的,当我在Arduino板上这样做。我丢失了样本还是正常?我做错了什么 数据表MAX30100: 我的代码如下: /* Includes ------------------------------------------------------------------*/ #include "mai

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

我没有一个滤波器工作,但没有滤波器的信号是不同的,当我在Arduino板上这样做。我丢失了样本还是正常?我做错了什么

数据表MAX30100:

我的代码如下:

/* 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);
}
/*包括------------------------------------------------------------------*/
#包括“main.h”
#包括“usb_设备.h”
/*私有定义------------------------------------------------------------*/
//先进先出寄存器
#定义MAX30100_FIFO_W_指针0x02
#定义MAX30100_OVF_计数器0x03
#定义MAX30100\u FIFO\u R\u指针0x04
#定义MAX30100\u FIFO\u数据\u注册表0x05
//配置寄存器
#定义MAX30100_模式_配置0x06
#定义MAX30100\U SPO2\U配置0x07
#定义MAX30100_LED_配置0x09
//部件ID寄存器
#定义MAX30100\u零件号0xFF
//MAX30100 I2C地址
#定义MAX30100_地址0xAE//8位地址转换为7位+W
#定义MAX30100_RADDRESS 0xAF//8位地址转换为7位+R
/*私有变量---------------------------------------------------------*/
I2C_手柄类型定义hi2c3;
字符缓冲区[30];
无符号长ir_buff[16]={0},红色_buff[16]={0};
/*私有函数原型-----------------------------------------------*/
无效系统时钟配置(无效);
静态void MX_GPIO_Init(void);
静态void MX_I2C3_Init(void);
uint8的CDC传输文件(字符*Buf,uint16的长度);
uint8\u t MAX30100\u getNumSamp(uint16\u t*ir\u buff,uint16\u t*red\u buff);
uint8\u t MAX30100\u getPartID(无效);
无效MAX30100_重置(无效);
void MAX30100_唤醒(void);
无效MAX30100_SetHR(无效);
无效MAX30100_初始FIFO(无效);
无效MAX30100_设置LED(uint8_t LED电流红色,uint8_t LED电流红色);
无效最大值30100_设置(uint8_t sr);
无效最大值30100_设置pw(uint8_t pw);
uint8\u t MAX30100\u读取(uint8\u t设备\u寄存器);
无效MAX30100_写入(uint8_t设备_寄存器、uint8_t寄存器数据);
内部主(空)
{
uint8_t id;
uint8_t i;
uint8_t样品;
uint16平均值=0;
uint16红色平均值=0;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C3_Init();
MX_USB_设备_Init();
halu延迟(10);
MAX30100_重置();
id=MAX30100_getPartID();
if(id==0x11)//确定
//设置LED电流
MAX30100_设置LED(0x07、0xFF);
//设定采样率
MAX30100_设置值(0x00);
//设置脉冲宽度
MAX30100_设置pw(0x3);
//设定心率模式
MAX30100_SetHR();
//将RD和WR指针设置为0x00
MAX30100_InitFIFO();
//醒醒
MAX30100_唤醒();
而(1)
{
//获取FIFO中的样本数,然后读取
samples=MAX30100_getNumSamp((uint16_t*)ir_buff,(uint16_t*)red_buff);
如果(样本数>0)
{
//我们有先进先出的数据
HAL_GPIO_WritePin(GPIOC,GPIO_引脚_14,1);//LED亮起
ir_平均值=0;
红色_平均值=0;
对于(i=0;i