SPL06电容式压力传感器数据读取与处理(基于STM32)

        该例程使用的开发板为正点原子的精英板F103,相关资料请大家自行去正点原子论坛下载。首先来看一下SPL06的简介,SPL06的压强测量范围30kPa~110kPa,最大供电电压为3.6V,相对精度为6 Pa,绝对精度为100 Pa,温度测量误差为正负0.5℃(压强的大小与温度存在一定关系,温度的精准测量可以很好的提升压强的测量精度);其通信方式有两种方式,I2C和SPI(这里我们选用的是I2C通信),压强和温度输出位数为24位的有符号位信号。SPL06里面集成了FIFO(这里我们没有用到,有需要的自行查看芯片手册——歌尔公司的官方网址https://www.goertek.com/content/details20_879.html)。

 

        接下来介绍一下硬件连接图,如下图所示,这里VDD与VDDIO可以供3.3V的电压,GND与地连接,CSB在I2C通信模式下可以不接,其内部有上拉电阻(这里博主使用的是NC),SDA与SCK(图中没有标出上拉)分别进行上拉,上拉电阻范围为5kΩ~100kΩ,SDO为地址选取端,不接或者上拉从机地址为0x77(01110111),接地从机地址为0x76(01110110),C1,C2为旁路电容,取值为100nF。

        I2C协议的底层信号这里不详细介绍,我们只介绍I2C通信的主要数据流程(这里我们的从机地址为0x77),I2C写入从机寄存器的流程如下图所示:

        首先主机发出一个I2C通信开始信号,然后发送SPL06的从机地址与写的指令即0XEE(11101110),然后等待SPL06的应答信号->接收到应答信号之后->发送寄存器的对应地址->等待SPL06的应答信号->发送需要写入的数据->写入完成之后发送I2C停止信号。

        I2C读取从机寄存器数据的流程如下图所示。

         首先主机发出一个I2C通信开始信号,然后发送SPL06的从机地址与写的指令即0XEE(11101110),然后等待SPL06的应答信号->接收到应答信号之后->发送寄存器的对应地址->等待SPL06的应答信号->再次发送开始信号->发送SPL06的从机地址与读的指令即0XEF(11101111)->读取对应寄存器的数据->等待应答->发送停止信号。

        I2C的底层程序选用的是正点原子的I2C底层程序,有需要的可以去看正点原子的对应例程,其程序如下(myiic.c):

#include "myiic.h"
#include "delay.h"
 
//初始化I2C
void IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_15); 	//SET the Pins to high level
}
//产生I2C起始信号(即START信号)
void IIC_Start(void)
{
	SDA_OUT();   
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL=0;
}	  
//产生I2C停止信号(即STOP信号)
void IIC_Stop(void)
{
	SDA_OUT();
	IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;
	delay_us(4);							   	
}
//等待应答信号
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;	   
	return 0;  
} 
//产生ACK应答信号
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}
//不产生ACK应答信号	    
void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}					 				     
//I2C发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答		  
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL=0;
    for(t=0;t<8;t++)
    {              
			IIC_SDA=(txd&0x80)>>7;
			txd<<=1; 	  
			delay_us(2);
			IIC_SCL=1;
			delay_us(2); 
			IIC_SCL=0;	
			delay_us(2);
    }	 
} 	    
//读1个字节,ack=1时,发送ACK,ack=0时,发送nACK 
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();
    for(i=0;i<8;i++ )
	{
		IIC_SCL=0; 
		delay_us(2);
		IIC_SCL=1;
		receive<<=1;
		if(READ_SDA)receive++;   
		delay_us(1); 
  }					 
	if (!ack)
			IIC_NAck();
	else
			IIC_Ack();  
	return receive;
}

头文件的程序如下(myiic.h): 

#ifndef __MYIIC_H
#define __MYIIC_H
#include "sys.h"

//IO方向设置
 
#define SDA_IN()  {GPIOB->CRH&=0X0FFFFFFF;GPIOB->CRH|=(u32)8<<28;}
#define SDA_OUT() {GPIOB->CRH&=0X0FFFFFFF;GPIOB->CRH|=(u32)3<<28;}

//IO口操作函数	 
#define IIC_SCL    PBout(13) //SCL
#define IIC_SDA    PBout(15) //输出SDA	 
#define READ_SDA   PBin(15)  //输入SDA 

//I2C所有操作函数
void IIC_Init(void);                //初始化I2C的IO口				 
void IIC_Start(void);				//发送IIC开始信号
void IIC_Stop(void);	  			//发送IIC停止信号
void IIC_Send_Byte(u8 txd);			//I2C发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//I2C读取一个字节
u8 IIC_Wait_Ack(void); 				//I2C等待ACK信号
void IIC_Ack(void);					//I2C发送ACK信号
void IIC_NAck(void);				//I2C不发送ACK信号

void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);	  
#endif

        接下来我们给出SPL06的数据写入函数如下,addr为写入寄存器的地址,data为写入的相应数据。

void SPL06_Write_Byte(u8 addr,u8 data)
{
  IIC_Start();
	IIC_Send_Byte(SPL06_Write);
	IIC_Wait_Ack();
	IIC_Send_Byte(addr);
	IIC_Wait_Ack();
	IIC_Send_Byte(data);
	IIC_Wait_Ack();
	IIC_Stop();
}

         我们给出SPL06的数据读取函数如下,addr为写入寄存器的地址,函数返回的值为SPL06发送的数据。

u8 SPL06_Read_Byte(u8 addr)
{
	u8 SPL06_Data;
	
	IIC_Start();
	IIC_Send_Byte(SPL06_Write);
	IIC_Wait_Ack();
	IIC_Send_Byte(addr);
	IIC_Wait_Ack();

	IIC_Start();// start again
	IIC_Send_Byte(SPL06_Read);
	IIC_Wait_Ack();
	SPL06_Data = IIC_Read_Byte(0);
	IIC_Stop();
	return SPL06_Data;
}

        接下来我们需要配置相应的寄存器以初始化我们的SPL06,SPL06的寄存器图如下所示。

        寄存器0x00~0x05存储的为压强数据与温度数据,PRS_CFG(addr:0x06)为压强采集的采样速率与过采样速率配置,TMP_CFG(addr:0x07)为温度采集的采样速率与过采样速率配置,MEAS_CFG(addr:0x08)可以用来读取当前寄存器的工作状态以及采集模式的配置。CFG_REG(addr:0x09),用来配置中断以及压强数据与温度数据的位移。关于FIFO的寄存器配置则不需要关心,ID(0x0D),SPL06的ID应为0x10,十进制为16,这里图表里面是错误的。

        根据不同的测试条件,我们进行不同的配置,其配置例子如下表所示。

        SPL06初始化的例程如下所示,采集模式为后台采集模式,压强过采样率为128次。这里需要注意的是,当温度或者压强的过采样率>8,则需要在CFG_REG配置相应数据的移位。

u8 SPL06_Init(void)
{
	u8 SPL06_ID;
	SPL06_Write_Byte(RESET_Addr,0x89);//Reset
	delay_ms(100);
	SPL06_ID = SPL06_Read_Byte(ID_Addr);//Read the SPL06's ID
	SPL06_Write_Byte(MEAS_CFG_Addr,0x07);//Set Working mode and state of sensor
	SPL06_Write_Byte(PRS_CFG_Addr,0x27);//Set the PM-RATE and PM-PRC
	SPL06_Write_Byte(TMP_CFG_Addr,0xA0);//Set the TMPI-RATE and TMP-PRC
	SPL06_Write_Byte(CFG_REG_Addr,0x04);//Configuration of abort, measurement data shift and FIFO enable
	return SPL06_ID;
}

        配置完成之后,进行数据读取与处理,压强处理的流程如下图所示(Traw与Praw为从寄存器中读取到的二进制补码数据经过转换之后的数据(即原码)):

        温度处理的流程如下图所示:

        其中kT和kP为比例因素,需要根据温度或者压强的过采样率进行选取,如下表所示。

        温度的校准系数有2个,压强的校准系数有7个,其数据组合如下表所示(注意所有的系数都是有符号位的,读取的数据为2进制的补码,我们需要进行相应的处理将其转换为原码):

         这里给出SPL06的所有函数(SPL06.c):

#include "SPL06.h"

void SPL06_Write_Byte(u8 addr,u8 data)
{
  IIC_Start();
	IIC_Send_Byte(SPL06_Write);
	IIC_Wait_Ack();
	IIC_Send_Byte(addr);
	IIC_Wait_Ack();
	IIC_Send_Byte(data);
	IIC_Wait_Ack();
	IIC_Stop();
}

u8 SPL06_Read_Byte(u8 addr)
{
	u8 SPL06_Data;
	
	IIC_Start();
	IIC_Send_Byte(SPL06_Write);
	IIC_Wait_Ack();
	IIC_Send_Byte(addr);
	IIC_Wait_Ack();

	IIC_Start();// start again
	IIC_Send_Byte(SPL06_Read);
	IIC_Wait_Ack();
	SPL06_Data = IIC_Read_Byte(0);
	IIC_Stop();
	return SPL06_Data;
}
u8 SPL06_Init(void)
{
	u8 SPL06_ID;
	SPL06_Write_Byte(RESET_Addr,0x89);//Reset
	delay_ms(100);
	SPL06_ID = SPL06_Read_Byte(ID_Addr);//Read the SPL06's ID
	SPL06_Write_Byte(MEAS_CFG_Addr,0x07);//Set Working mode and state of sensor
	SPL06_Write_Byte(PRS_CFG_Addr,0x27);//Set the PM-RATE and PM-PRC
	SPL06_Write_Byte(TMP_CFG_Addr,0xA0);//Set the TMPI-RATE and TMP-PRC
	SPL06_Write_Byte(CFG_REG_Addr,0x04);//Configuration of abort, measurement data shift and FIFO enable
	return SPL06_ID;
}

float Temperature_conversion(u32 Temp_Data,float k)
{
	float Temperature;
	int Temp;
	if(Temp_Data&0x800000)
	{
		Temp = Temp_Data-Total_Number_24;
	}
	else
	{
		Temp = Temp_Data;
	}
	Temperature = Temp/k;
	return Temperature;
}

float Pressure_conversion(u32 Pressure_Data,float k)
{
	float Pressure;
	int Press;
	if(Pressure_Data&0x800000)
	{
		Press = Pressure_Data-Total_Number_24;
	}
	else
	{
		Press = Pressure_Data;
	}
	Pressure = Press/k;
	return Pressure;
}

float Scale_factor(u8 Config_k)
{
	float k;
	switch(Config_k)
	{
		case 0: k = k_SPS1;break;
		case 1: k = k_SPS2;break;
    case 2: k = k_SPS4;break;
		case 3: k = k_SPS8;break;
		case 4: k = k_SPS16;break;
		case 5: k = k_SPS32;break;
    case 6: k = k_SPS64;break;
    case 7:	k = k_SPS128;break;	 	
	}
	return k;
}

void Parameter_Reading(int *Pressure_Para,int *Temperature_Para)
{
	u8 Temp_Config0,Temp_Config1,Temp_Config2;
	u8 Press_Config0,Press_Config1,Press_Config2,Press_Config3,Press_Config4;
	u8 Press_Config5,Press_Config6,Press_Config7,Press_Config8,Press_Config9;
	u8 Press_Config10,Press_Config11,Press_Config12,Press_Config13,Press_Config14;	 
	//Temperature
	Temp_Config0 = SPL06_Read_Byte(Temp_c0_Addr);
	Temp_Config1 = SPL06_Read_Byte(Temp_c1_Addr);
	Temp_Config2 = SPL06_Read_Byte(Temp_c2_Addr);
	Temperature_Para[0] = (Temp_Config0<<4)+((Temp_Config1&0xF0)>>4);
	if(Temperature_Para[0]&0x0800) Temperature_Para[0] = Temperature_Para[0]-Total_Number_12;
	Temperature_Para[1] = ((Temp_Config1&0x0F)<<8)+Temp_Config2;
	if(Temperature_Para[1]&0x0800) Temperature_Para[1] = Temperature_Para[1]-Total_Number_12;
	//Pressure
	Press_Config0 = SPL06_Read_Byte(Press_c0_Addr);
	Press_Config1 = SPL06_Read_Byte(Press_c1_Addr);
	Press_Config2 = SPL06_Read_Byte(Press_c2_Addr);
	Press_Config3 = SPL06_Read_Byte(Press_c3_Addr);
	Press_Config4 = SPL06_Read_Byte(Press_c4_Addr);
	Press_Config5 = SPL06_Read_Byte(Press_c5_Addr);
	Press_Config6 = SPL06_Read_Byte(Press_c6_Addr);
	Press_Config7 = SPL06_Read_Byte(Press_c7_Addr);
	Press_Config8 = SPL06_Read_Byte(Press_c8_Addr);
	Press_Config9 = SPL06_Read_Byte(Press_c9_Addr);
	Press_Config10 = SPL06_Read_Byte(Press_c10_Addr);
	Press_Config11 = SPL06_Read_Byte(Press_c11_Addr);
	Press_Config12 = SPL06_Read_Byte(Press_c12_Addr);
	Press_Config13 = SPL06_Read_Byte(Press_c13_Addr);
	Press_Config14 = SPL06_Read_Byte(Press_c14_Addr);
	Pressure_Para[0] = (Press_Config0<<12)+(Press_Config1<<4)+((Press_Config2&0xF0)>>4);//c00
	if(Pressure_Para[0]&0x80000) Pressure_Para[0] = Pressure_Para[0] - Total_Number_20;//c00
	Pressure_Para[1] = ((Press_Config2&0x0F)<<16)+ (Press_Config3<<8)+ Press_Config4;//c10
	if(Pressure_Para[1]&0x80000) Pressure_Para[1] = Pressure_Para[1] - Total_Number_20;//c10
	Pressure_Para[2] = (Press_Config5<<8)+Press_Config6;//c01
	if(Pressure_Para[2]&0x8000) Pressure_Para[2] = Pressure_Para[2] - Total_Number_16;//c01
	Pressure_Para[3] = (Press_Config7<<8)+Press_Config8;//c11
	if(Pressure_Para[3]&0x8000) Pressure_Para[3] = Pressure_Para[3] - Total_Number_16;//c11
	Pressure_Para[4] = (Press_Config9<<8)+Press_Config10;//c20
	if(Pressure_Para[4]&0x8000) Pressure_Para[4] = Pressure_Para[4] - Total_Number_16;//c20
	Pressure_Para[5] = (Press_Config11<<8)+Press_Config12;//c21
	if(Pressure_Para[5]&0x8000) Pressure_Para[5] = Pressure_Para[5] - Total_Number_16;//c21
	Pressure_Para[6] = (Press_Config13<<8)+Press_Config14;//c30
	if(Pressure_Para[6]&0x8000) Pressure_Para[6] = Pressure_Para[6] - Total_Number_16;//c30
}
float Correcting_Pressure(int *Pressure_Para,float Pressure,float Temperature)
{
		float	Corr_Pressure;
	  Corr_Pressure = Pressure_Para[0]+ Pressure*(Pressure_Para[1]+Pressure*(Pressure_Para[4]+Pressure*Pressure_Para[6]))+Temperature*Pressure_Para[2]+Temperature*Pressure*(Pressure_Para[3]+Pressure*Pressure_Para[5]);
		return Corr_Pressure;
}

float Correcting_Temperature(int *Temperature_Para,float Temperature)
{	
	float Corr_Temperature;
	Corr_Temperature = Temperature_Para[0]*0.5+Temperature_Para[1]*Temperature;
	return Corr_Temperature;
}

 SPL06的头文件如下(SPL06.h):

#ifndef __SPL06_H
#define __SPL06_H
#include "myiic.h"
#include "sys.h"
#include "LCD.h"
#include "delay.h"
#include "stdio.h"

#define SPL06_Write 0XEE
#define SPL06_Read 0xEF

#define k_SPS1 524288.0
#define k_SPS2 1572864.0
#define k_SPS4 3670016.0
#define k_SPS8 7864320.0
#define k_SPS16 253952.0
#define k_SPS32 516096.0
#define k_SPS64 1040384.0
#define k_SPS128 2088960.0

#define PSR_B2_Addr 0x00
#define PSR_B1_Addr 0x01
#define PSR_B0_Addr 0x02
#define TMP_B2_Addr 0x03
#define TMP_B1_Addr 0x04
#define TMP_B0_Addr 0x05
#define PRS_CFG_Addr 0x06
#define TMP_CFG_Addr 0x07
#define MEAS_CFG_Addr 0x08
#define CFG_REG_Addr 0x09
#define RESET_Addr 0x0C
#define ID_Addr 0x0D

#define Temp_c0_Addr 0x10
#define Temp_c1_Addr  0x11
#define Temp_c2_Addr  0x12

#define Press_c0_Addr  0x13
#define Press_c1_Addr  0x14
#define Press_c2_Addr  0x15
#define Press_c3_Addr  0x16
#define Press_c4_Addr  0x17
#define Press_c5_Addr  0x18
#define Press_c6_Addr  0x19
#define Press_c7_Addr  0x1A
#define Press_c8_Addr  0x1B
#define Press_c9_Addr  0x1C
#define Press_c10_Addr  0x1D
#define Press_c11_Addr  0x1E
#define Press_c12_Addr  0x1F
#define Press_c13_Addr  0x20
#define Press_c14_Addr  0x21

#define Total_Number_24 16777216.0
#define Total_Number_20 1048576.0
#define Total_Number_16 65536.0
#define Total_Number_12 4096.0

u8 SPL06_Init(void);
u8 SPL06_Read_Byte(u8 addr);
void SPL06_Write_Byte(u8 addr,u8 data);
void Parameter_Reading(int *Pressure_Para,int *Temperature_Para);
float Temperature_conversion(u32 Temp_Data,float k);
float Pressure_conversion(u32 Pressure_Data,float k);
float Scale_factor(u8 Config_k);
float Correcting_Pressure(int *Pressure_Para,float Pressure,float Temperature);
float Correcting_Temperature(int *Temperature_Para,float Temperature);

#endif

        主函数如下,其中关于LCD相关显示的函数,是使用的正点原子的LCD的驱动函数,这里不给出,有需要的请自行去正点原子的论坛进行下载 :

#include "delay.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"
#include "myiic.h"
#include "SPL06.h"
#include "math.h"

#define Average_Times 4
#define Standard_atmospheric_pressure 101325.0
#define Offest_Pressure 0
 int main(void)
 {	 
	u8 t=0;
	u8 i;
	u8 Config,Config_Press,Config_Temp;
	u8 Pressure_MSB,Pressure_CSB,Pressure_LSB;
	u8 Temp_MSB,Temp_CSB,Temp_LSB;
	u8 lcd_id[12];			
	u8 SPL06_ID;
	u32 Altitude_Temp,Alti_temp;
	u32 Temperature,Temperature_Temp,Temp_temp;
	u32 Pressure,Pressure_Temp,Pres_temp;
	int Pressure_Para[7],Temperature_Para[2];
	float k_Press,k_Temp;
	float Actual_Temperature,Actual_Pressure,Actual_Altitude;
	float Correcting_Temp,Correcting_Press;
	//Delay initialization	  
	delay_init();	    	 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	
	//Usart->115200
	uart_init(115200);	 	
	//IIC initialization
	IIC_Init();
	//LCD initialization
	LCD_Init();
	LCD_Clear(WHITE); 
	sprintf((char*)lcd_id,"LCD ID:%04X",lcddev.id);
	//show initialization
    POINT_COLOR=BLUE;	 
	LCD_ShowString(30,20,240,24,16,"Pressure Measurement");
	POINT_COLOR=RED;
    LCD_ShowString(30,44,240,24,12,"Device ID:");
	LCD_ShowString(30,56,240,24,12,"Mode:Temperature and Pressure");	
	LCD_ShowString(30,68,240,24,16,"Pressure:");
	LCD_ShowString(30,84,240,24,12,"Temperature:");
	LCD_ShowString(30,96,240,24,12,"Altitude:");
	LCD_ShowString(30,108,240,24,12,"Coefficients Status:");
	LCD_ShowString(30,120,240,24,12,"Sensor Status:");
	LCD_ShowString(30,132,240,24,12,"Number of Reads:");
	//SPL06_Init
	SPL06_ID = SPL06_Init();
	Parameter_Reading(Pressure_Para,Temperature_Para);
	Config_Press = SPL06_Read_Byte(PRS_CFG_Addr);
	Config_Temp = SPL06_Read_Byte(TMP_CFG_Addr);
	k_Press = Scale_factor((Config_Press)&0x0F);
	k_Temp = Scale_factor((Config_Temp)&0x07);
	LCD_ShowxNum(91,44,SPL06_ID,3,12,0);
	//Judge the relevant state of the sensor
	Config = SPL06_Read_Byte(MEAS_CFG_Addr);
	if((Config>>7)&0x01) LCD_ShowString(151,108,240,24,12,"Available.");
	else LCD_ShowString(151,108,240,24,12,"Not available");
	if((Config>>6)&0x01) LCD_ShowString(115,120,240,24,12,"Successful.");
	else LCD_ShowString(115,120,240,24,12,"Failed.");
  while(1) 
	{	
		Pressure = 0;
		Temperature = 0;
		for (i=0;i<Average_Times;i++)
		{
			Config = SPL06_Read_Byte(MEAS_CFG_Addr);
			while(1)
			{
				if(((Config>>5)&0x01) && ((Config>>4)&0x01) && i == 0)
				{
					Pressure_MSB = SPL06_Read_Byte(PSR_B2_Addr);
					Pressure_CSB = SPL06_Read_Byte(PSR_B1_Addr);
					Pressure_LSB = SPL06_Read_Byte(PSR_B0_Addr);
					Temp_MSB = SPL06_Read_Byte(TMP_B2_Addr);
					Temp_CSB = SPL06_Read_Byte(TMP_B1_Addr);
					Temp_LSB = SPL06_Read_Byte(TMP_B0_Addr);
					Pressure = (Pressure_MSB<<16)+(Pressure_CSB<<8)+Pressure_LSB;
					Temperature = (Temp_MSB<<16)+(Temp_CSB<<8)+Temp_LSB;
                    LCD_ShowString(30,144,240,24,12,"                  ");					
					LCD_ShowString(30,144,240,24,12,"Data is ready!");
					break;
				}
				else if(((Config>>5)&0x01) && ((Config>>4)&0x01) && i > 0)
				{
					Pressure_MSB = SPL06_Read_Byte(PSR_B2_Addr);
					Pressure_CSB = SPL06_Read_Byte(PSR_B1_Addr);
					Pressure_LSB = SPL06_Read_Byte(PSR_B0_Addr);
					Temp_MSB = SPL06_Read_Byte(TMP_B2_Addr);
					Temp_CSB = SPL06_Read_Byte(TMP_B1_Addr);
					Temp_LSB = SPL06_Read_Byte(TMP_B0_Addr);
					Pressure = Pressure + (Pressure_MSB<<16)+(Pressure_CSB<<8)+Pressure_LSB;
					Temperature = Temperature + (Temp_MSB<<16)+(Temp_CSB<<8)+Temp_LSB;
					LCD_ShowString(30,144,240,24,12,"                  ");
					LCD_ShowString(30,144,240,24,12,"Data is ready!");
					break;				
				}
				else
				{
					LCD_ShowString(30,144,240,24,12,"                  ");
					LCD_ShowString(30,144,240,24,12,"Data is not ready!");
					break;
				}
			}
			delay_ms(250);
	  }
		Pressure = Pressure/Average_Times;
		Temperature = Temperature/Average_Times;
		Actual_Temperature = Temperature_conversion(Temperature,k_Temp);
		Actual_Pressure = Pressure_conversion(Pressure,k_Press);
		Correcting_Press = Correcting_Pressure(Pressure_Para,Actual_Pressure,Actual_Temperature)+Offest_Pressure;
		Correcting_Temp = Correcting_Temperature(Temperature_Para,Actual_Temperature);	
		Actual_Altitude = 44330*(1-pow(Correcting_Press/Standard_atmospheric_pressure,1.0/5.255));	
		//show the Correcting Pressure
		Pressure_Temp = Correcting_Press*10;
		Pres_temp = Pressure_Temp/10;
		LCD_ShowxNum(102,68,Pres_temp,7,16,0);
		LCD_ShowString(159,68,240,24,16,".");
		Pres_temp = Pressure_Temp%10;
		LCD_ShowxNum(168,68,Pres_temp,1,16,0);
		LCD_ShowString(177,68,240,24,16,"Pa");
		//show the Correcting Temperature
		Temperature_Temp = Correcting_Temp*10;
		Temp_temp = Temperature_Temp/10;
		LCD_ShowxNum(103,84,Temp_temp,4,12,0);
		LCD_ShowString(128,84,240,24,12,".");
		Temp_temp = Temperature_Temp%10;
		LCD_ShowxNum(135,84,Temp_temp,1,12,0);
		LCD_ShowString(143,84,240,24,12,"Centigrade");
		//show the altitude
		Altitude_Temp = Actual_Altitude*10;
		Alti_temp = Altitude_Temp/10;
		LCD_ShowxNum(85,96,Alti_temp,4,12,0);
		LCD_ShowString(110,96,240,24,12,".");
		Alti_temp = Altitude_Temp%10;
		LCD_ShowxNum(117,96,Alti_temp,1,12,0);
		LCD_ShowString(130,96,240,24,12,"m");
		// count the reading times
		t++;
		LCD_ShowxNum(127,132,t,3,12,0);				
 } 
}

使用SPL06进行压强测试,测试结果如下表所示:

压强测试结果
标准压强(Pa)测试结果(Pa)
110000110035
100000100029
9000090031
7000070015
5000050006
3000030087

  • 21
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
STM32的声音检测传感器输出的是模拟电压值,我们需要将其转化为分贝值来表示声音的强度。下面是将STM32的声音检测传感器的测量值转化为分贝的方法: 1. 首先,将声音检测传感器的输出电压转化为声压值,通常使用下面的公进行计算: 声压值 = 20 * log10(Vout / Vref) 其中,Vout表示传感器输出的电压值,Vref表示参考电压值(例如,3.3V或5V)。 2. 然后,将声压值转化为分贝值,使用下面的公: 分贝值 = 20 * log10(声压值 / 基准声压值) 其中,基准声压值通常为20微帕斯卡(20μPa),是人类听觉的参考声压值。 下面是一个示例代码,将STM32的声音检测传感器的输出电压转化为分贝值: ``` const float Vref = 3.3; //参考电压值 const float Vpp = 0.5; //声音传感器输出的最大峰-峰电压值 const float sensitivity = 0.5; //传感器灵敏度(mv/dB) void setup() { Analog_init(); //初始化模拟输入引脚 Serial_init(); //初始化串口通信 } void loop() { float Vout = Analog_read(0) * Vref / 4095; //将模拟电压值转化为实际电压值 float VP = Vout / 2; //计算声音的幅值 float SPL = 20 * log10(VP / 0.00002); //计算声压级 float dB = SPL + sensitivity; //计算分贝值 Serial_print("Vout = "); Serial_print_float(Vout); Serial_print("V, dB = "); Serial_print_float(dB); Serial_println(""); delay(100); //延时100毫秒 } ``` 其中,Analog_init()和Analog_read()函数用于初始化模拟输入引脚和读取模拟电压值,Serial_init()、Serial_print()和Serial_print_float()函数用于初始化串口通信和输出结果。 希望这个回答能够解决您的问题。如果您还有其他问题,欢迎随时提出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值