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版权协议,转载请附上原文出处链接和本声明。