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

硬件平台: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博客

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
首先,需要将STM32与MAX6675连接。Connect MAX6675的VCC和GND引脚至STM32相应的电源和接地引脚,以便MAX6675可以得到能够工作的电源。将MAX6675的DO引脚连接至STM32的MISO引脚,将CLK引脚连接至STM32的SCK引脚以进行通信。 接下来,需要创建STM32的工程并编写代码以读取MAX6675传输的温度数据。首先,我们需要初始化SPI模块以与MAX6675进行通信。您可以使用STM32的SPI库或自行编写驱动程序。 接下来,我们可以通过发送16位空数据到MAX6675并检查返回的16位数据的位0来读取温度数据。如果bit0为0,则读取数据成功,否则该位为1,则表示存在错误。接下来,我们需要进行数据转换,将读取到的数据转化为可读取的温度。 最后,我们需要将温度数据通过UART或其他接口进行输出或显示。完成后,您可以将程序下载至STM32进行测试。 下面是一个简单的示例代码: ```c #include "stm32f10x.h" #include "stdio.h" /* 初始化SPI */ void InitSPI(void) { // 配置GPIO为SPI模式 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置SPI RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); SPI_InitTypeDef SPI_InitStructure; SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); } int main(void) { // 初始化SPI InitSPI(); // 读取温度数据 uint16_t data, temp; while(1) { // 发送16位空数据获取温度数据 SPI_I2S_SendData(SPI1, 0x0000); // 等待数据传输结束 while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); // 读取数据 data = SPI_I2S_ReceiveData(SPI1); // 检查bit0 if((data & 0x01) == 0) { // 数据读取正确,进行数据转换 temp = data >> 3; // 输出温度 printf("Temperature: %d.%d C\r\n", temp >> 4, (temp & 0x0F) * 62); } else { // 数据读取失败,输出错误信息 printf("Error reading temperature data\r\n"); } } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值