说明:
//SGP30的SCL引脚定义
sbit SCL = P1^6;
//SGP30的SDA引脚定义
sbit SDA = P1^7;
SGP-30.h:
#ifndef __SGP30_H
#define __SGP30_H
#include "main.h"
#define SGP30_read 0xb1 //SGP30的读地址
#define SGP30_write 0xb0 //SGP30的写地址
#define ACK 0 //应答信号
#define NACK 1 //非应答信号
sbit SCL = P1^6; //SGP30的SCL引脚定义
sbit SDA = P1^7; //SGP30的SDA引脚定义
//I2C起始信号
void I2CStart(void);
//I2C停止信号
void I2CStop(void);
//I2C写一个字节数据,返回ACK或者NACK
u8 I2C_Write_Byte(u8 Write_Byte);
//I2C读一个字节数据,入口参数用于控制应答状态,ACK或者NACK
u8 I2C_Read_Byte(u8 AckValue);
//初始化SGP30
void SGP30_Init(void);
//向SGP30写数据
void SGP30_Write(u8 a, u8 b);
//从SGP30读数据
u32 SGP30_Read(void);
#endif
SGP-30.c:
#include "SGP30.H"
#include "delay.h"
//模拟IIC用的短延时 us
void I2C_Delay (u8 t)
{
while(t--);
}
//I2C起始信号
void I2CStart(void)
{
SDA = 1; //发送起始条件的数据信号
SCL = 1;
I2C_Delay(50); //起始条件建立时间大于4.7us,延时
SDA = 0; //发送起始信号
I2C_Delay(50); //起始条件锁定时间大于4μs
SCL = 0; //钳住I2C总线,准备发送或接收数据
I2C_Delay(50);
}
//I2C停止信号
void I2CStop(void)
{
SDA = 0; //发送结束条件的数据信号
SCL = 0;
I2C_Delay(50);
SCL = 1; //发送结束条件的时钟信号
I2C_Delay(50); //结束条件建立时间大于4μs
SDA = 1; //发送I2C总线结束信号
I2C_Delay(50);
}
//I2C写一个字节数据,返回ACK或者NACK
u8 I2C_Write_Byte(u8 Write_Byte) //Sendbyte
{
u8 i;
SCL=0;
I2C_Delay(10);
for(i=0; i<8; i++) //要传送的数据长度为8位
{
if(Write_Byte&0x80) //判断发送位
{
SDA = 1;
}
else
{
SDA = 0;
}
I2C_Delay(5);
SCL=1; //输出SDA稳定后,拉高SCL给出上升沿,从机检测到后进行数据采样
I2C_Delay(5); //保证时钟高电平周期大于4μs
SCL=0;
I2C_Delay(5);
Write_Byte <<= 1;
}
I2C_Delay(1);
SDA = 1; //8位发送完后释放数据线,准备接收应答位-ZLG
I2C_Delay(40);
SCL = 1; //MCU告知SHT2X数据发送完毕,等待从机的应答信号
I2C_Delay(40);
/*以下是判断I2C总线接收应到应答信号是ACK还是NACK*/
if(SDA==1) //SDA为高,收到NACK
{
I2C_Delay(40);
SCL=0;
return NACK;
}
else //SDA为低,收到ACK
{
I2C_Delay(40);
SCL=0;
return ACK;
}
}
//I2C读一个字节数据,入口参数用于控制应答状态,ACK或者NACK
u8 I2C_Read_Byte(u8 AckValue)//receivebyte
{
u8 i,RDByte=0;
SCL=0; //置时钟线为低,准备接收数据位
I2C_Delay(40);
SDA = 1; //释放总线,置数据线为输入方式
for (i=0; i<8; i++)
{
SCL = 1; //SCL高电平期间,采集SDA信号,并作为有效数据 //置时钟线为高使数据线上数据有效
I2C_Delay(20);
RDByte <<= 1; //移位
if(SDA==1) //采样获取数据
{
RDByte |= 0x01;
}
else
{
RDByte &= 0xfe;
}
I2C_Delay(10);
SCL = 0; //下降沿,从机给出下一位值
I2C_Delay(60);
}
/*以下是I2C总线发送应答信号ACK或者NACK*/
SDA = AckValue; //应答状态
I2C_Delay(30);
SCL = 1;
I2C_Delay(50); //时钟低电平周期大于4μs
SCL = 0; //清时钟线,钳住I2C总线以便继续接收
I2C_Delay(50);
return RDByte;
}
//初始化IIC接口
void SGP30_Init(void)
{
SCL = 1;
I2C_Delay(50);
SDA = 1;
I2C_Delay(50);
SGP30_Write(0x20,0x03);
// SGP30_ad_write(0x20,0x61);
// SGP30_ad_write(0x01,0x00);
}
void SGP30_Write(u8 a, u8 b)
{
I2CStart();
I2C_Write_Byte(SGP30_write); //发送器件地址+写指令
I2C_Write_Byte(a); //发送控制字节
I2C_Write_Byte(b);
I2CStop();
delay_ms(20);
}
unsigned long SGP30_Read(void)
{
unsigned long dat;
int crc;
I2CStart();
I2C_Write_Byte(SGP30_read); //发送器件地址+读指令
dat = I2C_Read_Byte(ACK);
dat <<= 8;
dat += I2C_Read_Byte(ACK);
crc = I2C_Read_Byte(ACK); //check数据,舍去
crc = crc; //避免编译产生警告,这句可有可无
dat <<= 8;
dat += I2C_Read_Byte(ACK);
dat <<= 8;
dat += I2C_Read_Byte(NACK);
I2CStop();
delay_ms(20);
return(dat);
}