用I2C读取SM9541的数据

SM9541简介

SM9541是SMI的MEMS低压压力传感器,结合了先进的信号调理IC,可提供完整的压力校准和温度补偿,用I2C通信。
SM9541的型号有很多种,但是读取的方法几乎一样,只不过每种传感器的量程和精确度可能有所差别。我用的是SM9541-010C-D-C-3-S,相对压力检测范围-10 to 10 cmH2O,耐压范围±1.5 PSI,冲击压力可达±3.0 PSI。温度补偿范围-5 to 65°C,精度1%。全数字式,I2C数字接口。符合ISO9001 and ISO/TS 16949标准。典型供电电压3.3V和5V,最大供电电压6V,工作温度范围-5 to 65°C,SOIC-16标准封装。
一种可能的应用场景:用它来测量赛车跑动时空套表面的风压,一根管插入车内,另一根管在车外,可以测量风压,提供可供空套工程师分析的数据。

代码

首先提供一些I2C的一些基础操作的代码,封装好,之后读取数据的时候要用。最好是自己阅读I2C通信协议,对I2C通信的逻辑有所了解,这里只给出了一例子。

#include "I2C.h"
#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)
#define SDA_IN()  I2C_GPIOB_Pin7_In()
#define SDA_OUT() I2C_GPIOB_Pin7_Out()
#define IIC_SCL    PBout(6) 
#define IIC_SDA    PBout(7) 
#define READ_SDA   PBin(7)
void IIC_Init(void)//GPIO初始化,拉高SCL和SDA。
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;      
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	IIC_SCL=1;
	IIC_SDA=1;
}

void IIC_Start(void)//起始位
{
	SDA_OUT();     	
	IIC_SDA=1;	  	
	IIC_SCL=1;		
	delay_us(4);    
 	IIC_SDA=0;		
	delay_us(4);   
	IIC_SCL=0;	
}

void IIC_Stop(void)//终止位
{
	SDA_OUT();  	
	IIC_SCL=0;		
	IIC_SDA=0;		
 	delay_us(4);	 
	IIC_SCL=1; 	 
	IIC_SDA=1;		
	delay_us(4);			   	
}
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;  
}
void IIC_Ack(void)//发送ACK
{
	IIC_SCL=0;    	
	SDA_OUT();		
	IIC_SDA=0;		
	delay_us(2);	
	
	IIC_SCL=1;		
	delay_us(2);
	IIC_SCL=0;
	delay_us(2);
}   
void IIC_NAck(void)//发送NACK
{
	IIC_SCL=0;   
	SDA_OUT();   	
	IIC_SDA=1;   
	delay_us(2); 
	IIC_SCL=1;   	
	delay_us(2); 	
	IIC_SCL=0; 
delay_us(2);  
}
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);
    }	 
}
u8 IIC_Read_Byte_ACK(void)//接收函数,结尾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); 
    }					 
       	IIC_Ack();
    return receive;
}
u8 IIC_Read_Byte_NACK(void)//接收函数,结尾NACK
{
	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); 
    }					 
  	IIC_NAck();
    return receive;
}

读取数据,应该阅读SMI给的数据手册,里面详尽的告诉了怎么读取数据

int main(void)
{
	SysTick_Init(72);
  IIC_Init();
	while(1)
	{
	IIC_Start();//开始位
	IIC_Send_Byte(SM_Address1);//SM_Address在数据手册中给了,是0x28,根据数据手册,要线发送(SM_Address<<1)+1;表示要读取数据,之后会连续接收到四个字节
	IIC_Wait_Ack();
	I2C_BYTE1=IIC_Read_Byte_ACK();//I2C_BYTE1的数据类型是u8,以下是连续读取四个字节,其中前三个最后是ACK,最后一个是NACK
	I2C_BYTE2=IIC_Read_Byte_ACK();
	I2C_BYTE3=IIC_Read_Byte_ACK();
	I2C_BYTE4=IIC_Read_Byte_NACK();
	IIC_Stop();//停止位
	
	}
}

读取到四个字节的含义:绿色的两位是状态位,红色的14位,红色的11位是温度的数据。
在这里插入图片描述
压强的计算方法:
在这里插入图片描述

	I2C_BYTE4>>=5;
	I2C_temperature=I2C_BYTE3*8+I2C_BYTE4;
	I2C_pressure=(0x3f&I2C_BYTE1)*256+I2C_BYTE2;
	I2C_status=I2C_BYTE1>>6;//先移位还原原始数据
	temp1=20.0/(14745.0-1638.0);
	Pressure_In_cmH2O=(temp1*(I2C_pressure-1638.0)+(-10.0));
	temp2=(float)I2C_temperature/2048.0;
	Temperature_In_Celsius=(temp2*200.0)-50.0;

工程文件和SMI的数据手册以及官方所给的编程指南已打包上传,有需要的朋友可以下载。
debug的结果
在这里插入图片描述


版权声明:本文为Rendezvous1原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。