气压传感器(msp880)
·
概述
项目上使用此款IC,在此写了一版demo,顺手做个笔录。注:气压计要想更加精准,需要要做校准的 手动补偿。
一、开发平台
环境:keil
stm32
二、代码
bsp_msp880.c
/******************** (C) COPYRIGHT 2019~2023 MEMSENSING **********************
* File Name : bas_msp880.c
* Author : champion
* Version : V1.1
* Date : 2023-02-13
* Description : MSP data Handle
*******************************************************************************/
#include "st_bas_msp.h"
#include "msp.h"
#include "math.h"
#ifdef MSP_USING_FIX_POINT
MSP_OTP_INT32_Typedef MSP_OTP_INT32_Structure;
#endif
#ifdef MSP_USING_FLOATING_POINT
MSP_OTP_Typedef MSP_OTP_Structure;
#endif
MSP_Press_Typedef MSP_Press_Structure;
MSP_Temperature_Typedef MSP_Temperature_Structure;
/*******************************************************************************
* Function Name : st_delay_us
* Description : us delay for STM32F429, HLK 168Mhz
* Input : time_cnt
* Output : None
* Return : None
*******************************************************************************/
void st_delay_us(uint16_t delay)
{
uint32_t i;
while(delay--)
{
i = 42;
while(i--);
}
}
/*******************************************************************************
* Function Name : msa_DelayMS
* Description : delay ms
* Input : time_cnt
* Output : None
* Return : None
*******************************************************************************/
void msa_DelayMS(uint16_t delay)
{
uint32_t i=0;
for(i=0; i<delay; i++)
{
st_delay_us(700);
}
}
void MSP_Delay_ms(uint16_t delay_time)
{
msa_DelayMS(delay_time);
}
/*******************************************************************************
* Function Name : i2c_read_block_data
* Description : MSP data read , I2C mode
* Input : address , sizeof(data_read) , data_return
* Output : None
* Return : -1:read fail sizeif(data_read):read success
*******************************************************************************/
int32_t i2c_read_block_data(uint8_t base_addr, uint8_t count, uint8_t *data)
{
int32_t i = 0;
for(i = 0; i < count;i++)
{
if(i2c_read_byte_data(base_addr+i,(data+i)))
{
return -1;
}
}
return count;
}
/*******************************************************************************
* Function Name : i2c_read_byte_data
* Description : MSP data read , I2C mode
* Input : address , data_return
* Output : None
* Return : 0:read success others: read fail
*******************************************************************************/
int32_t i2c_read_byte_data(uint8_t addr, uint8_t *data)
{
int status = 0;
status = msp_ReadBytes(data,addr);
return (!status);
}
/*******************************************************************************
* Function Name : msp_ReadBytes
* Description : MSP byte read, I2C mode
* Input : address , data_return
* Output : None
* Return : 0:read fail 1:read success
*******************************************************************************/
bool msp_ReadBytes(uint8_t* Data, uint8_t RegAddr)
{
SW_i2c_start(); //start bit
ms_SendByte(MS_I2C_Addr << 1); //slave address|write bit
if(FALSE == ms_ChkAck()) //check Ack bit
{
//TO_DO: display ack check fail when send write id
SW_i2c_stop();
return FALSE;
}
ms_SendByte(RegAddr); //send RegAddr
if(FALSE == ms_ChkAck()) //check Ack bit
{
//TO_DO: display ack check fail when send RegAddr
SW_i2c_stop();
return FALSE;
}
ms_Restart(); //restart bit
ms_SendByte(MS_I2C_Addr<<1 | MS_I2C_Addr_Read); //slave address|read bit
if(FALSE == ms_ChkAck())
{
//TO_DO: display ack check fail when send read id
SW_i2c_stop();
return FALSE;
}
*Data = ms_ReadByteNAck();
SW_i2c_stop(); //stop bit
//TO_DO: add debug code to display the data received
return TRUE;
}
/*******************************************************************************
* Function Name : msp_WriteBytes
* Description : MSP date write, I2C mode
* Input : address , data_write
* Output : None
* Return : 0:write fail 1:write success
*******************************************************************************/
bool msp_WriteBytes(uint8_t RegAddr, uint8_t Data)
{
SW_i2c_start(); //start bit
ms_SendByte(MS_I2C_Addr<<1 | MS_I2C_Addr_Write); //slave address|write bit
if(FALSE == ms_ChkAck()) //check Ack bit
{
//TO_DO: display check ack fail when send write id
SW_i2c_stop();
return FALSE;
}
ms_SendByte(RegAddr); //send RegAddr
if(FALSE == ms_ChkAck()) //check Ack bit
{
//TO_DO: display check ack fail when send RegAddr
SW_i2c_stop();
return FALSE;
}
ms_SendByte(Data); //send parameter
if(FALSE == ms_ChkAck())
{
//TO_DO: display check ack fail when send data
SW_i2c_stop();
return FALSE;
}
SW_i2c_stop(); //stop bit
return TRUE;
}
/*******************************************************************************
* Function Name : ms_SendByte
* Description : MSP send byte, I2C mode
* Input : data
* Output : None
* Return : 0:read fail 1:read success
*******************************************************************************/
void ms_SendByte(uint8_t Data)
{
int32_t i;
for (i=7; i>=0; i--)
{
if ((Data>>i)&0x01)
{
MS_I2C_DATA_HIGH;
}
else
{
MS_I2C_DATA_LOW;
}
SW_i2c_one_clk();
}
}
/*******************************************************************************
* Function Name : SW_i2c_start
* Description : I2C start, software mode
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SW_i2c_start(void)
{
MS_SCL_OUT;
MS_SDA_OUT;
MS_I2C_DATA_HIGH;
MS_I2C_CLK_HIGH;
st_delay_us(40); //40us
MS_I2C_DATA_LOW;
st_delay_us(20); //20us
MS_I2C_CLK_LOW;
st_delay_us(20); //20us
}
/*******************************************************************************
* Function Name : SW_i2c_stop
* Description : I2C stop, software mode
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SW_i2c_stop(void)
{
MS_SCL_OUT;
MS_SDA_OUT;
MS_I2C_DATA_LOW;
st_delay_us(20); //20us
MS_I2C_CLK_HIGH;
st_delay_us(20); //20us
MS_I2C_DATA_HIGH;
st_delay_us(20); //20us
}
/*******************************************************************************
* Function Name : ms_Restart
* Description : I2C restart, software mode
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void ms_Restart(void)
{
MS_SCL_OUT;
MS_SDA_OUT;
st_delay_us(40); //40us
MS_I2C_DATA_HIGH;
st_delay_us(20); //20us
MS_I2C_CLK_HIGH;
st_delay_us(40);
MS_I2C_DATA_LOW;
st_delay_us(40); //20us
MS_I2C_CLK_LOW;
st_delay_us(20); //20us
}
/*******************************************************************************
* Function Name : SW_i2c_one_clk
* Description : I2C one clk send
* Input : None
* Output : None
* Return : None
* Notice : the max frequence of i2c clk is 400K, then the min clk is 2.5us
*******************************************************************************/
void SW_i2c_one_clk(void)
{
st_delay_us(10); //10us
MS_I2C_CLK_HIGH;
st_delay_us(20); //20us
MS_I2C_CLK_LOW;
st_delay_us(10); //10us
}
/*******************************************************************************
* Function Name : ms_ChkAck
* Description : I2C Ack
* Input : None
* Output : None
* Return : 1:Ack 0:no Ack
*******************************************************************************/
bool ms_ChkAck(void)
{
MS_SDA_IN;
st_delay_us(10); //10us
MS_I2C_CLK_HIGH;
st_delay_us(10); //10us
if(MS_I2C_GET_BIT) //Non-ack
{
st_delay_us(10); //10us
MS_I2C_CLK_LOW;
st_delay_us(10); //10us
MS_SDA_OUT;
MS_I2C_DATA_LOW;
return FALSE;
}
else //Ack
{
st_delay_us(10); //10us
MS_I2C_CLK_LOW;
st_delay_us(10); //10us
MS_SDA_OUT;
MS_I2C_DATA_LOW;
return TRUE;
}
}
/*******************************************************************************
* Function Name : ms_ReadByteNAck
* Description : I2C data read without ack
* Input : None
* Output : None
* Return : data read
*******************************************************************************/
uint8_t ms_ReadByteNAck(void)
{
int32_t i;
uint8_t data;
MS_SDA_IN;
data = 0;
for (i=7; i>=0; i--)
{
if (MS_I2C_GET_BIT)
{
data |= (0x01<<i);
}
SW_i2c_one_clk();
}
MS_SDA_OUT;
MS_I2C_DATA_HIGH;
SW_i2c_one_clk();
return data;
}
/*******************************************************************************
* Function Name : msp_read_pressure
* Description : MSP pressure data read , I2C mode
* Input : *pressure
* Output : None
* Return : None
*******************************************************************************/
void msp_read_press(uint32_t *press)
{
uint8_t temp_data[3] = {0,0,0};
//press read signal, OSR 8192
msp_WriteBytes(MS_REG_CONFIGURE,MS_PRESS_READ);
MSP_Delay_ms(30); //30ms delay,wait for ADC convert
if (msp_register_read_continuously(MS_REG_PRESS_MSB, 3, temp_data) == 0) {
MSP_LOG("error ");
return;
}
*press = temp_data[0]<<16 | temp_data[1]<<8 | temp_data[2];
}
/*******************************************************************************
* Function Name : msp_read_temperature
* Description : MSP temperature data read , I2C mode
* Input : *temperature
* Output : None
* Return : None
*******************************************************************************/
void msp_read_temperature(uint32_t *temperature)
{
uint8_t temp_data[2] = {0,0};
//temperature read signal, OSR 1024
msp_WriteBytes(MS_REG_CONFIGURE,MS_TEMPERATURE_READ);
MSP_Delay_ms(10); //10ms delay,wait for ADC convert
if (msp_register_read_continuously(MS_REG_TEMPERATURE_MSB, 2, temp_data) == 0) {
MSP_LOG("error ");
return;
}
*temperature = ((temp_data[0]&0x7F)<<8) | temp_data[1];
}
/*******************************************************************************
* Function Name : ST_USER_GetPressParam
* Description : MSP press data read
* Input : MSP_Press_Typedef
* Output : None
* Return : None
*******************************************************************************/
void ST_USER_GetPressParam(MSP_Press_Typedef *Press)
{
msp_read_press(&Press->Data_Read);
}
/*******************************************************************************
* Function Name : ST_USER_GetAllParam
* Description : MSP data read
* Input : MSP_Pre_Typedef
* Output : None
* Return : None
*******************************************************************************/
void ST_USER_GetTemperatureParam(MSP_Temperature_Typedef *Temperature)
{
msp_read_temperature(&Temperature->Data_Read);
}
/*******************************************************************************
* Function Name : MSP_Para_Calculate
* Description : MSP parameter calculate ( fix point data)
* Input :
* Output : None
* Return : None
*******************************************************************************/
#ifdef MSP_USING_FIX_POINT
void MSP_Para_Calculate_INT32(MSP_Press_Typedef *Press , MSP_Temperature_Typedef *Temperature)
{
int32_t deltaT,Ptemp,Ttemp;
int64_t var1,var2,p;
Ttemp = Temperature->Data_Read >> 1;
Temperature->Temperature_INT32[Temperature->Cnt] = ((((Ttemp * Ttemp) >> 5 ) * (MSP_OTP_INT32_Structure.Temp_a >> 5)) >>13 )+ \
(((Ttemp >> 2)* (MSP_OTP_INT32_Structure.Temp_b >> 3)) >> 10 ) + \
(MSP_OTP_INT32_Structure.Temp_c >> 2);
/*
Ttemp = Temperature->Data_Read >> 3;
Temperature->Temperature_INT32[Temperature->Cnt] = ((((Ttemp * Ttemp) >> 8 ) * MSP_OTP_INT32_Structure.Temp_a) >>11 )+ \
((Ttemp * MSP_OTP_INT32_Structure.Temp_b) >> 13 ) + \
(MSP_OTP_INT32_Structure.Temp_c >> 2);
*/
deltaT = (Temperature->Temperature_INT32[Temperature->Cnt] / 100) - (MSP_OTP_INT32_Structure.Tbase >> 4);
Ptemp = Press->Data_Read;
//var2 << 29
var1 = (1<<29) + (MSP_OTP_INT32_Structure.stc1 << 7 ) * deltaT + MSP_OTP_INT32_Structure.stc2 * deltaT * deltaT;
//var2 << 29
var2 = (Ptemp <<6) - (MSP_OTP_INT32_Structure.f0 <<14) - (MSP_OTP_INT32_Structure.ftc1 <<7 ) * deltaT - MSP_OTP_INT32_Structure.ftc2 * deltaT * deltaT ;
var2 *= 1250;
p = (MSP_OTP_INT32_Structure.s0 >> 3) * (var1 >> 15)* (var2 >> 15);
p>>= 25;
Press->Press_INT32[Press->Cnt] = ((p * 10000) >> 10) + ((MSP_OTP_INT32_Structure.ks >> 5)* (p >> 11) * (p >> 11) >> 9);
Press->Press_INT32[Press->Cnt] /= 1000;
}
#endif
/*******************************************************************************
* Function Name : MSP_Para_Calculate
* Description : MSP parameter calculate
* Input :
* Output : None
* Return : None
*******************************************************************************/
#ifdef MSP_USING_FLOATING_POINT
void MSP_Para_Calculate(MSP_Press_Typedef *Press , MSP_Temperature_Typedef *Temperature)
{
float P,P1,P2,P3, T;
T = Temperature->Data_Read / 16384.0f;
Temperature->Temperature = T*1.1307*128.0f+10.428f;
P = Press->Data_Read * (1.0f / 262144.0f);
P1 = MSP_OTP_Structure.C00 + MSP_OTP_Structure.C10*P + MSP_OTP_Structure.C20*P*P;
P2 = MSP_OTP_Structure.C01*T + MSP_OTP_Structure.C11*T*P + MSP_OTP_Structure.C21*T*P*P;
P3 = MSP_OTP_Structure.C02*T*T +MSP_OTP_Structure.C12*P*T*T;
Press->Press = P1 + P2 + P3;
//H=44300* (1- (P/P0)^ (1/5.256)) :H,P0=(0,101.325kPa)
Press->Height = 44330.0 * (1.0 - pow((float)(Press->Press)/101325.0, (1.0/5.255)));
RtkWristbandSys.barometer.temperature = Temperature->Temperature;
RtkWristbandSys.barometer.hPaValue = Press->Press / 100;
RtkWristbandSys.barometer.elevation = Press->Height;
MSP_LOG("Temperature->Data_Read:%d, T:%lf, Press->Data_Read:%d, P:%lf, Press->Press:%lf, Press->Press/100:%lf", Temperature->Data_Read, T, Press->Data_Read, P, Press->Press, Press->Press/100);
MSP_LOG("Temperature->Temperature:%lf, hPaValue:%lf, elevation:%d", Temperature->Temperature, RtkWristbandSys.barometer.hPaValue, RtkWristbandSys.barometer.elevation);
}
#endif
/*******************************************************************************
* Function Name : MSP_Configuration
* Description : MSP parameter init and setting
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void MSP_Configuration(void)
{
uint8_t temp_data[16] = {0};
int32_t temp;
MSP_Write_Reg(0x5C,0x00);
MSP_Delay_ms(20);
if (MSP_MultiRead_Reg(MS_REG_OTP_PARA, temp_data, 16) == 1)
{
MSP_LOG("error ");
return;
}
for(uint8_t i = 0; i < 16; i++) {
MSP_LOG("temp_data[%d] = 0x%x", i, temp_data[i]);
}
//C00
temp = temp_data[0]<<8|temp_data[1];
MSP_OTP_Structure.C00 = temp *10.0f;
//C10
temp = temp_data[2]<<8|temp_data[3];
MSP_OTP_Structure.C10 =temp*1.0f;
//C20
temp = temp_data[4]<<8|temp_data[5];
MSP_OTP_Structure.C20 = temp*(-1.0f / 1000.0f);
//C01
temp = temp_data[6]<<8|temp_data[7];
if(temp>8191)
MSP_OTP_Structure.C01 =(temp-16383)*10.0f;
else
MSP_OTP_Structure.C01 =temp*10.0f;
//C11
temp = temp_data[8]<<8|temp_data[9];
if(temp <8191)
MSP_OTP_Structure.C11 =temp*1.0f ;
else
MSP_OTP_Structure.C11 = (temp-16384)*1.0f;
//C21
temp = temp_data[10]<<8|temp_data[11];
if(temp >4095)
MSP_OTP_Structure.C21 =(temp-8191)*(1.0f / 1000.0f);
else
MSP_OTP_Structure.C21 = temp*(1.0f /1000.0f);
//C02
temp = temp_data[12]<<8|temp_data[13];
if(temp >16383)
MSP_OTP_Structure.C02 =(temp-32767)*1.0f;
else
MSP_OTP_Structure.C02 = temp*1.0f;
//C12
temp = (temp_data[14]&0x0f)<<8|temp_data[15];
if(temp <2047)
MSP_OTP_Structure.C12 =temp*1.0f ;
else
MSP_OTP_Structure.C12 = (temp-4095)/10.0f;
}
void MSP_Init(void)
{
uint8_t id = 0;
MSP_Delay_ms(40);
MSP_Read_Reg(MSP_ID, &id);
MSP_LOG("MSP - 0x10 : %d",id);
RtkWristbandSys.mp_function_state.bit.barometer = ((id>=0) && (id<=32))? 1:0;
if ((id>=0) && (id<=32)) {
MSP_LOG("Read MSP Success");
} else {
MSP_LOG("Read MSP Fail");
}
}
void MSP_UpDate(void)
{
ST_USER_GetTemperatureParam(&MSP_Temperature_Structure);
ST_USER_GetPressParam(&MSP_Press_Structure);
MSP_Para_Calculate(&MSP_Press_Structure, &MSP_Temperature_Structure);
}
void MSP_Bpm_algo_handler(void)
{
MSP_UpDate();
}
void MSP_Enable(void)
{
MSP_Configuration();
}
void MSP_Disable(void)
{
//enter dlps 低功耗
MSP_Write_Reg(0x5B,0x00);
}
/************************ (C) COPYRIGHT MEMSENSING *****END OF FILE****/
bsp_msp880.h
/******************** (C) COPYRIGHT 2019~2023 MEMSENSING **********************
* File Name : bas_msp880.h
* Author : champion
* Version : V1.1
* Date : 2023-02-13
* Description : MSP data Handle
*******************************************************************************/
#ifndef _ST_BAS_MSP_H_
#define _ST_BAS_MSP_H_
#include <stdint.h>
#define MSP_USING_FLOATING_POINT
//#define MSP_USING_FIX_POINT
#define Press_Buff_Length 20
#define Temperature_Buff_Length 20
#define MSP880_7BITI2C_ADDRESS 0x6C /*SDO external pull high or float , pull down 0x6C */
#define MSP880_ID 0x10 /* 0~32 */
#define MS_PRESS_READ 0xF3 //press osr 8192
#define MS_TEMPERATURE_READ 0xB3 //Temperature osr 1024
#define MS_REG_SOFT_RESET 0x50
#define MS_REG_PRESS_MSB 0x55
#define MS_REG_TEMPERATURE_MSB 0x58
#define MS_REG_CONFIGURE 0x5B
#define MS_REG_OTP_PARA 0x14
typedef struct{
float C00;
float C10;
float C20;
float C01;
float C11;
float C21;
float C02;
float C12;
}MSP_OTP_Typedef,*pMSP_OTP_Typedef;
extern MSP_OTP_Typedef MSP_OTP_Structure;
typedef struct{
int32_t s0;
int32_t stc1;
int32_t stc2;
int32_t ftc1;
int32_t ftc2;
int32_t f0;
int32_t ks;
int32_t Tbase;
int32_t Temp_a;
int32_t Temp_b;
int32_t Temp_c;
}MSP_OTP_INT32_Typedef,*pMSP_OTP_INT32_Typedef;
extern MSP_OTP_INT32_Typedef MSP_OTP_INT32_Structure;
typedef struct{
uint32_t Data_Read;
float Standard_Pressure;
int Measured_Standard_Value;
float Press;
float Height;
}MSP_Press_Typedef,*pMSP_Press_Typedef;
extern MSP_Press_Typedef MSP_Press_Structure;
typedef struct{
uint32_t Data_Read;
float Temperature;
}MSP_Temperature_Typedef,*pMSP_Temperature_Typedef;
extern MSP_Temperature_Typedef MSP_Temperature_Structure;
void ST_USER_GetPressParam(MSP_Press_Typedef *Press);
void ST_USER_GetTemperatureParam(MSP_Temperature_Typedef *Temperature);
void MSP_Para_Calculate(MSP_Press_Typedef *Press , MSP_Temperature_Typedef *Temperature);
void MSP_Para_Calculate_INT32(MSP_Press_Typedef *Press , MSP_Temperature_Typedef *Temperature);
void MSP_Configuration(void);
void MSP_Init(void);
void MSP_Bpm_algo_handler(void);
void MSP_Enable(void);
void MSP_Disable(void);
#endif /* _ST_BAS_MSP_H_ */
/************************ (C) COPYRIGHT MEMSENSING *****END OF FILE****/
main.c
.
.
.
#include "bsp_msp880.h"
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_DMA_Init();
MX_FATFS_Init();
/* USER CODE BEGIN 2 */
MSP_Init();
MSP_Enable();
/* USER CODE END 2 */
/* Init scheduler */
osKernelInitialize(); /* Call init function for freertos objects (in freertos.c) */
MX_FREERTOS_Init();
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
MSP880_Bpm_algo_handler();
HAL_Delay(200);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}三、运行结果

四、总结
好了,就介绍到此为止。
更多推荐
所有评论(0)