一、产品特点
二、典型应用
引脚编号 | 引脚定义 | 说明 |
1.2.3.4.5.8.9.12.13.14.15.16 | ?????????????NC | 空置 |
6 | VSS | 电源地 |
7 | VDD | 电源正 |
10 | SDA | 数据 |
11 | SCL | 时钟? |
I2C ?总线使用 ?SCL ?和 ?SDA ?作为信号线。这两根线都通过上拉电阻连接到 ?VDD,通信时都保持为高电平。
?三、通信协议
1、寄存器地址?
地址 | 位地址 | 寄存器名称 | 默认值 | 描述描述 |
0x30 | 7-4 | Reserve | 4'b0000 | 写入0x0A开始单次压力采集模式,当寄存器值变为0x02时,单次采集完 成; |
3 | Sco | 1'b0 | ||
2-0 | Measurement ctn<2:0> | 3'b000 | ||
0x06 | 7-0 | PDATA<23:16> | 0x00 | 24bit有符号数,存储经过校准的压力传感器数据 若最高位为0,? Pdata = PDataxos*65536+ PData.o7*256+PDataoxo8; 若最高位为1,? Pdata = PData.o6*65536+PDataxo*256+ PDatax8-16777216; |
0x07 | 7-0 | PDATA<15:8> | ?0x00 | |
0x08 | 7-0 | PDATA<7:0> | 0x00 |
2、数字输出转换?
使用如下等式,可将数字输出寄存器值转化为压力值:
P=(Code-0.5)/0.4*PH
其中 Code 为数据寄存器归一化值(Pdata /8388608);PH 为满量程压力值,P 为实际压力
值,单位为 kPa;
测量压力值转换示例:
若所选型号满量程气压为10kPa,当 0x06、0x07、0x08 寄存器的值分别为 0x5E,0xBE,0xBF,
Pdata =94 * 65536+ 190 * 256 + 191 = 6209215,
得到压力值 P(kPa) = (Pdata /8388608-0.5)/0.4*10= 6 kPa。
3、接口协议
(1)设备地址
该系列产品的 ?I2C ?设备地址如下:
A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 | W/R |
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
(2)I2C协议?
?(3)I2C 写时序:
写操作是以写入模式(读写位为0)发送从机地址来实现的, 从而产生从机写地址11111110b。然后主机发送成对的寄存器地址及对应的数值。写操作以 STOP 位终止。 图示表格以写 0x30 寄存器为例,
I2C 读时序如下:
在开始读操作之前,首先寄存器地址在写模式(从机地址 11111110b)下被发送。然后重新产生开始信号,之后从机在读模式下以 I2C 地址(11111111b)被寻址。从机从寄存器地址开始发送寄存器值直到一个 NOACK 信号和停止条件产生,读操作结束。图示表格以读取0x06,0x07,0x08 寄存器,
四、单片机驱动程序
?STM32F103 + GXP9541压差传感器驱动实例?
1、I2C1.h
#ifndef __IIC1_H
#define __IIC1_H
#include "stdint.h"
#include "stm32f10x.h" // Device header
#include "string.h"
#define SCL GPIO_Pin_8 //PB6---CTRL_SCL
#define SDA GPIO_Pin_9 //PB7---CTRL_SDA
#define I2C1_PORT GPIOB //IIC端口
#define I2C1_SCL_H GPIO_SetBits(I2C1_PORT,SCL)
#define I2C1_SCL_L GPIO_ResetBits(I2C1_PORT,SCL)
#define I2C1_SDA_H GPIO_SetBits(I2C1_PORT,SDA)
#define I2C1_SDA_L GPIO_ResetBits(I2C1_PORT,SDA)
#define I2C1_Read GPIO_ReadInputDataBit(I2C1_PORT, SDA)
void I2C1_INIT(void);
void I2C_SDA_OUT(void);
void I2C1_SDA_IN(void);
void I2C1_Start(void);
void I2C1_Stop(void);
void I2C1_SendByte(uint8_t Byte);
void I2C1_Ack(void);
void I2C1_NAck(void);
uint8_t I2C1_Read_Byte(uint8_t ack);
uint8_t I2C1_Wait_Ack(void);
#endif
2、I2C1.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "string.h"
#include "I2C1.h"
/***********
* 推挽输出
************/
void I2C1_INIT(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB ,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDA | SCL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(I2C1_PORT,&GPIO_InitStructure);
I2C1_SCL_H;
I2C1_SDA_H;
}
/*******************************************************************************
* 函 数 名 : I2C_SDA_OUT
* 函数功能 : SDA输出配置
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void I2C_SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDA;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(I2C1_PORT, &GPIO_InitStructure);
}
void I2C1_SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDA;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(I2C1_PORT, &GPIO_InitStructure);
}
/*******************************************************************************
* 函 数 名 : I2C1_Start
* 函数功能 : 产生起始信号
*******************************************************************************/
void I2C1_Start(void)
{
I2C_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)
{
I2C_SDA_OUT();
I2C1_SCL_L;
I2C1_SDA_L;
I2C1_SCL_H;
Delay_us(6);
I2C1_SDA_H;
Delay_us(6);
}
/*******************************************************************************
* 函 数 名 : I2C1_SendByte
* 函数功能 : 发送一个字节
*******************************************************************************/
void I2C1_SendByte(uint8_t Byte)
{
uint8_t i;
I2C_SDA_OUT();
I2C1_SCL_L;
for(i=0;i<8;i++)
{
if((Byte & 0x80) > 0) // 0x80 1000 0000
I2C1_SDA_H;
else
I2C1_SDA_L;
Byte <<= 1;
Delay_us(1);
I2C1_SCL_H;
Delay_us(2);
I2C1_SCL_L;
Delay_us(2);
}
}
/*******************************************************************************
* 函 数 名 : I2C1_Ack
* 函数功能 : 主机产生应答信号ACK
*******************************************************************************/
void I2C1_Ack(void)
{
I2C1_SCL_L;
I2C_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;
I2C_SDA_OUT();
I2C1_SDA_H;
Delay_us(1);
I2C1_SCL_H;
Delay_us(3);
I2C1_SCL_L;
}
/*******************************************************************************
* 函 数 名 : I2C1_Read_Byte
* 函数功能 : 主机读取一个字节
*******************************************************************************/
uint8_t I2C1_Read_Byte(uint8_t ack)
{
uint8_t i = 0, receive = 0,tempTime=0;
I2C1_SDA_IN();
for(i = 0; i < 8; i++)
{
I2C1_SCL_L;
Delay_us(2);
I2C1_SCL_H;
while((!GPIO_ReadInputDataBit(I2C1_PORT, SCL)) && tempTime < 10)
{
tempTime += 1;
Delay_us(1);
}
receive <<= 1;
if(GPIO_ReadInputDataBit(I2C1_PORT, SDA))receive++;
Delay_us(1);
}
if(ack == 0)
I2C1_NAck();
else
I2C1_Ack();
return receive;
}
/*******************************************************************************
* 函 数 名 : I2C1_Wait_Ack
* 函数功能 : 等待从机应答信号
返回值: 1 接收应答失败
0 接收应答成功
*******************************************************************************/
uint8_t I2C1_Wait_Ack(void) //返回值为0表示做出应答
{
uint8_t ucErrTime=0;
I2C1_SDA_IN();
I2C1_SDA_H;
Delay_us(1);
I2C1_SCL_H;
Delay_us(1);
while(GPIO_ReadInputDataBit(I2C1_PORT, SDA))
{
ucErrTime++;
Delay_us(1);
if(ucErrTime>250)
{
I2C1_Stop();
return 1;
}
}
I2C1_SCL_L;
Delay_us(1);
return 0;
}
3、GXP9541.h
#ifndef __GXP9541_H
#define __GXP9541_H
#include "stm32f10x.h"
// 初始化I2C1串口
void GXP9541_Init(void);
void GXP9541_Add(u8 add);
void GXP9541_Write(u8 add,u8 data);
void GXP9541_ReadData(void);
#endif
4、GXP9541.c
#include "GXP9541.h"
#include "Delay.h"
#include "stdio.h" // printf用
#include "Serial.h"
#include "I2C1.h"
uint16_t Pdata;
// 初始化I2C1串口
void GXP9541_Init(void)
{
I2C1_INIT();
}
void GXP9541_Add(u8 add)//写寄存器地址
{
I2C1_Start();//开始
I2C1_SendByte(0Xfe); //发送写地址
I2C1_Wait_Ack();
I2C1_SendByte(add); //要写的寄存器地址
I2C1_Wait_Ack();
I2C1_Stop();//停止
}
void GXP9541_Write(u8 add,u8 data)//向某寄存疲写某值
{
I2C1_Start();//开始
I2C1_SendByte(0Xfe); //发送写地址
I2C1_Wait_Ack();
I2C1_SendByte(add); //要写的寄存器地址
I2C1_Wait_Ack();
I2C1_SendByte(data); //要写的数据
I2C1_Wait_Ack();
I2C1_Stop();//停止
}
uint8_t GXP9541_Gather(void) //单次压力采集模式
{
uint8_t data=0;
GXP9541_Write(0X30,0X0a); //开始单次压力采集模式
GXP9541_Add(0X30); //写寄存器地址
data=I2C1_Read_Byte(0); //读取寄存器值
I2C1_Stop();//停止
if(data==0X02) //寄存器值为0X02时单次压力采集完成
{
return 1;
}
else
{
return 0;
}
}
void GXP9541_ReadData(void)
{
uint8_t i=0,ack=0;
uint8_t p[3];
while(GXP9541_Gather())//等待压力采集完成
{
I2C1_Start();//开始
GXP9541_Add(0X06);
Delay_ms(10);
I2C1_Start();
I2C1_SendByte(0Xff);
I2C1_Wait_Ack();
for(i=0;i<3;i++)
{
if(i<2)
{
ack=1;
}
else
{
ack=0;//最后一个发送nack
}
p[i]=I2C1_Read_Byte(ack);
}
I2C1_Stop();//停 止
}
Delay_ms(10);
// if(p[2] & 0X80)
// {
// Pdata=(float)(p[0]*65536+p[1]*256+p[2]-16777216);
// }
// else
// {
// Pdata=(float)(p[0]*65536+p[1]*256+p[2]);
// }
// Pa=(Pdata/8388608-0.5)/0.4*10; //Kpa
Serial_SendByte(p[0]);
Serial_SendByte(p[1]);
Serial_SendByte(p[2]);
}