GXP800差压传感器驱动程序

本文详细介绍了STM32平台上的GXP800压力与温度传感器的I2C通信接口,包括其特点、典型应用、通信协议以及提供了一些关键驱动函数的代码示例,如初始化、数据传输和CRC校验。

一、产品特点

• 压力范围±500Pa,精度高达±3.0%m.v.

• 基于热式流量测量的压力

• 出色的迟滞性和重复性

• 线性化和温度补偿

• 16位分辨率的数字I2C

• 低零点漂移

• 最小可检测压差0.02pa

二、典型应用

引脚

名字

描述

1

SCL

I2C总线串行时钟线

2

VDD

电源

3

GND

4

SDA

I2C总线串行数据线

三、通信协议

每个SCL和SDA线路必须使用约4.7k欧姆的上拉电阻器连接到VDD,GXPP800的VDD输入范围为3-5.5V,但建议的VDD为5V(校准条件)。

I2C地址:0x25

字节数量

数据定义

Byte1

差压高字节

Byte2

差压低字节

Byte3

CRC

Byte4

温度高字节

Byte5

温度低字节

Byte6

CRC

 CRC校验字节是对16 bit数据进行的CRC运算:

四、驱动代码

1、I2C1.h

#ifndef __IIC_H
#define __IIC_H

#include "stdint.h"
#include "stm32f10x.h"                  // Device header
#include "string.h"

void I2C_init(void);
void I2C_Start(void);
void I2C_Spot(void);
void I2C_SendByte(uint8_t Byte);
uint8_t I2C_ReceiveByte(void);
void I2C_SendAck(uint8_t Ackbit);
uint8_t I2C_ReceiveAck(void);


void I2C_SCL_H(void);
void I2C_SCL_L(void);
void I2C_W_SDA(uint8_t BitValue);
void I2C_W_SCL(uint8_t BitValue);
uint8_t I2C_R_SDA(void);

#endif

2、 I2C1.c

#include "I2C1.h"
#include "delay.h"
#include "stdio.h"

/***********
*		推挽输出
************/

void I2C1_INIT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Pin = I2C1_SCL;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_Init(I2C1_SCL_GPIOX, &GPIO_InitStructure);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Pin = I2C1_SDA;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_Init(I2C1_SDA_GPIOX, &GPIO_InitStructure);
    I2C1_SCL_H;
    I2C1_SDA_H;
}
/*******************************************************************************
 * 函 数 名         : I2C_SDA_OUT
 * 函数功能		   : SDA输出配置
 * 输    入         : 无
 * 输    出         : 无
 *******************************************************************************/
void I2C1_SDA_OUT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Pin = I2C1_SDA;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_Init(I2C1_SDA_GPIOX, &GPIO_InitStructure);
}

void I2C1_SDA_IN(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Pin = I2C1_SDA;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(I2C1_SDA_GPIOX, &GPIO_InitStructure);
}
/*******************************************************************************
* 函 数 名         : I2C1_Start
* 函数功能		   : 产生起始信号
*******************************************************************************/
void I2C1_Start(void)
{
    I2C1_SDA_OUT();
    I2C1_SCL_H;
    I2C1_SDA_H;

    Delay_us(5);
    I2C1_SDA_L;
    Delay_us(6);
    I2C1_SCL_L;

}
/*******************************************************************************
* 函 数 名         : I2C1_Stop
* 函数功能		   : 产生停止信号
*******************************************************************************/
void I2C1_Stop(void)
{

    I2C1_SDA_OUT();

    I2C1_SCL_L;
    I2C1_SDA_L;
    I2C1_SCL_H;
    Delay_us(6);
    I2C1_SDA_H;
    Delay_us(6);
}

void I2C_RS(void)
{

    I2C1_SDA_OUT();
    I2C1_SCL_L;
    Delay_us(2);
    I2C1_SDA_L;
    Delay_us(2);
    I2C1_SDA_H;
    Delay_us(2);
    I2C1_SCL_H;
    Delay_us(2);
    I2C1_SDA_L;
    Delay_us(2);
    I2C1_SCL_L;
    Delay_us(2);
}
/*******************************************************************************
* 函 数 名         : I2C1_Ack
* 函数功能		   : 主机产生应答信号ACK
*******************************************************************************/
void I2C1_Ack(void)
{
    I2C1_SCL_L;
    I2C1_SDA_OUT();
    I2C1_SDA_L;
    Delay_us(1);
    I2C1_SCL_H;
    Delay_us(3);
    I2C1_SCL_L;
}
/*******************************************************************************
* 函 数 名         : I2C1_NAck
* 函数功能		   : 主机不产生应答信号NACK
*******************************************************************************/
void I2C1_NAck(void)
{
    I2C1_SCL_L;
    I2C1_SDA_OUT();
    I2C1_SDA_H;
    Delay_us(1);
    I2C1_SCL_H;
    Delay_us(3);
    I2C1_SCL_L;
}
/*******************************************************************************
* 函 数 名         : I2C1_Wait_Ack
* 函数功能		   : 等待从机应答信号
  返回值:            1 接收应答失败
		  	         0 接收应答成功
*******************************************************************************/
uint8_t I2C1_Wait_Ack(void)
{
    uint8_t tempTime = 0;

    I2C1_SDA_IN();

    I2C1_SDA_H;
    Delay_us(1);
    I2C1_SCL_H;
    Delay_us(1);

    while(GPIO_ReadInputDataBit(I2C1_SDA_GPIOX, I2C1_SDA))
    {
        tempTime++;
        Delay_us(1);

        if(tempTime > 250)
        {
            I2C1_Stop();

            return 1;
        }
    }

    I2C1_SCL_L;
    Delay_us(1);
    return 0;
}

/*******************************************************************************
* 函 数 名         : I2C1_SendByte
* 函数功能		   : 发送一个字节
*******************************************************************************/
void I2C1_SendByte(uint8_t txd)
{
    uint8_t i = 0;

    I2C1_SDA_OUT();
    I2C1_SCL_L;

    for(i = 0; i < 8; i++)
    {
        if((txd & 0x80) > 0)  // 0x80  1000 0000
            I2C1_SDA_H;
        else
            I2C1_SDA_L;

        txd <<= 1;
        Delay_us(1);
        I2C1_SCL_H;
        Delay_us(2);
        I2C1_SCL_L;
        Delay_us(2);
    }
}
/*******************************************************************************
* 函 数 名         : I2C1_Read_Byte
* 函数功能		   : 主机读取一个字节
*******************************************************************************/
uint8_t I2C1_ReadByte(uint8_t ack)
{
    uint8_t i = 0, receive = 0;
		uint8_t tempTime = 0;
    I2C1_SDA_IN();

    for(i = 0; i < 8; i++)
    {
        I2C1_SCL_L;
        Delay_us(2);
        I2C1_SCL_H;

        while((!GPIO_ReadInputDataBit(I2C1_SCL_GPIOX, I2C1_SCL)) && tempTime < 10)
        {
            tempTime += 1;
            Delay_us(1);
        }
        receive <<= 1;

        if(GPIO_ReadInputDataBit(I2C1_SDA_GPIOX, I2C1_SDA))
            receive++;

        Delay_us(1);
    }

    if(ack == 0)
        I2C1_NAck();
    else
        I2C1_Ack();

    return receive;
}

/*******************************************************************************
* 函 数 名         : I2C_read_bit
* 函数功能		   : 主机读取一位
*******************************************************************************/
uint8_t I2C_read_bit(void)
{
    uint8_t i;
    I2C1_SDA_IN();
    I2C1_SCL_L;
    Delay_us(2);
    I2C1_SCL_H;
    Delay_us(2);
    // while(!GPIO_ReadInputDataBit(I2C1_SCL_GPIOX, I2C_SCL_L))
    //   ;

    i = GPIO_ReadInputDataBit(I2C1_SDA_GPIOX, I2C1_SDA);

    Delay_us(2);
    I2C1_SCL_L;
    Delay_us(2);
    return i;
}

3、GXP800.h

#ifndef __GXP800_H
#define __GXP800_H 
  
#include "stm32f10x.h"


// 初始化I2C1串口
void GXP800_init(void);
//GXP800连续测量
void GXP800_Write_Cmd(uint16_t cmd);
//GXP800获取值
void GXP800_GetValue(void);
void GXP800_Read(uint16_t add);
void GXP800_GetValue1(void);
void GXP800_ReadData(void);
void GXP800_ReadData1(void);
uint8_t crc8(uint16_t data);
#endif

4、GXP800.c

#include "GXP800.h"
#include "Delay.h"
#include "stdio.h" // printf用
#include "Serial.h"
#include "I2C1.h"

//uint8_t  crc = 0xff;
uint16_t dif_pressure;//差压
uint16_t tempre;  //温度
uint16_t Scale_Factors; //压差系数

// 初始化I2C1串口
void GXP800_init(void)
{
	I2C1_INIT();
}
void  GXP800_Read(uint16_t add)
{    

	I2C1_Start();  	 	   	
	I2C1_SendByte(0X4a);           //发送写地址	   
	I2C1_Wait_Ack();
	I2C1_SendByte(add>>8);//发送高地址
	I2C1_Wait_Ack();
	I2C1_SendByte(add);   //发送低地址
	I2C1_Wait_Ack(); 
	I2C1_Stop();//停止
	SDP800_ReadData();
}	
void GXP800_ReadData(void)
{    
	uint8_t i=0;
	uint8_t ack=0;
	uint8_t p[8];
	Delay_ms(20);
	I2C1_Start();
	I2C1_SendByte(0X4b);           //发送读地址	
	I2C1_Wait_Ack();	
 
	for(i=0;i<6;i++)
		{
		 if(i<5)
		 {
				ack=1;
		 }
		 else
		 {
				ack=0;//最后一个发送nack
		 }
		p[i]=I2C1_ReadByte(ack);	
		}
	I2C1_Stop();//停	止
	Delay_ms(5);
	if((crc8((p[0]<<8)+p[1])==p[2])&&(crc8((p[3]<<8)+p[4])==p[5]))
	{
		Serial_SendByte(p[0]);
		Serial_SendByte(p[1]);
		Serial_SendByte(p[2]);
		Serial_SendByte(p[3]);
		Serial_SendByte(p[4]);
		Serial_SendByte(p[5]);
	}
	else
	{
		GXP800_ReadData1();
	}
}	
void GXP800_ReadData1(void)
{    
	uint8_t i=0;
	uint8_t ack=0;
	uint8_t p[8];
	Delay_ms(20);
	I2C1_Start();
	I2C1_SendByte(0X4b);           //发送读地址	
	I2C1_Wait_Ack();	
 
	for(i=0;i<6;i++)
		{
		 if(i<5)
		 {
				ack=1;
		 }
		 else
		 {
				ack=0;//最后一个发送nack
		 }
		p[i]=I2C1_ReadByte(ack);	
		}
	I2C1_Stop();//停	止
	Delay_ms(5);
	if((crc8((p[0]<<8)+p[1])==p[2])&&(crc8((p[3]<<8)+p[4])==p[5]))
	{
		Serial_SendByte(p[0]);
		Serial_SendByte(p[1]);
		Serial_SendByte(p[2]);
		Serial_SendByte(p[3]);
		Serial_SendByte(p[4]);
		Serial_SendByte(p[5]);
	}
	else
	{
		SDP800_ReadData();
	}
}
//GXP800连续测量
void GXP800_Write_Cmd(uint16_t cmd)
{				   	  	    																 
     	
	I2C1_Start();  
	I2C1_SendByte(0X4a);	    //读地址
	I2C1_Wait_Ack();
	I2C1_SendByte(cmd>>8);//发送高地址
	I2C1_Wait_Ack();
	I2C1_SendByte(cmd);   //发送低地址
	I2C1_Wait_Ack(); 	 										  		   			   
	I2C1_Stop();//停止
	Delay_ms(10);
}

//GXP800获取值
void GXP800_GetValue(void)
{
	GXP800_Read(0x3615);
}
//滤波输出
void GXP800_GetValue1(void)
{
	GXP800_Read(0x361e);
}
/******************************************************************************
 * Name:    CRC-8               x8+x5+x4+1
 * Poly:    0x31
 * Init:    0xFF
 * Refin:   False
 * Refout:  False
 * Xorout:  0x00
 * Note:	
 *****************************************************************************/
uint8_t crc8(uint16_t data) {
		uint8_t i,j;
		uint8_t dat[2];
		dat[0]=data>>8;
		dat[1]=data;
    uint8_t crc=0XFF; /* 计算的初始crc值: 0 - 输入值, 1 - 输入翻转 */ 
		
		for(j=0;j<2;j++)
    {
        crc ^= dat[j];  /* 每次先与需要计算的数据异或,计算完指向下一数据 */  
        for (i=8; i>0; --i)   /* 下面这段计算过程与计算一个字节crc一样 */  
        { 
            if (crc & 0x80)
                crc = (crc << 1) ^ 0x31;
            else
                crc = (crc << 1);
        }
    }
 	//reture (~crc); /* 输出翻转 */
    return (crc); 

}
友情提示:
欢迎各位伙伴咨询、测试有任何问题可随时交流沟通。
TEL : 15134034823 !!! 欢迎骚扰,哈哈^_^。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值