STM32+MS5611测气压温度例程详解,测试无误

2023-11-08

硬件平台:STM32F10X + MS5611 + JLink 

软件平台:Keil 4 

一、基础知识

首先,MS5611是什么?

MS5611气压传感器是集合SPI和I²C(高达20 MHz)总线接口的高分辨率气压传感器,分辨率可达到10cm。内部有一个高线性度的压力传感器和一个超低功耗的24位AD。

MS5611主要用于智能手机、海拔高度测量和导航辅助,做四轴的朋友一般都了解。

其次,对于飞行器的姿态控制,我们使用GY-86 10DOF 的模块,里面带有MS5611 + MPU6050 + HMC5883,通过IIC协议读取数据进行操作。MS5611挂在MPU5060的从I2C接口上。MS5611的I2C地址为0b111011Cx,其中C比特位由CSB引脚决定,为CSB引脚的补码值(取反)。GY-86上 MS5611的CSB引脚接地,所以CSB引脚值为0,8位I2C地址为0b1110111x(0xEE),7位I2C地址为 0b1110111(0x77)。

 

这里,0b表示二进制,0x表示十六进制,数字前加0表示八进制。例如:

  '\077' //是8进制表示' ',0可以省略,因为C,C++规定不允许使用斜杠加10进制数来表示字符;

  '\0x3F' //是16进制表示。这些都是C语言中的基础,不懂得请自行百度。

二、运行结果

三、相应模块

程序涉及的模块有:

RCC:复位及时钟控制模块,用于初始化STM32 USART外设时钟及IO口复用时钟;

IIC:模拟IIC 协议,好多人都说STM32的硬件IIC模块用不了,主要是因为STM32 的硬件 IIC 模块有个天生的 BUG,就是不能被中断,也就是IIC要处于中断的最高级,ST在自己后来的 DataSheet 中已经证实了这一点。

Delay:利用系统时钟SysTick,也号称“滴答”,写的延时模块;

USART:串口模块;

MS5611:MS5611模块配置。

四:代码

RCC

  #include "Rcc.h"
  
  void RCC_Init(void)
  {	 
  	 ErrorStatus HSEStartUpStatus;
  	//定义枚举类型错误状态变量	
  	 
  	 RCC_DeInit();//复位系统时钟设置
  		
  	 RCC_HSEConfig(RCC_HSE_ON);
  	 //打开外部高速时钟晶振,使能HSE
  	/*RCC_HSE_ON  开
  	 _off 关  _bypass hse晶振被外部时钟旁路*/	
  	 
  	HSEStartUpStatus = RCC_WaitForHSEStartUp();
  	/*RCC_WaitForHSEStartUp()返回一个ErrorStatus枚举值,
  	success好,error未好*/
  	
  	 if(HSEStartUpStatus == SUCCESS)//HES就绪
  	 {		 
  		 RCC_HCLKConfig(RCC_SYSCLK_Div1);
  		 //AHB时钟(HCLK)=系统时钟		
  
  			RCC_PCLK1Config(RCC_HCLK_Div2);
  		 //设置低速AHB时钟(APB1)为HCLK的2分频			 
  		 
  		 RCC_PCLK2Config(RCC_HCLK_Div1);
  		 //设置高速AHB时钟(APB2)=HCLK时钟			 	
  		 
  		 FLASH_SetLatency(FLASH_Latency_2);
  		 //设置FLASH延时周期数为2
  		 
  		 //使能领取指缓存
  		 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
  		 
  		 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
  		 //设置PLL时钟源及倍频系数,为HSE的9倍频 8MHz * 9 = 72MHz
  		 /*void RCC_PLLConfig(u32 RCC_PLLSource, u32 RCC_PLLMul)
  		 RCC_PLLSource_HSI_Div2   pll输入时钟=hsi/2;
  		 RCC_PLLSource_HSE_Div1   pll输入时钟 =hse
  		 RCC_PLLSource_HSE_Div2   pll输入时钟=hse/2
  		 
  		 RCC_PLLMul_2  ------_16       pll输入时钟*2---16
  		 pll输出时钟不得超过72MHZ*/	 
  		 
  		 RCC_PLLCmd(ENABLE);
  		 //ENABLE  / DISABLE
  		 
  		 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);//等待PLL输出稳定
  		 /*FlagStatus RCC_GetFlagStatus(u8 RCC_FLAG)  检查指定RCC标志位
  		 返回SET OR RESET
  		 RCC_FLAG_HSIRDY  HSI晶振就绪
  		 RCC_FLAG_HSERDY
  		 RCC_FLAG_PLLRDY
  		 RCC_FLAG_LSERDY 
  		 RCC_FLAG_LSIRDY.......*/		 
  		 
  		 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
  		 //设置PLL为系统时钟源
  		 /*void RCC_SYSCLKConfig(u32 RCC_SYSCLKSource)  设置系统时钟
  		 RCC_SYSCLKSource_HSI 
  		 RCC_SYSCLKSource_HSE 
  		 RCC_SYSCLKSource_PLLCLK  选HSI  HSE PLL 作为系统时钟*/ 		 
  		 
  		 while(RCC_GetSYSCLKSource() != 0x08);
  		 //判断PLL是否是系统时钟
  		 /*u8 RCC_GetSYSCLKSource(void)  返回用作系统时钟的时钟源
  		 0x00:HSI   0x04:HSE 0x08:PLL */
  	 }	 
  	 
  	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | 
  													RCC_APB2Periph_AFIO |
  													RCC_APB2Periph_GPIOB , ENABLE);
  	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
  	 //U2  U3 时钟在APB1
  	 //打开GPIO时钟,复用功能,串口1的时钟	             											 
  
  	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟	
  	//好奇怪,是因为官方的库函数更新?
  	//不是说F10X系列只有一个CAN,而F4有CAN1  CAN2 吗?
  	//怎么他的系统配置文件里面是can1?????
  	 
  	 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能
  	 
  	 /*void RCC_APB2PeriphClockCmd(u32 RCC_APB2Periph, FunctionalState NewState) 
  		enable 或 disable apb2 外设时钟
  	 RCC_APB2Periph_AFIO  功能复用IO 时钟
  	 RCC_APB2Periph_GPIOA/B/C/D/E   GPIOA/B/C/D/E 时钟
  	 RCC_APB2Periph_ADC1/ADC2			ADC1/2 时钟
  	 RCC_APB2Periph_TIM1 
  	 RCC_APB2Periph_SPI1
  	 RCC_APB2Periph_USART1 
  	 RCC_APB2Periph_ALL			全部APB2外设时钟*/
  }
 

IIC

  #include "myIIC.h"
  
  
  unsigned char I2C_ReadByte(unsigned char DeviceAddr,unsigned char address);  //从24c02的地址address中读取一个字节数据
  void I2C_WriteByte(unsigned char DeviceAddr,unsigned char address,unsigned char info);
  void I2C_NoAddr_WriteByte(unsigned char DeviceAddr,unsigned char info);
  void I2C_Read_MultiBytes(unsigned char DeviceAddr,unsigned char address,unsigned char BytesNum,unsigned char * OutDate );
  uint16_t I2C_Read_2Bytes(unsigned char DeviceAddr,unsigned char address);
  uint32_t I2C_Read_3Bytes(unsigned char DeviceAddr,unsigned char address);
  void delay_nop(void);
  void delay2(unsigned int x);
  void iic_start(void);
  void iic_stop(void);
  void iic_writex(unsigned char j);
  unsigned char iic_readx(void);
  void iic_check_ACK(void);
  void iic_SDA_Set_Dir(unsigned char io_set);
  void I2C_GPIO_Configuration(void);
  void delay2(unsigned int x)
  {
     unsigned int i;
     for(i=0;i<x;i++);
  }
  
  void delay_nop(void)
  {
    unsigned int i=10; //i=10延时1.5us//这里可以优化速度 ,经测试最低到5还能写入
     while(i--);
  }
  void iic_start(void)
  {
     //SDA=1;
     GPIO_SetBits(GPIOB,SDA);
     delay_nop();
     //SCL=1;
     GPIO_SetBits(GPIOB,SCL);
     delay_nop();
     //SDA=0;
      GPIO_ResetBits(GPIOB, SDA);
     delay_nop();
     //SCL=0;
     GPIO_ResetBits(GPIOB, SCL);
     delay_nop();
  }
  void iic_stop(void)
  {
     //SDA=0;
     GPIO_ResetBits(GPIOB, SDA);
     delay_nop();
     //SCL=1;
     GPIO_SetBits(GPIOB,SCL);
     delay_nop();
     //SDA=1;
     GPIO_SetBits(GPIOB,SDA);
     delay_nop();
  }
  void iic_writex(unsigned char j)
  
  {
     unsigned char i,temp,temp1;
  
     temp=j;
    //iic_SDA_Set_Dir(0);
     for (i=0;i<8;i++)
     {
        temp1=temp & 0x80;
        temp=temp<<1;
       
        //SCL=0;
     GPIO_ResetBits(GPIOB, SCL);
        delay_nop();
  
     //SDA=CY;
    if(temp1==0x80)
     {GPIO_SetBits(GPIOB, SDA);}
    else
     {GPIO_ResetBits(GPIOB, SDA);}
       
  
        delay_nop();
       // SCL=1;
    GPIO_SetBits(GPIOB,SCL);
        delay_nop();
     }
   //iic_SDA_Set_Dir(0);
     //SCL=0;
      GPIO_ResetBits(GPIOB, SCL);
     delay_nop();
     //SDA=1;
     GPIO_SetBits(GPIOB,SDA);
     delay_nop();
  
  }
  unsigned char iic_readx(void)
  {
     unsigned char i,j,k=0;
  
     //SCL=0;
      GPIO_ResetBits(GPIOB, SCL);
      delay_nop(); 
   //SDA=1;
   GPIO_SetBits(GPIOB,SDA);
  
   iic_SDA_Set_Dir(1);
     for (i=0;i<8;i++)
     {
        delay_nop();
        //SCL=1;
     GPIO_SetBits(GPIOB,SCL);
        delay_nop();
        //if (SDA==1) j=1;
    if( GPIO_ReadInputDataBit(GPIOB,SDA)==1 ) 
     {j=1;}
        else 
     {j=0;}
        k=(k<<1)|j;
        //SCL=0;
      GPIO_ResetBits(GPIOB, SCL);
     }
      iic_SDA_Set_Dir(0);
     delay_nop();
     return(k);
  
  }
  void iic_check_ACK(void)//检测从机应答信号
  {
     unsigned int i=0;
        iic_SDA_Set_Dir(1);
     //SCL=1;
     GPIO_SetBits(GPIOB,SCL);
     delay_nop();
     while ((GPIO_ReadInputDataBit(GPIOB,SDA)==1)&&(i<5000))i++;
     //SCL=0;
      GPIO_ResetBits(GPIOB, SCL);
     delay_nop();
     iic_SDA_Set_Dir(0);
  
  }
  void I2C_Ack(void)
  {	
  	GPIO_ResetBits(GPIOB,SCL);
    delay_nop();
  	GPIO_ResetBits(GPIOB,SDA);
  	delay_nop();
  	GPIO_SetBits(GPIOB,SCL);
  	delay_nop();
  	GPIO_ResetBits(GPIOB,SCL);
  	delay_nop();
  } 
  void I2C_NoAck(void)
  {	
  	GPIO_ResetBits(GPIOB,SCL);
  	delay_nop();
  	GPIO_SetBits(GPIOB,SDA);
  	delay_nop();
  	GPIO_SetBits(GPIOB,SCL);
  	delay_nop();
  	GPIO_ResetBits(GPIOB,SCL);
  	delay_nop();
  } 
  unsigned char I2C_ReadByte(unsigned char DeviceAddr,unsigned char address)
  {
     unsigned char i;
     iic_start();
     iic_writex(DeviceAddr);
     iic_check_ACK();
     iic_writex(address);
     iic_check_ACK();
     iic_start();
     iic_writex(DeviceAddr+1);
     iic_check_ACK();
     i=iic_readx();
     iic_stop();
     //delay2(10);
     delay2(50);
     return(i);
  }
  void I2C_WriteByte(unsigned char DeviceAddr,unsigned char address,unsigned char info)
  {
  
     iic_start();
     iic_writex(DeviceAddr);
     iic_check_ACK();
     iic_writex(address);
     iic_check_ACK();
     iic_writex(info);
     iic_check_ACK();
     iic_stop();
     //delay2(50);
     delay2(250);
  
  }
  void I2C_NoAddr_WriteByte(unsigned char DeviceAddr,unsigned char info)
  {
  
     iic_start();
     iic_writex(DeviceAddr);
     iic_check_ACK();
     iic_writex(info);
     iic_check_ACK();
     iic_stop();
     //delay2(50);
     delay2(250);
  
  }
  void I2C_Read_MultiBytes(unsigned char DeviceAddr,unsigned char address,unsigned char BytesNum,unsigned char * OutDate )
  {
     unsigned char i;
     iic_start();
     iic_writex(DeviceAddr);
     iic_check_ACK();
     iic_writex(address);
     iic_check_ACK();
     iic_start();
     iic_writex(DeviceAddr+1);
     iic_check_ACK();
  	 for(i=0;i<BytesNum;i++)
  	{
     OutDate[i]=iic_readx();
  		if(i+1<BytesNum)  I2C_Ack();else	I2C_NoAck();//最后一个字节无需应答
  	 }
     iic_stop();
     delay2(250);
  }
  uint16_t I2C_Read_2Bytes(unsigned char DeviceAddr,unsigned char address)
  {
     unsigned char i,data_temp1,data_temp2;
  	 uint16_t data16;
     iic_start();
     iic_writex(DeviceAddr);
     iic_check_ACK();
     iic_writex(address);
     iic_check_ACK();
     iic_start();
     iic_writex(DeviceAddr+1);
     iic_check_ACK();	 
     data_temp1=iic_readx();
  	 I2C_Ack();
     data_temp2=iic_readx();	
  	 I2C_NoAck();//最后一个字节无需应答
     iic_stop();
     //delay2(10);
     delay2(250);
  	data16=(data_temp1<<8)|data_temp2;
  	return data16;}
  uint32_t I2C_Read_3Bytes(unsigned char DeviceAddr,unsigned char address)
  {
     unsigned char i,data_temp1,data_temp2,data_temp3;
  	 uint32_t data32;
     iic_start();
     iic_writex(DeviceAddr);
     iic_check_ACK();
     iic_writex(address);
     iic_check_ACK();
     iic_start();
     iic_writex(DeviceAddr+1);
     iic_check_ACK();
  	 
     data_temp1=iic_readx();
  	 I2C_Ack();
     data_temp2=iic_readx();	
  	 I2C_Ack();
     data_temp3=iic_readx();
  	 I2C_NoAck();//最后一个字节无需应答
     iic_stop();
     //delay2(10);
     delay2(250);
  	 data32=data_temp1*65535+data_temp2*256+data_temp3;
  	 return data32;}
  void I2C_GPIO_Configuration(void)
  {
    GPIO_InitTypeDef  GPIO_InitStructure;
     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE); 
    
    GPIO_InitStructure.GPIO_Pin = SCL;          //24C02 SCL
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
  
    GPIO_InitStructure.GPIO_Pin = SDA;          //24C02 SDA 作为输出
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
  }
  void iic_SDA_Set_Dir(unsigned char io_set) //SDA引脚输入输出设置
  {
  	GPIO_InitTypeDef  GPIO_InitStructure;
      if(io_set==0)
    {
    GPIO_InitStructure.GPIO_Pin = SDA;          //24C02 SDA 作为输出
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure); 
    }
   else if(io_set==1)
    {
    GPIO_InitStructure.GPIO_Pin = SDA;          //24C02 SDA 作为输入
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  //上拉输入
    GPIO_Init(GPIOB, &GPIO_InitStructure); 
    }
   else
    {;}
  }

 


DELAY

  #include "delay.h"
  
  static u8  fac_us=0;							//us延时倍乘数			   
  static u16 fac_ms=0;							//ms延时倍乘数,在ucos下,代表每个节拍的ms数
  	
  	   
  //初始化延迟函数
  //SYSTICK的时钟固定为HCLK时钟的1/8
  //SYSCLK:系统时钟
  void delay_init()
  {
  	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	//选择外部时钟  HCLK/8
  	fac_us=SystemCoreClock/8000000;				//为系统时钟的1/8 
  
  	fac_ms=(u16)fac_us*1000;					//非OS下,代表每个ms需要的systick时钟数 
  }								    
  
  //延时nus
  //nus为要延时的us数.		    								   
  void delay_us(u32 nus)
  {		
  	u32 temp;	    	 
  	SysTick->LOAD=nus*fac_us; 					//时间加载	  		 
  	SysTick->VAL=0x00;        					//清空计数器
  	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;	//开始倒数	  
  	do
  	{
  		temp=SysTick->CTRL;
  	}while((temp&0x01)&&!(temp&(1<<16)));		//等待时间到达   
  	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//关闭计数器
  	SysTick->VAL =0X00;      					 //清空计数器	 
  }
  //延时nms
  //注意nms的范围
  //SysTick->LOAD为24位寄存器,所以,最大延时为:
  //nms<=0xffffff*8*1000/SYSCLK
  //SYSCLK单位为Hz,nms单位为ms
  //对72M条件下,nms<=1864 
  void delay_ms(u16 nms)
  {	 		  	  
  	u32 temp;		   
  	SysTick->LOAD=(u32)nms*fac_ms;				//时间加载(SysTick->LOAD为24bit)
  	SysTick->VAL =0x00;							//清空计数器
  	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;	//开始倒数  
  	do
  	{
  		temp=SysTick->CTRL;
  	}while((temp&0x01)&&!(temp&(1<<16)));		//等待时间到达   
  	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//关闭计数器
  	SysTick->VAL =0X00;       					//清空计数器	  	    
} 

 

 


MS5611

  #include "MS5611.h"
  
  
  /*宏定义------------------------------------------------------------------*/
  //定义器件在IIC总线中的从地址,根据CSB引脚不同修改
  //#define MS561101BA_ADDR  0xec   //CBR=1 0x76 I2C address when CSB is connected to HIGH (VCC)
  #define MS561101BA_ADDR   0xee   //CBR=0 0x77 I2C address when CSB is connected to LOW (GND)
  
  // 定义MS561101BA内部地址
  // registers of the device
  #define MS561101BA_D1 0x40
  #define MS561101BA_D2 0x50
  #define MS561101BA_RESET 0x1E
  
  // D1 and D2 result size (bytes)
  #define MS561101BA_D1D2_SIZE 3
  
  // OSR (Over Sampling Ratio) constants
  #define MS561101BA_OSR_256 0x00
  #define MS561101BA_OSR_512 0x02
  #define MS561101BA_OSR_1024 0x04
  #define MS561101BA_OSR_2048 0x06
  #define MS561101BA_OSR_4096 0x08
  //#define  MS561101BA_D1_OSR_256 0x40 
  //#define  MS561101BA_D1_OSR_512 0x42 
  //#define  MS561101BA_D1_OSR_1024 0x44 
  //#define  MS561101BA_D1_OSR_2048 0x46 
  #define  MS561101BA_D1_OSR_4096 0x48 
  
  //#define  MS561101BA_D2_OSR_256 0x50 
  //#define  MS561101BA_D2_OSR_512 0x52 
  //#define  MS561101BA_D2_OSR_1024 0x54 
  //#define  MS561101BA_D2_OSR_2048 0x56 
  #define  MS561101BA_D2_OSR_4096 0x58 
  
  #define MS561101BA_PROM_BASE_ADDR 0xA0 // by adding ints from 0 to 6 we can read all the prom configuration values. 
  // C1 will be at 0xA2 and all the subsequent are multiples of 2
  #define MS561101BA_PROM_REG_COUNT 6 // number of registers in the PROM
  #define MS561101BA_PROM_REG_SIZE 2 // size in bytes of a prom registry.
  
  
  /*变量声明----------------------------------------------------------------*/
  uint16_t Cal_C[7];  //用于存放PROM中的6组数据	
  uint32_t D1_Pres,D2_Temp; // 存放数字压力和温度
  float Pressure;				//温度补偿大气压
  float dT,Temperature,Temperature2;//实际和参考温度之间的差异,实际温度,中间值
  double OFF,SENS;  //实际温度抵消,实际温度灵敏度
  float Aux,OFF2,SENS2;  //温度校验值
  
  uint32_t ex_Pressure;			//串口读数转换值
  uint8_t  exchange_num[8];
  
  
  /*函数声明----------------------------------------------------------------*/
   void MS561101BA_Reset(void);
   void MS561101BA_readPROM(void);
   uint32_t MS561101BA_DO_CONVERSION(u8 command);
   void MS561101BA_GetTemperature(u8 OSR_Temp);
   void MS561101BA_GetPressure(u8 OSR_Pres);
   void MS561101BA_Init(void);
   void SampleANDExchange(void);
  /************************************************************   
  * 函数名:MS561101BA_Reset   
  * 描述 : 复位  
  * 输入  :无   
  * 输出  :无    
  */ 
  void MS561101BA_Reset(void)
  {
  		I2C_NoAddr_WriteByte(MS561101BA_ADDR,MS561101BA_RESET);
  }
  
  
  /************************************************************   
  * 函数名:MS561101BA_readPROM   
  * 描述 : 从PROM读取出厂校准数据
  * 输入  :无   
  * 输出  :无    
  */ 
  void MS561101BA_readPROM(void)
  {   uint16_t value=0;u8 temp1[2]={0};
  	  u8 i;
  	  for (i=0;i<=MS561101BA_PROM_REG_COUNT;i++) 
  	 {
        // I2C_Read_MultiBytes(MS561101BA_ADDR,MS561101BA_PROM_BASE_ADDR + (i * MS561101BA_PROM_REG_SIZE),2,temp1);
         
         //value=temp1[0]<<8|temp1[1];
  		   //Cal_C[i]=value;
  		 Cal_C[i]=I2C_Read_2Bytes(MS561101BA_ADDR,MS561101BA_PROM_BASE_ADDR + (i * MS561101BA_PROM_REG_SIZE));
  
  		}
  	printf("\n The MS561101BA is reading PROM : \r\n");
    printf("\r\nC1 = %d\r\nC2 = %d\r\nC3 = %d\r\nC4 = %d\r\nC5 = %d\r\nC6 = %d\r\n",Cal_C[1],Cal_C[2],Cal_C[3],Cal_C[4],Cal_C[5],Cal_C[6]);  
  }
  
  /************************************************************   
  * 函数名:MS561101BA_DO_CONVERSION   
  * 描述 :  
  * 输入  :无   
  * 输出  :无    
  */
  uint32_t MS561101BA_DO_CONVERSION(uint8_t command)
  {
  		uint32_t conversion;
  
  	 I2C_NoAddr_WriteByte(MS561101BA_ADDR,command);
  	 
  	delay_ms(10);//延时,去掉数据错误
   
  	conversion=I2C_Read_3Bytes(MS561101BA_ADDR,0);
  
     return conversion;
  
  }
  
  /************************************************************   
  * 函数名:MS561101BA_GetTemperature   
  * 描述 : 读取数字温度
  * 输入  :过采样率   
  * 输出  :无    
  */
  void MS561101BA_GetTemperature(u8 OSR_Temp)
  {
     
  	D2_Temp= MS561101BA_DO_CONVERSION(OSR_Temp);	
  	delay_ms(100);
  	
  	dT=D2_Temp - (((uint32_t)Cal_C[5])<<8);
  	Temperature=2000+dT*((uint32_t)Cal_C[6])/8388608;	//算出温度值的100倍,2001表示20.01°
  
  
  }
  
  
  /************************************************************   
  * 函数名:MS561101BA_GetPressure   
  * 描述 : 读取数字气压
  * 输入  :过采样率   
  * 输出  :无    
  */
  void MS561101BA_GetPressure(u8 OSR_Pres)
  {
  	
   
  	
  	D1_Pres= MS561101BA_DO_CONVERSION(OSR_Pres);
  
  	delay_ms(100); 
  	
  	OFF=(uint32_t)(Cal_C[2]<<16)+((uint32_t)Cal_C[4]*dT)/128.0;
  	SENS=(uint32_t)(Cal_C[1]<<15)+((uint32_t)Cal_C[3]*dT)/256.0;
  	//温度补偿
  	if(Temperature < 2000)// second order temperature compensation when under 20 degrees C
  	{
  		Temperature2 = (dT*dT) / 0x80000000;
  		Aux = (Temperature-2000)*(Temperature-2000);
  		OFF2 = 2.5*Aux;
  		SENS2 = 1.25*Aux;
  		if(Temperature < -1500)
  		{
  			Aux = (Temperature+1500)*(Temperature+1500);
  			OFF2 = OFF2 + 7*Aux;
  			SENS2 = SENS + 5.5*Aux;
  		}
  	}else  //(Temperature > 2000)
  	{
  		Temperature2 = 0;
  		OFF2 = 0;
  		SENS2 = 0;
  	}
  	
  	Temperature = Temperature - Temperature2;
  	OFF = OFF - OFF2;
  	SENS = SENS - SENS2;	
  
  	Pressure=(D1_Pres*SENS/2097152.0-OFF)/32768.0;
  
  }
  
  /************************************************************   
  * 函数名:MS561101BA_Init   
  * 描述 : MS561101BA初始化
  * 输入  :无   
  * 输出  :无    
  */ 
  void MS561101BA_Init(void)
  {
  	MS561101BA_Reset();
  	delay_ms(100);
  	MS561101BA_readPROM();
  	delay_ms(100);
  } 
  
  /************************************************************   
  * 函数名:SampleANDExchange   
  * 描述 : 读取数据并转换串口发送
  * 输入  :无   
  * 输出  :无    
  */ 
  void SampleANDExchange(void) 
  {
     uint8_t i=0;
  	MS561101BA_GetTemperature(MS561101BA_D2_OSR_4096);//0x58
  	MS561101BA_GetPressure(MS561101BA_D1_OSR_4096);		//0x48
  	ex_Pressure=(long)(Pressure);
  
      if(Pressure<0)
  	{
  		ex_Pressure=-ex_Pressure;
  		exchange_num[0]='-';
  	}
  	else exchange_num[0]='\0';
  
  	exchange_num[1]=ex_Pressure/100000+0x30;
  	ex_Pressure=ex_Pressure%100000;
  
  	exchange_num[2]=ex_Pressure/10000+0x30;
  	ex_Pressure=ex_Pressure%10000;
  
  	exchange_num[3]=ex_Pressure/1000+0x30;
  	ex_Pressure=ex_Pressure%1000;
  
  	exchange_num[4]=ex_Pressure/100+0x30;
  	ex_Pressure=ex_Pressure%100;
  
  	exchange_num[5]='.';
  
  	exchange_num[6]=ex_Pressure/10+0x30;
  	ex_Pressure=ex_Pressure%10;
  
  	exchange_num[7]=ex_Pressure+0x30;
  	printf("\nP : %c%c%c%c%c%c%c%c      mbar \r\n",exchange_num[0],exchange_num[1],exchange_num[2],exchange_num[3],exchange_num[4],exchange_num[5],exchange_num[6],exchange_num[7]);
  //    	for(i=0;i<8;i++)
  // 	{
  // 	  printf("%c",exchange_num[i]);
  // 	}
  //		printf(" mbar   \r\n");
  	printf("T : %4.3f      °C\r\n ",Temperature/100);
    	
  }

欢迎讨论,共同进步

STM32+MS5611测气压温度例程详解,测试无误_The Dawn-CSDN博客

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32+MS5611测气压温度例程详解,测试无误 的相关文章

  • 飞控开发--气压计MS5611

    ms5611简介 xff1a 官方给出的最大分辨率 xff1a 10cm 工作电压 xff1a 1 8v 3 6v 气压 AD 精度 xff1a 24位 工作环境 xff1a xff0d 40 43 85 C xff0c 10 1200mb
  • STM32F407单片机移植MS5611气压计(基于IIC)---同时解决温度低于20度时计算得到的大气压错误的问题

    最近一个工程项目需要使用MS5611气压计 就花时间研究了一下 发现网上很多都是基于STM32F103单片机的MS5611气压计源程序 当移植到STM32F407时发现采集的大气压力和温度值不对 同时发现网上部分程序在温度高于20度时 计算
  • 基于STM32F103ZET6核心板控制HX711(称重传感器带屏蔽)

    目的 使用核心板控制传感器 实现串口打印数据 硬件要求 1 gt stm32f103zet6核心板 2 gt HX711 带屏蔽 HX711有好几款板子 我这里使用的是带屏蔽的板子 只要知道引脚的功能什么板子都是一样的 HX711原理图 管
  • DFRobot智能视觉传感器二哈识图(Huskylens)的应用

    二哈识图 HuskyLens 是国内著名开源硬件商DFRobot在人工智能领域出品的一款简单易用的智能视觉传感器 其板载的UART I2C端口 可以与主流控制器Arduino micro bit LattePanda Raspberry P
  • 传感器学习——旋转编码器

    旋转编码器是将旋转机械位移量转换为电器信号 对该信号进行处理后检测位置 速度等的传感器 旋转编码器可分为 增量式 编码器和 绝对值 式编码器 1 增量式编码器 旋转盘转动时 光敏二极管断续收到发光二极管发出的光 从而输出方波 增量式编码器通
  • 九轴传感器之测试篇

    关于九轴传感器的数据测试处理
  • 【mcuclub】水流量检测模块-YF-S401

    一 实物图 型号 YF S401 二 原理图 编号 名称 功能 1 VCC 电源正 红色线 2 GND 电源地 黑色线 3 OUT 输出引脚 黄色线 三 简介 水流量传感器主要由塑料阀体 水流转子组件和霍尔传感器组成 它装在电器的进水端 用
  • 通过 rqt_plot 完成ATI F/T 力和力矩传感器六轴数据可视化

    基于该篇博客https blog csdn net qq 34935373 article details 103481401 实现了通过ROS节点的方式启动ATI sensor 完成配置归零和设置软件矢量偏移 并且获取六轴数据 实时的打印
  • DHT11解析

    一 DHT11工作原理 1 获取数据 DHT11包括一个电阻式感湿元件和一个NTC测温元件 这两个获取温湿度数据的方式都差不多 利用湿 温 敏元件的电气特性 如电阻值 随湿 温 度的变化而变化的原理进行湿 温 度测量 2 数据发送 数据格式
  • 基于Matlab的激光雷达与单目摄像头联合外参标定

    1 背景介绍 目前团队正在与某主机厂合作开发L4级自动驾驶出租车项目 所用的传感器包括80线激光雷达和单目摄像头 为了充分利用Lidar和Cam各自的优势 设计了一种融合算法 需要获得Lidar2Camera的联合外参 前期使用Autowa
  • 博世BMI160六轴传感器I2C通信配置

    博世BMI160简介 Bosch Sensortec公司推出的最新BMI160惯性测量单元将最顶尖的16位3轴重力加速度计和超低功耗3轴陀螺仪集成于单一封装 采用14管脚LGA封装 尺寸为2 5 3 0 0 8mm3 当加速度计和陀螺仪在全
  • MS5611气压计 I2C驱动代码 STM32

    文章目录 前言 通信接口 IIC 一 MS5611的5种命令 RESET 重启芯片 READ PROM D1 D2 CONVERSION READ ADC RESULT 二 实现代码 1 初始化 2 读取数据 3 补偿温度数据 前言 这篇博
  • MPU6050使用心得(简单分享一下)

    前言 选用MPU6050做 倾斜检测 功能 前期准备 开发板 正点原子STM32F103 精英版 STM32F103ZET6 模块 GY 521 MPU6050 其他 杜邦线若干 烧录线 FlyMcu Keil5 正点原子开发板配套的套件
  • 【传感器课程设计——DHT11温湿度数据上传阿里云】课程设计论文大纲

    1 摘要 摘要可以分为中文和英文两部分 2 概述 2 1 课程设计背景 2 2 国内外研究现状 2 3 报告组织形式 3 系统设计 3 1 设计目标 3 2 设计方案 3 3 设计方案分析 3 4 程序结构 4 硬件设计 4 1 ESP82
  • SHT3x-DIS驱动及应用详解(附源码和手册)

    文章目录 一 电路组成 二 通讯指令说明 一 单次获取数据指令 二 周期获取数据指令 1 配置模式 2 读取数据 三 加快响应时间指令 四 停止周期读取数据指令 五 复位 1 IIC接口复位 2 软复位 重新初始化 3 一般呼叫复位指令 4
  • HX711称重模块的使用

    HX711称重模块的使用 先贴一段文字 见多了可以跳过直接看下面 满量程输出电压 激励电压 灵敏度1 0mv v 例如 供电电压是5v 乘以灵敏度1 0mv v 满量程5mv 相当于有5Kg 重力产生时候产生5mV 的电压 2 概述 711
  • 自动驾驶汽车传感器融合系统及多传感器数据融合算法浅析

    本文转自电子技术设计 知乎小鹏汽车 作者 Hannes Estl 德州仪器 TI 汽车ADAS部门的总经理 如需转载请注明来源 原文没找到 只找到知乎小鹏汽车的一个回答https zhuanlan zhihu com p 23881606
  • 【雕爷学编程】Arduino动手做(93)--- 有关OLED屏的两个非常重要的知识点:像素点点阵和坐标系

    37款传感器与执行器的提法 在网络上广泛流传 其实Arduino能够兼容的传感器模块肯定是不止这37种的 鉴于本人手头积累了一些传感器和执行器模块 依照实践出真知 一定要动手做 的理念 以学习和交流为目的 这里准备逐一动手尝试系列实验 不管
  • [附代码]多输入AD模数转换,数据接受模块 Verilog 实现 (授人与渔)

    要素察觉 本文基于 AD7888 八输入通道 模数转换芯片 对转换后的数据在 FPGA 中进行接收 所使用的 HDL 为 Verilog 所有实现步骤依据 AD7888 DataSheet 中给出的相关数据和时序图 对原理和相应 Veril
  • IMU的ROS调试开发工具包:imu_tools

    目录 imu tool包 问题 参数配置便利性问题 实例 调试microstrain 3dm gx5 25 imu 问题 发布的imu姿态与实际imu姿态不一致问题 imu tool包 http wiki ros org imu tools

随机推荐

  • 基础篇——Pycharm的安装与使用windows+ubuntu 初学者此篇够用

    简介 Pycharm是python编程过程中最为推荐的编辑调试软件之一 其使用简单 界面友好 也成了学习Python路上必须学会的软件之一 本篇教程简单介绍一下windows用户从安装到日常使用的基本功能 其他系统也可简单参考 软件安装 P
  • 嵌入式Linux学习笔记 1-14 异常与中断

    1 异常与中断的概念引入与处理流程 上图解释了何为中断何为异常 其中中断也是属于一种异常 引申拓展为ARM对异常 中断 的处理过程 1 初始化 1 设置中断源 让他可以产生中断 如某个按键可以产生中断的话 我们可以设置他的gpio引脚为中断
  • LeetCode刷题笔记--015. 三数之和

    题目描述 给定一个包含 n 个整数的数组 nums 判断 nums 中是否存在三个元素 a b c 使得 a b c 0 找出所有满足条件且不重复的三元组 注意 答案中不可以包含重复的三元组 例如 给定数组 nums 1 0 1 2 1 4
  • 【算法】蓝桥杯dfs深度优先搜索之凑算式总结

    本文 算法 蓝桥杯dfs深度优先搜索之凑算式总结 相关文章 算法 蓝桥杯dfs深度优先搜索之排列组合总结 算法 蓝桥杯dfs深度优先搜索之图连通总结 前言 曾几何时这个词现在用正适合不过了 曾几何时我还是对dfs算法一脸懵x的状态 虽说大二
  • Java中32位的最高位为1的二进制数如何转换成整数

    int类型的 3的32位表示为 11111111111111111111111111111101 将32位翻转的时候应该为 10111111111111111111111111111111 当时在LeetCode做这题的时候想的是用字符串翻
  • IDEA开发工具11---Python引入第三方包

    如要在工程文件中引入requests 但是本机上并没有安装这个包 在工程文件中输入import requests 然后Alt Enter 然后回车 IDEA会自动安装这个包
  • ESP8266 连接 MQTT

    ESP8266 连接 MQTT 主控芯片 MM32F2377 MB 039 WiFi 适配器 ESP8266 开发环境 IAR 7 80 4 MQTT 模拟服务器 MQTT fx MQTT MQTT is an OASIS standard
  • 解决windows 下使用 mingw编译器 调试时 无法跟进源码

    windows 下使用 mingw编译器 调试时 无法跟进源码 最近在公司使用QT 开发 官方在线下载的 安装的QT mingw 都是没有debug版本的 由于没有debug版本动态库 所以你调试的时候压根就无法跟进QT源代码里 那么找问题
  • 关于在windows下启动zkServer.cmd闪退的解决办法

    1 下载zookeeper注册中心 下载地址 http www apache org dyn closer cgi zookeeper 下载后解压即可 进入D apach zookeeper 3 4 5 bin 双击zkServer cmd
  • ES6 数组内对象去重

    在实际的项目当中不可避免的会遇到数组里面元素重复情况 下面将介绍几种ES6数组去重的方法 1 使用Set去重 const arr 张三 张三 三张三 let set new Set arr set 自带去重 Set 张三 三张三 conso
  • Ubuntu搭建Samba服务-学习记录

    文章目录 Ubuntu安装Samba流程 Samba配置文件 Samba添加账户 配置文件修改 Samba服务控制 设置开机自动启动 通过systemctl 启动服务 通过 rc local 启动 Windows访问 参考链接 当前文章仅用
  • 福禄克电缆检测仪MS2-100有哪些功能?

    现在的通信技术人员有很多问题需要处理 而不仅仅是电缆问题 在确定连接问题的原因之前 必须先排除可能存在的电缆和服务等问题 是否有电话电压 极性是什么 远端有以太网交换机吗 PoE 是否可用 福禄克电缆检测仪MS2 100可以确认这些问题 为
  • LaTeX:插入PDF出现版本警告

    LaTeX LaTeX LATE X 插入PDF出现版本警告 文章目录 LaTeX LaTeX LATE X 插入PDF出现版本警告 1 问题描述 2 解决
  • 微信封号被限制的几种原因及解决方法

    微信被限制了也不需要紧张 找到原因对应处理就行了 一 总结一下微信微信被限制登录的几种原因 1 频繁的违规操作 微信违规操作了 比方说频繁的添加微信好友 发布违规信息 使用第三方非法破解软件等 这些行为都属于微信明令禁止的行为 如果触犯了微
  • vim连接外接显示器后右侧无法选中的问题

    RT 解决办法 在 vimrc添加如下代码 if has mouse sgr set ttymouse sgr else set ttymouse xterm2 end 原文连接 https ifconfiger com articles
  • 4.jeston nano NX安装系统、pycharm

    笔者有幸通过项目一次入手一块jeston Xavier NX和jeston nano 随即开始研究安装系统和pycharm 其中系统换了4个镜像才安装成功 其实下载安装官方的就行 其他的包括店里的都不要用 1 安装系统 务必注意镜像要下对
  • 如何修改VsCode的背景图片

    步骤 第一步 准备一张图片 图片路径最好不要出现中文 第二步 在VsCode中安装插件 搜索 background 安装这个插件 第三步 这个插件安装成功之后 里面自带了一些背景 如果喜欢可以不用换 也可以根据需要自定义 找到 settin
  • SpringBoot-线程池ThreadPoolExecutor异步处理(包含拆分集合工具类)

    ThreadPoolExecutor VS ThreadPoolTaskExecutor ThreadPoolTaskExecutor是对ThreadPoolExecutor进行了封装处理 配置文件application yml 异步线程配
  • 顺序表的静态和动态实现

    静态顺序表 所谓静态顺序表就是把空间的大小给定 结构体的定义 typedef struct SeqList DataType array MaxSize int size SeqList 基本操作的实现 void InitSeqList S
  • STM32+MS5611测气压温度例程详解,测试无误

    硬件平台 STM32F10X MS5611 JLink 软件平台 Keil 4 一 基础知识 首先 MS5611是什么 MS5611气压传感器是集合SPI和I C 高达20 MHz 总线接口的高分辨率气压传感器 分辨率可达到10cm 内部有