当前位置: 首页 > news >正文

STM32配置读取BMP280气压传感器数据

STM32配置读取BMP280气压传感器数据

BMP280是在BMP180基础上增强的绝对气压传感器,在飞控领域的高度识别方面应用也比较多。
在这里插入图片描述
BMP280和BMP180的区别:
在这里插入图片描述

市面上也有一些模块:
在这里插入图片描述
这里介绍STM32芯片和BMP280的连接和数据读取。

电路连接

BMP280和STM32的供电范围一致,可以在1.8V, 2.5V和3.3V多个供电电压点直接连接。

BMP280和STM32可以通过SPI或者I2C总线实现访问连接,I2C接口连接管脚少,这里采用I2C接口实现连接。

这里采用GPIO模拟I2C协议的方式,所以随意找2个管脚作为SCL和SDA。
在这里插入图片描述
用I2C总线连接时,BMP280的SDO管脚的电平状态用作I2C地址低位的选择。

运行过程

运行过程包括测试参数的配置选择:
在这里插入图片描述
也包括循环运行过程的节奏控制:
在这里插入图片描述
这里以STM32F401CCU6和STM32CUBEIDE开发环境为例,实现BMP280的访问读取数据,采用USB虚拟串口或普通串口方式打印输出。

初始化主要配置的寄存器0xF4 "ctrl_meas"的定义如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
过采样率oversampling会对采样分辨率和噪声产生影响:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
不同场景有推荐配置:
在这里插入图片描述

初始化主要配置的寄存器0xF5 "config"的定义如下:

在这里插入图片描述
在这里插入图片描述
测量时间和上面的测量间隔,就构成了数据输出率:
在这里插入图片描述
在这里插入图片描述
滤波参数和推荐:
在这里插入图片描述
按照数据手册表达方式,应该是
在这里插入图片描述

在这里插入图片描述

STM32工程配置

首先建立基本工程并配置时钟系统:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

配置USB虚拟串口:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置USART1作为通讯串口:
在这里插入图片描述
在这里插入图片描述
配置两个管脚作为与BMP280的通讯管脚:
在这里插入图片描述

保存并生成初始工程代码:
在这里插入图片描述

STM32工程代码

I2C模拟时序用到的微秒延时函数,参考: STM32 HAL us delay(微秒延时)的指令延时实现方式及优化
USB虚拟串口的实现,参考: STM32 USB VCOM和HID的区别,配置及Echo功能实现(HAL)
STM32串口打印的实现,参考: STM32 UART串口printf函数应用及浮点打印代码空间节省 (HAL)
采用减少代码编译size的方式,参考: STM32 region `FLASH‘ overflowed by xxx bytes 问题解决

代码逻辑识别USB虚拟串口是否连接,如果连接,则通过USB虚拟串口打印输出,否则通过普通串口打印输出。
上电或重启后,STM32对BMP280进行初始化,如果失败,则打印输出报错信息,如果成功,则循环进行检测和输出压力,高度和温度值。

建立BMP280.h放置一些寄存器访问地址参数:

#ifndef __BMP280_H
#define __BMP280_H#include "main.h"
#include "math.h"
#include "string.h"
#include "stdio.h"
/**  BMP280 register address*/
#define BMP280_REGISTER_DIG_T1      0x88
#define BMP280_REGISTER_DIG_T2      0x8A
#define BMP280_REGISTER_DIG_T3      0x8C#define BMP280_REGISTER_DIG_P1      0x8E
#define BMP280_REGISTER_DIG_P2      0x90
#define BMP280_REGISTER_DIG_P3      0x92
#define BMP280_REGISTER_DIG_P4      0x94
#define BMP280_REGISTER_DIG_P5      0x96
#define BMP280_REGISTER_DIG_P6      0x98
#define BMP280_REGISTER_DIG_P7      0x9A
#define BMP280_REGISTER_DIG_P8      0x9C
#define BMP280_REGISTER_DIG_P9      0x9E#define BMP280_REGISTER_CHIPID      0xD0
#define BMP280_REGISTER_VERSION     0xD1
#define BMP280_REGISTER_SOFTRESET   0xE0
#define BMP280_REGISTER_STATUS      0xF3
#define BMP280_REGISTER_CONTROL     0xF4
#define BMP280_REGISTER_CONFIG      0xF5#define BMP280_TEMP_XLSB_REG        0xFC	    /*Temperature XLSB Register */
#define BMP280_TEMP_LSB_REG         0xFB        /*Temperature LSB Register  */
#define BMP280_TEMP_MSB_REG         0xFA        /*Temperature LSB Register  */
#define BMP280_PRESS_XLSB_REG       0xF9		/*Pressure XLSB  Register   */
#define BMP280_PRESS_LSB_REG        0xF8		/*Pressure LSB Register     */
#define BMP280_PRESS_MSB_REG        0xF7		/*Pressure MSB Register     *//*calibration parameters */
#define BMP280_DIG_T1_LSB_REG                0x88
#define BMP280_DIG_T1_MSB_REG                0x89
#define BMP280_DIG_T2_LSB_REG                0x8A
#define BMP280_DIG_T2_MSB_REG                0x8B
#define BMP280_DIG_T3_LSB_REG                0x8C
#define BMP280_DIG_T3_MSB_REG                0x8D
#define BMP280_DIG_P1_LSB_REG                0x8E
#define BMP280_DIG_P1_MSB_REG                0x8F
#define BMP280_DIG_P2_LSB_REG                0x90
#define BMP280_DIG_P2_MSB_REG                0x91
#define BMP280_DIG_P3_LSB_REG                0x92
#define BMP280_DIG_P3_MSB_REG                0x93
#define BMP280_DIG_P4_LSB_REG                0x94
#define BMP280_DIG_P4_MSB_REG                0x95
#define BMP280_DIG_P5_LSB_REG                0x96
#define BMP280_DIG_P5_MSB_REG                0x97
#define BMP280_DIG_P6_LSB_REG                0x98
#define BMP280_DIG_P6_MSB_REG                0x99
#define BMP280_DIG_P7_LSB_REG                0x9A
#define BMP280_DIG_P7_MSB_REG                0x9B
#define BMP280_DIG_P8_LSB_REG                0x9C
#define BMP280_DIG_P8_MSB_REG                0x9D
#define BMP280_DIG_P9_LSB_REG                0x9E
#define BMP280_DIG_P9_MSB_REG                0x9Ftypedef struct {uint16_t T1; 		/*<calibration T1 data*/int16_t T2;  	 	/*<calibration T2 data*/int16_t T3;  		/*<calibration T3 data*/uint16_t P1;  	    /*<calibration P1 data*/int16_t P2;  		/*<calibration P2 data*/int16_t P3;  		/*<calibration P3 data*/int16_t P4;  		/*<calibration P4 data*/int16_t P5;  		/*<calibration P5 data*/int16_t P6;  		/*<calibration P6 data*/int16_t P7;  		/*<calibration P7 data*/int16_t P8;  		/*<calibration P8 data*/int16_t P9;			/*<calibration P9 data*/int32_t T_fine;	/*<calibration t_fine data*/
} BMP280_HandleTypeDef;typedef struct
{uint8_t Index;int32_t AvgBuffer[8];
} BMP280_AvgTypeDef;#define MSLP     101325          // Mean Sea Level Pressure = 1013.25 hPA (1hPa = 100Pa = 1mbar)
#define ALTITUDE_OFFSET          10000void I2C_Init(void);
void BMP280_Init();
void BMP280_CalTemperatureAndPressureAndAltitude(int32_t *temperature, int32_t *pressure, int32_t *Altitude);#endif /* __BMP280_H */其中ALTITUDE_OFFSET用于设定用户高度偏差。

建立BMP280.c实现访问和计算函数:


#include "BMP280.h"extern void PY_Delay_us_t(uint32_t Delay);
extern char console[128];//BMP280 I2C access protocol
#define us_num 2#define SCL_OUT_H HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET)
#define SCL_OUT_L HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET)
#define SDA_OUT_H HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET)
#define SDA_OUT_L HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET)
#define SDA_IN HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13)void I2C_Init(void)
{SCL_OUT_H;SDA_OUT_H;PY_Delay_us_t(100000);}void I2C_Start(void)
{PY_Delay_us_t(us_num) ;SDA_OUT_H;SCL_OUT_H;PY_Delay_us_t(us_num/2) ;SDA_OUT_L;PY_Delay_us_t(us_num/2) ;SCL_OUT_L;
}void I2C_Stop(void)
{SCL_OUT_L;PY_Delay_us_t(us_num) ;SDA_OUT_L;PY_Delay_us_t(us_num) ;SCL_OUT_H;PY_Delay_us_t(us_num) ;SDA_OUT_H;PY_Delay_us_t(us_num) ;
}void I2C_Write_Ack(void)
{PY_Delay_us_t(us_num/2) ;SDA_OUT_L;PY_Delay_us_t(us_num/2) ;SCL_OUT_H;PY_Delay_us_t(us_num) ;SCL_OUT_L;SDA_OUT_H;}uint8_t I2C_Read_Ack(void)
{uint8_t status=0;SCL_OUT_L;PY_Delay_us_t(us_num/2) ;SDA_OUT_H;PY_Delay_us_t(us_num/2) ;status = SDA_IN;SCL_OUT_H;PY_Delay_us_t(us_num) ;SCL_OUT_L;SDA_OUT_L;return status;}void I2C_Send_Byte(uint8_t txd){for(uint8_t i=0;i<8;i++){PY_Delay_us_t(us_num/2) ;if((txd&0x80)>>7) SDA_OUT_H;else SDA_OUT_L;txd<<=1;PY_Delay_us_t(us_num/2) ;SCL_OUT_H;PY_Delay_us_t(us_num) ;SCL_OUT_L;}SDA_OUT_L;
}uint8_t I2C_Read_Byte(unsigned char rdack)
{uint8_t rxd=0;for(uint8_t i=0;i<8;i++ ){SCL_OUT_L;PY_Delay_us_t(us_num/2) ;SDA_OUT_H;PY_Delay_us_t(us_num/2) ;SCL_OUT_H;rxd<<=1;if(SDA_IN) rxd++;PY_Delay_us_t(us_num) ;}SCL_OUT_L;SDA_OUT_H;if (rdack) I2C_Write_Ack();return rxd;
}#define BMP280_I2C_ADDR_SEL 1BMP280_HandleTypeDef bmp280;
#define dig_T1 bmp280.T1
#define dig_T2 bmp280.T2
#define dig_T3 bmp280.T3
#define dig_P1 bmp280.P1
#define dig_P2 bmp280.P2
#define dig_P3 bmp280.P3
#define dig_P4 bmp280.P4
#define dig_P5 bmp280.P5
#define dig_P6 bmp280.P6
#define dig_P7 bmp280.P7
#define dig_P8 bmp280.P8
#define dig_P9 bmp280.P9
#define t_fine bmp280.T_fineint32_t gs32Pressure0 = MSLP;void BMP280_WriteReg(uint8_t WrAddr, uint8_t data)
{uint8_t daddr; //device address (0x1e<<1)if(BMP280_I2C_ADDR_SEL==0) daddr = 0xec; //device address for SDO low status (0x76<<1)else daddr = 0xee; //device address for SDO high status (0x77<<1)I2C_Start();I2C_Send_Byte(daddr);I2C_Read_Ack();I2C_Send_Byte(WrAddr);I2C_Read_Ack();I2C_Send_Byte(data);I2C_Read_Ack();I2C_Stop();}uint8_t BMP280_ReadReg(uint8_t RdAddr)
{uint8_t RegValue = 0;uint8_t daddr;if(BMP280_I2C_ADDR_SEL==0) daddr = 0xec; //device address for SDO low status (0x76<<1)else daddr = 0xee; //device address for SDO high status (0x77<<1)I2C_Start();I2C_Send_Byte(daddr);I2C_Read_Ack();I2C_Send_Byte(RdAddr);I2C_Read_Ack();I2C_Start();I2C_Send_Byte(daddr+1);I2C_Read_Ack();RegValue=I2C_Read_Byte(0);I2C_Stop();return RegValue;
}/* Returns temperature in DegC, double precision. Output value of "1.23"equals 51.23 DegC. */
double BMP280_Compensate_Temperature(int32_t adc_T)
{double var1, var2, temperature;var1 = (((double) adc_T) / 16384.0 - ((double) dig_T1) / 1024.0) * ((double) dig_T2);var2 = ((((double) adc_T) / 131072.0 - ((double) dig_T1) / 8192.0)  * (((double) adc_T) / 131072.0- ((double) dig_T1) / 8192.0)) * ((double) dig_T3);t_fine = (int32_t) (var1 + var2);temperature = (var1 + var2) / 5120.0;return temperature;
}/* Returns pressure in Pa as double. Output value of "6386.2"equals 96386.2 Pa = 963.862 hPa */
double BMP280_Compensate_Pressure(int32_t adc_P)
{double var1, var2, pressure;var1 = ((double)t_fine / 2.0) - 64000.0;var2 = var1 * var1 * ((double) dig_P6) / 32768.0;var2 = var2 + var1 * ((double) dig_P5) * 2.0;var2 = (var2 / 4.0) + (((double) dig_P4) * 65536.0);var1 = (((double) dig_P3) * var1 * var1 / 524288.0  + ((double) dig_P2) * var1) / 524288.0;var1 = (1.0 + var1 / 32768.0) * ((double) dig_P1);if (var1 == 0.0) {return 0; // avoid exception caused by division by zero}pressure = 1048576.0 - (double) adc_P;pressure = (pressure - (var2 / 4096.0)) * 6250.0 / var1;var1 = ((double) dig_P9) * pressure * pressure / 2147483648.0;var2 = pressure * ((double) dig_P8) / 32768.0;pressure = pressure + (var1 + var2 + ((double) dig_P7)) / 16.0;return pressure;
}double BMP280_Get_Pressure(void)
{uint8_t lsb, msb, xlsb;int32_t adc_P;xlsb = BMP280_ReadReg(BMP280_PRESS_XLSB_REG);lsb = BMP280_ReadReg(BMP280_PRESS_LSB_REG);msb = BMP280_ReadReg(BMP280_PRESS_MSB_REG);adc_P = (msb << 12) | (lsb << 4) | (xlsb >> 4);//adc_P = 51988;return BMP280_Compensate_Pressure(adc_P);
}void BMP280_Get_Temperature_And_Pressure(double *temperature, double *pressure)
{uint8_t lsb, msb, xlsb;int32_t adc_P,adc_T;xlsb = BMP280_ReadReg(BMP280_TEMP_XLSB_REG);lsb = BMP280_ReadReg(BMP280_TEMP_LSB_REG);msb = BMP280_ReadReg(BMP280_TEMP_MSB_REG);adc_T = (msb << 12) | (lsb << 4) | (xlsb >> 4);//adc_T = 415148;* temperature = BMP280_Compensate_Temperature(adc_T);xlsb = BMP280_ReadReg(BMP280_PRESS_XLSB_REG);lsb = BMP280_ReadReg(BMP280_PRESS_LSB_REG);msb = BMP280_ReadReg(BMP280_PRESS_MSB_REG);adc_P = (msb << 12) | (lsb << 4) | (xlsb >> 4);//adc_P = 51988;* pressure = BMP280_Compensate_Pressure(adc_P);
}#define BMP280_AVG_TIMES 8 //maximum: 8
void BMP280_CalAvgValue(uint8_t *pIndex, int32_t *pAvgBuffer, int32_t InVal, int32_t *pOutVal)
{uint8_t i;static uint8_t status = 0;*(pAvgBuffer + ((*pIndex) ++)) = InVal;*pIndex %= BMP280_AVG_TIMES;if(status<=24) //skip average computation before getting pre-defined data times (24 times){*pOutVal = InVal;status++;}else //compute average value{*pOutVal = 0;for(i = 0; i < BMP280_AVG_TIMES; i ++){*pOutVal += *(pAvgBuffer + i);}*pOutVal /= BMP280_AVG_TIMES;}
}void BMP280_CalculateAbsoluteAltitude(int32_t *pAltitude, int32_t PressureVal)
{*pAltitude = 4433000 * (1 - pow((PressureVal / (float)gs32Pressure0), 0.1903));
}void BMP280_CalTemperatureAndPressureAndAltitude(int32_t *temperature, int32_t *pressure, int32_t *Altitude)
{double CurPressure, CurTemperature;int32_t CurAltitude;static BMP280_AvgTypeDef BMP280_Filter[3];BMP280_Get_Temperature_And_Pressure(&CurTemperature, &CurPressure);BMP280_CalAvgValue(&BMP280_Filter[0].Index, BMP280_Filter[0].AvgBuffer, (int32_t)(CurPressure), pressure);BMP280_CalculateAbsoluteAltitude(&CurAltitude, (*pressure));BMP280_CalAvgValue(&BMP280_Filter[1].Index, BMP280_Filter[1].AvgBuffer, CurAltitude, Altitude);BMP280_CalAvgValue(&BMP280_Filter[2].Index, BMP280_Filter[2].AvgBuffer, (int32_t)CurTemperature*10, temperature);(*Altitude) += ALTITUDE_OFFSET;return;
}void BMP280_Read_Calibration(void)
{uint8_t lsb, msb;/* read the temperature calibration parameters */lsb = BMP280_ReadReg(BMP280_DIG_T1_LSB_REG);msb = BMP280_ReadReg(BMP280_DIG_T1_MSB_REG);dig_T1 = msb << 8 | lsb;lsb = BMP280_ReadReg(BMP280_DIG_T2_LSB_REG);msb = BMP280_ReadReg(BMP280_DIG_T2_MSB_REG);dig_T2 = msb << 8 | lsb;lsb = BMP280_ReadReg(BMP280_DIG_T3_LSB_REG);msb = BMP280_ReadReg(BMP280_DIG_T3_MSB_REG);dig_T3 = msb << 8 | lsb;/* read the pressure calibration parameters */lsb = BMP280_ReadReg(BMP280_DIG_P1_LSB_REG);msb = BMP280_ReadReg(BMP280_DIG_P1_MSB_REG);dig_P1 = msb << 8 | lsb;lsb = BMP280_ReadReg(BMP280_DIG_P2_LSB_REG);msb = BMP280_ReadReg(BMP280_DIG_P2_MSB_REG);dig_P2 = msb << 8 | lsb;lsb = BMP280_ReadReg(BMP280_DIG_P3_LSB_REG);msb = BMP280_ReadReg(BMP280_DIG_P3_MSB_REG);dig_P3 = msb << 8 | lsb;lsb = BMP280_ReadReg(BMP280_DIG_P4_LSB_REG);msb = BMP280_ReadReg(BMP280_DIG_P4_MSB_REG);dig_P4 = msb << 8 | lsb;lsb = BMP280_ReadReg(BMP280_DIG_P5_LSB_REG);msb = BMP280_ReadReg(BMP280_DIG_P5_MSB_REG);dig_P5 = msb << 8 | lsb;lsb = BMP280_ReadReg(BMP280_DIG_P6_LSB_REG);msb = BMP280_ReadReg(BMP280_DIG_P6_MSB_REG);dig_P6 = msb << 8 | lsb;lsb = BMP280_ReadReg(BMP280_DIG_P7_LSB_REG);msb = BMP280_ReadReg(BMP280_DIG_P7_MSB_REG);dig_P7 = msb << 8 | lsb;lsb = BMP280_ReadReg(BMP280_DIG_P8_LSB_REG);msb = BMP280_ReadReg(BMP280_DIG_P8_MSB_REG);dig_P8 = msb << 8 | lsb;lsb = BMP280_ReadReg(BMP280_DIG_P9_LSB_REG);msb = BMP280_ReadReg(BMP280_DIG_P9_MSB_REG);dig_P9 = msb << 8 | lsb;}void BMP280_Init()
{uint8_t u8ChipID, u8CtrlMod, u8Status;u8ChipID = BMP280_ReadReg(BMP280_REGISTER_CHIPID);u8CtrlMod = BMP280_ReadReg(BMP280_REGISTER_CONTROL);u8Status = BMP280_ReadReg(BMP280_REGISTER_STATUS);if(u8ChipID == 0x58){if(USB_CONN_STATUS()){sprintf(console, "\r\nBMP280 initial successful : ChipID [0x%x] CtrlMod [0x%x] Status [0x%x] \r\n", u8ChipID,u8CtrlMod,u8Status);CDC_Transmit_FS((uint8_t*)console, strlen(console));}else{printf("\r\nBMP280 initial successful : ChipID [0x%x] CtrlMod [0x%x] Status [0x%x] \r\n", u8ChipID,u8CtrlMod,u8Status);}BMP280_WriteReg(BMP280_REGISTER_CONTROL, 0xFF); //ctrl_meas registerBMP280_WriteReg(BMP280_REGISTER_CONFIG, 0x0C);  //config registerBMP280_Read_Calibration();}else{if(USB_CONN_STATUS()){sprintf(console, "\r\nBMP280 initial failure : ChipID [0x%x] CtrlMod [0x%x] Status [0x%x] \r\n", u8ChipID,u8CtrlMod,u8Status);CDC_Transmit_FS((uint8_t*)console, strlen(console));}else{printf("\r\nBMP280 initial failure : ChipID [0x%x] CtrlMod [0x%x] Status [0x%x] \r\n", u8ChipID,u8CtrlMod,u8Status);}return BMP280_Init();}}

main.c文件的实现功能测试代码,注意这里把BMP280管脚SDO拉到了高电平,所以定义为#define BMP280_I2C_ADDR_SEL 1:

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_device.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "BMP280.h"
#include "usart.h"/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
__IO float usDelayBase;
void PY_usDelayTest(void)
{__IO uint32_t firstms, secondms;__IO uint32_t counter = 0;firstms = HAL_GetTick()+1;secondms = firstms+1;while(uwTick!=firstms) ;while(uwTick!=secondms) counter++;usDelayBase = ((float)counter)/1000;
}void PY_Delay_us_t(uint32_t Delay)
{__IO uint32_t delayReg;__IO uint32_t usNum = (uint32_t)(Delay*usDelayBase);delayReg = 0;while(delayReg!=usNum) delayReg++;
}void PY_usDelayOptimize(void)
{__IO uint32_t firstms, secondms;__IO float coe = 1.0;firstms = HAL_GetTick();PY_Delay_us_t(1000000) ;secondms = HAL_GetTick();coe = ((float)1000)/(secondms-firstms);usDelayBase = coe*usDelayBase;
}void PY_Delay_us(uint32_t Delay)
{__IO uint32_t delayReg;__IO uint32_t msNum = Delay/1000;__IO uint32_t usNum = (uint32_t)((Delay%1000)*usDelayBase);if(msNum>0) HAL_Delay(msNum);delayReg = 0;while(delayReg!=usNum) delayReg++;
}
/* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;/* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int32_t PressureVal = 0, TemperatureVal = 0, AltitudeVal = 0;
char mychar[100];
char console[128];
/*
*Convert float to string type
*Written by Pegasus Yu in 2022
*stra: string address as mychar from char mychar[];
*float: float input like 12.345
*flen: fraction length as 3 for 12.345
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
void py_f2s4printf(char * stra, float x, uint8_t flen)
{uint32_t base;int64_t dn;char mc[32];base = pow(10,flen);dn = x*base;sprintf(stra, "%d.", (int)(dn/base));dn = abs(dn);if(dn%base==0){for(uint8_t j=1;j<=flen;j++){stra = strcat(stra, "0");}return;}else{if(flen==1){sprintf(mc, "%d", (int)(dn%base));stra = strcat(stra, mc);return;}for(uint8_t j=1;j<flen;j++){if((dn%base)<pow(10,j)){for(uint8_t k=1;k<=(flen-j);k++){stra = strcat(stra, "0");}sprintf(mc, "%d", (int)(dn%base));stra = strcat(stra, mc);return;}}sprintf(mc, "%d", (int)(dn%base));stra = strcat(stra, mc);return;}
}
/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
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_USB_DEVICE_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */PY_usDelayTest();PY_usDelayOptimize();I2C_Init();BMP280_Init();PY_Delay_us_t(100000); //Waiting for the stability of BMP280 after initiation/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){BMP280_CalTemperatureAndPressureAndAltitude(&TemperatureVal, &PressureVal, &AltitudeVal);if(USB_CONN_STATUS()){sprintf(console, "\r\n\r\n--------------BMP280 TEST---------------");while( CDC_Transmit_FS((uint8_t*)console, strlen(console)) == USBD_BUSY ) PY_Delay_us_t(1);py_f2s4printf(mychar, (float)PressureVal/100, 2);sprintf(console, "\r\n Pressure: %s\r\n", mychar);while( CDC_Transmit_FS((uint8_t*)console, strlen(console)) == USBD_BUSY ) PY_Delay_us_t(1);py_f2s4printf(mychar, (float)AltitudeVal/100, 2);sprintf(console, "\r\n Altitude: %s\r\n", mychar);while( CDC_Transmit_FS((uint8_t*)console, strlen(console)) == USBD_BUSY ) PY_Delay_us_t(1);py_f2s4printf(mychar, (float)TemperatureVal/10, 1);sprintf(console, "\r\n Temperature: %s\r\n", mychar);while( CDC_Transmit_FS((uint8_t*)console, strlen(console)) == USBD_BUSY ) PY_Delay_us_t(1);}else{printf("\r\n\r\n-----------------------------------------------");py_f2s4printf(mychar, (float)PressureVal/100, 2);printf("\r\n Pressure: %s\r\n", mychar);py_f2s4printf(mychar, (float)AltitudeVal/100, 2);sprintf(console, "\r\n Altitude: %s\r\n", mychar);printf("\r\n Altitude: %s\r\n", mychar);py_f2s4printf(mychar, (float)TemperatureVal/10, 1);sprintf(console, "\r\n Temperature: %s\r\n", mychar);}PY_Delay_us_t(200000);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Configure the main internal regulator output voltage*/__HAL_RCC_PWR_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/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();}/** Initializes the CPU, AHB and APB buses clocks*/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_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}/*** @brief USART1 Initialization Function* @param None* @retval None*/
static void MX_USART1_UART_Init(void)
{/* USER CODE BEGIN USART1_Init 0 *//* USER CODE END USART1_Init 0 *//* USER CODE BEGIN USART1_Init 1 *//* USER CODE END USART1_Init 1 */huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN USART1_Init 2 *//* USER CODE END USART1_Init 2 */}/*** @brief GPIO Initialization Function* @param None* @retval None*/
static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOH_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12|GPIO_PIN_13, GPIO_PIN_SET);/*Configure GPIO pins : PB12 PB13 */GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

注意芯片内部已经配置选用了滤波功能,采用滤波功能后的输出速率不高,对于外部进行静态高度测量,可以再进行取多次平均的算法,如果是运动过程高度测量,则不必再采用平均算法。另外,可以给

测试输出

代码运行的测试输出:
在这里插入图片描述

工程代码下载

STM32F401CCU6配置读取BMP280工程下载

–End–

相关文章:

STM32配置读取BMP280气压传感器数据

STM32配置读取BMP280气压传感器数据 BMP280是在BMP180基础上增强的绝对气压传感器&#xff0c;在飞控领域的高度识别方面应用也比较多。 BMP280和BMP180的区别&#xff1a; 市面上也有一些模块&#xff1a; 这里介绍STM32芯片和BMP280的连接和数据读取。 电路连接 BMP28…...

【Linux】 基础IO——文件(中)

文章目录1. 文件描述符为什么从3开始使用&#xff1f;2. 文件描述符本质理解3. 如何理解Linux下的一切皆文件&#xff1f;4. FILE是什么&#xff0c;谁提供&#xff1f;和内核的struct有关系么&#xff1f;证明struct FILE结构体中存在文件描述符fd5. 重定向的本质输出重定向输…...

蓝桥杯刷题冲刺 | 倒计时13天

作者&#xff1a;指针不指南吗 专栏&#xff1a;蓝桥杯倒计时冲刺 &#x1f43e;马上就要蓝桥杯了&#xff0c;最后的这几天尤为重要&#xff0c;不可懈怠哦&#x1f43e; 文章目录1.母牛的故事2.魔板1.母牛的故事 题目 链接&#xff1a; [递归]母牛的故事 - C语言网 (dotcpp.c…...

MIPI D-PHYv2.5笔记(5) -- 不同的PHY配置方式

声明&#xff1a;作者是做嵌入式软件开发的&#xff0c;并非专业的硬件设计人员&#xff0c;笔记内容根据自己的经验和对协议的理解输出&#xff0c;肯定存在有些理解和翻译不到位的地方&#xff0c;有疑问请参考原始规范看 规范5.7章节列举了一些常见的PHY配置&#xff0c;但实…...

【周末闲谈】文心一言,模仿还是超越?

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️周末闲谈】 周末闲谈 ✨第一周 二进制VS三进制 文章目录周末闲谈前言一、背景环境二、文心一言&#xff1f;(_)?三、文心一言的优势&#xff1f;&#x1f617;&#x1f617;&#x1f617;四、文心一…...

《一“企”谈》 | 「佛山市政」:携手企企通,让采购业务数智化

近日&#xff0c;国家施工总承包壹级企业「佛山市市政建设工程有限公司」&#xff08;以下简称“佛山市政”&#xff09;正积极布局数字化建设工作&#xff0c;基于采购业务数智化&#xff0c;携手企企通打造了SaaS采购云平台。 01、岭南建筑强企 匠心铸造精品 …...

Spark运行架构

目录 1 运行架构 2 核心组件 2.1 Driver 2.2 Executor 2.3 Master & Worker 2.4 ApplicationMaster 3 核心概念 3.1 Executor 与 Core 3.2 并行度&#xff08; Parallelism&#xff09; 3.3 ​​​​​​​有向无环图&#xff08; DAG&#xff09; 4 提交流程 …...

基于卷积神经网络CNN的水果分类预测,卷积神经网络水果等级识别

目录 背影 卷积神经网络CNN的原理 卷积神经网络CNN的定义 卷积神经网络CNN的神经元 卷积神经网络CNN的激活函数 卷积神经网络CNN的传递函数 卷积神经网络CNN水果分类预测 基本结构 主要参数 MATALB代码 结果图 展望 背影 现在生活&#xff0c;为节能减排&#xff0c;减少电能…...

Spring Boot 框架总结

Spring Boot 框架总结 1. springboot的引言 Spring Boot是由Pivotal团队提供的全新框架&#xff0c;其设计目的是用来简化Spring应用的 初始搭建以及开发过程。该框架使用了特定的方式来进行配置&#xff0c;从而使开发人员不 再需要定义样板化的配置。通过这种方式&#xff0…...

【数据结构】第五站:带头双向循环链表

目录 一、链表的八种结构 二、带头双向循环链表的实现 1.链表的定义 2.链表的接口定义 3.接口的具体实现 三、带头双向循环链表的完整代码 四、顺序表和链表的区别 一、链表的八种结构 我们已经知道链表可以有以下三种分法 而这三种结构又可以排列组合&#xff0c;形成八…...

Springboot生成二维码

Springboot生成二维码整合 我们使用两种方式&#xff0c;去生成二维码&#xff0c;但是其实&#xff0c;二维码的生成基础&#xff0c;都是zxing包&#xff0c;这是Google开源的一个包&#xff0c;第一种是使用原始的zxing方式去实现&#xff0c;第二种是使用hutool来实现&…...

“独裁者”何小鹏,再造小鹏汽车

文丨智能相对论 作者丨沈浪 如果没有何小鹏&#xff0c;小鹏汽车将失去灵魂。 2014年&#xff0c;夏珩、何涛等人在广州组建小鹏汽车&#xff08;当时还叫“橙子汽车”&#xff09;&#xff0c;何小鹏还只是股权投资人。 夏珩、何涛原任职于广汽&#xff0c;负责新能源汽车…...

数据结构 | 泛型 | 擦除机制| 泛型的上界

目录 ​编辑 1.泛型 1.1Object类引出泛型概念 2.泛型语法 2.1泛型编写代码 3.泛型的机制 3.1擦除机制 4.泛型的上界 4.1泛型上界的语法 4.2泛型上界的使用 5.泛型方法 5.1泛型方法语法 5.2泛型方法的使用 1.泛型 一般的类和方法中&#xff0c;只能使用具体的代码…...

C++拷贝构造函数(复制构造函数)详解

拷贝和复制是一个意思&#xff0c;对应的英文单词都是copy。对于计算机来说&#xff0c;拷贝是指用一份原有的、已经存在的数据创建出一份新的数据&#xff0c;最终的结果是多了一份相同的数据。例如&#xff0c;将 Word 文档拷贝到U盘去复印店打印&#xff0c;将 D 盘的图片拷…...

python学习——多线程

python学习——多线程概念python中线程的开发线程的启动线程的退出和传参threading的属性和方法threading实例的属性和方法多线程daemon线程和non-demone线程daemon线程的应用场景线程的jointhreading.local类线程的延迟执行&#xff1a;Timer线程同步Event 事件Lock ——锁加锁…...

SAP 系统中过账码or记账码

SAP中过账码和记账码是指同一个事物。 在实际业务中&#xff0c;记账码就是只有“借”和“贷”&#xff0c; 而SAP中Posting Code肩负着更多的任务&#xff1a; 1&#xff09;界定科目类型&#xff0c; 2&#xff09;借贷方向&#xff0c; 3&#xff09;凭证输入时画面上的字…...

【FreeRTOS(一)】FreeRTOS新手入门——初识FreeRTOS

初识FreeRTOS一、实时操作系统概述1、概念2、RTOS的必要性3、RTOS与裸机的区别4、FreeRTOS的特点二、FreeRTOS的架构三、FreeRTOS的代码架构一、实时操作系统概述 1、概念 RTOS&#xff1a;根据各个任务的要求&#xff0c;进行资源&#xff08;包括存储器、外设等&#xff09…...

Python中 __init__的通俗解释是什么?

__init__是Python中的一个特殊方法&#xff0c;用于在创建对象时初始化对象的属性。通俗来讲&#xff0c;它就像是一个构造函数&#xff0c;当我们创建一个类的实例时&#xff0c;__init__方法会被自动调用&#xff0c;用于初始化对象的属性。 举个例子&#xff0c;如果我们定义…...

网友真实面试总结出的自动化测试面试题库

目录 常规问题 手工测试部 自动化测试 自动化测试面试题2&#xff1a;selenium篇 常规问题 1、如何快速深入的了解移动互联网领域的应用 &#xff08;答案&#xff1a;看http协议 restful api知识 json加1分&#xff09; 2、对xx应用自己会花多久可以在业务上从入门到精通&…...

2023 年最佳 C++ IDE

文章目录前言1. Visual Studio2. Code::Blocks3. CLion4. Eclipse CDT&#xff08;C/C 开发工具&#xff09;5. CodeLite6. Apache NetBeans7. Qt Creator8. Dev C9. C Builder10. Xcode11. GNAT Programming Studio12. Kite总结前言 要跟踪极佳 IDE&#xff08;集成开发环境&…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...