我用STM32f103c8t6写了一个系统,测试二氧化碳浓度;结果测出来的数值一直不变是怎么回事,硬件是新换的应该没有问题,那是哪里出错了呢,求解答
以下是驱动内容,难道是驱动的问题吗
#include "CCS811.h"
u8 BUF[12];
u8 Information[10];
u8 MeasureMode, Status, Error_ID;
u8 FlagGetId = 1;
u8 n = 4; // 3次读取ID都对则说明没问题
u8 temp = 0x5a;
ccs811_measurement_t CCS;
#define STEP_DELAY 100
void CCS811_GPIO_Config()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; // CCS811-CS
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
CCS811_CS_OFF();
CCS811_I2C_GPIO_Config(); //IIC GPIO Configure
delay_ms(1000); //等待模块初始化完成
delay_ms(1000); //等待模块初始化完成
delay_ms(1000);
}
void CCS811Init()
{
u8 idCount = 0; // count the correct times of id.
CCS811_CS_ON(); //nWAKE pin is asserted at least 50μs before the transaction and kept asserted throughout,nWAKE pin is active low
delay_ms(STEP_DELAY);
// get CCS811 device id,when addr pin connect to GND and the id is 0x81(129)
while( FlagGetId)
{
CCS811_ReadI2C(CCS811_Add, 0x20, Information, 1); //Read CCS's information ,ID
if(Information[0] == 0x81)
{
if(++idCount == n)
{
FlagGetId = 0;
}
else
{
printf("id=%d,correct %d!rn", Information[0], idCount);
}
}
else
{
printf("id=%d,incorrect,continuing...rn", Information[0]);
}
delay_ms(STEP_DELAY);
}
printf("id correct,initing...rn");
delay_ms(STEP_DELAY);
CCS811_ReadI2C(CCS811_Add, 0x23, &Information[1], 2); //FW_Boot_Version
delay_ms(STEP_DELAY);
CCS811_ReadI2C(CCS811_Add, 0x24, &Information[3], 2); //FW_App_Version
delay_ms(STEP_DELAY);
CCS811_ReadI2C(CCS811_Add, 0x00, &Status, 1); //Firstly the status register is read and the APP_VALID flag is checked.
delay_ms(STEP_DELAY);
// if there is valid application firmware loaded
if(Status & 0x10)
{
while(!(Status & 0x80)) // if firmware not in application mode but boot mode.
{
CCS811_WriteI2C_byte(CCS811_Add, 0xF3, 0xF0); // Application Verify
printf("trying to transition the CCS811 state from boot to application mode...rn");
CCS811_MWriteI2C_byte(CCS811_Add, 0xF4, &temp, 0); //Used to transition the CCS811 state from boot to application mode, a write with no data is required.
delay_ms(STEP_DELAY);
CCS811_ReadI2C(CCS811_Add, 0x00, &Status, 1);
delay_ms(STEP_DELAY);
}
printf("CCS811 is already in application mode!rn");
}
delay_ms(STEP_DELAY);
CCS811_ReadI2C(CCS811_Add, 0x01, &MeasureMode, 1);
delay_ms(STEP_DELAY);
MeasureMode &= 0x70; // get measure mode
//if measure mode incorrect,and reset the measure mode.
while(MeasureMode != DRIVE_MODE_1SEC)
{
CCS811_WriteI2C_byte(CCS811_Add, 0x01, DRIVE_MODE_1SEC); // Write Measure Mode Register,sensor measurement every second,no interrupt
delay_ms(STEP_DELAY);
CCS811_ReadI2C(CCS811_Add, 0x01, &MeasureMode, 1);
MeasureMode &= 0x70;
printf("trying to enter measure mode...rn");
delay_ms(STEP_DELAY);
}
delay_ms(STEP_DELAY);
CCS811_ReadI2C(CCS811_Add, 0x00, &Status, 1);
delay_ms(STEP_DELAY);
CCS811_ReadI2C(CCS811_Add, 0x01, &MeasureMode, 1);
delay_ms(STEP_DELAY);
CCS811_CS_OFF();
delay_ms(STEP_DELAY);
CCS811_ReadI2C(CCS811_Add, 0xE0, &Error_ID, 1);
printf("status=%d error_id=%d measureMode=%d rn", Status, Error_ID, MeasureMode);
}
void CCS811GetData()
{
CCS811_CS_ON(); // nWAKE pin is asserted at least 50μs before the transaction and kept asserted throughout,nWAKE pin is active low
delay_ms(10);
CCS811_ReadI2C(CCS811_Add, 0x02, BUF, 8);
delay_ms(10);
CCS811_ReadI2C(CCS811_Add, 0x20, Information, 1); // Read CCS's information ,ID
delay_ms(10);
CCS811_ReadI2C(CCS811_Add, 0xE0, &Error_ID, 1);
CCS811_CS_OFF();
CCS.eco2 = (u16)BUF[0] * 256 + BUF[1];
CCS.tvoc = (u16)BUF[2] * 256 + BUF[3];
CCS.device_id = Information[0];
CCS.error_id = Error_ID;
Error_ID = 0;
Information[0] = 0;
}
void CCS811ClearData()
{
CCS.device_id = 0;
CCS.eco2 = 0;
CCS.status = 0;
CCS.tvoc = 0;
CCS.error_id = 0;
}
//管教初始化驱动
#include "CCS811_IIC.h"
#include "delay.h"
#include "usart.h"
void CCS811_I2C_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* 使能与 I2C有关的时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );
/* PB10-I2C_SCL、PB11-I2C_SDA*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11| GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
SCL_H;
SDA_H;
}
void delay_1us(u8 x)//粗略延时,iic_40K
{
u8 i = 20;
x = i * x;
while(x--);
}
//////// IIC起始函数 //////////
/*
IIC起始:当SCL处于高电平期间,SDA由高电平变成低电平出现一个下降沿,然后SCL拉低
*/
u8 I2C_Start(void)
{
SDA_H;
delay_us(50); //延时保证时钟频率低于40K,以便从机识别
SCL_H;
delay_us(50);//延时保证时钟频率低于40K,以便从机识别
if(!SDA_read) return 0;//SDA线为低电平则总线忙,退出
SDA_L; //SCL处于高电平的时候,SDA拉低
delay_us(50);
if(SDA_read) return 0;//SDA线为高电平则总线出错,退出
SCL_L;
delay_us(50);
return 1;
}
//**************************************
//IIC停止信号
/*
IIC停止:当SCL处于高电平期间,SDA由低电平变成高电平出现一个上升沿
*/
//**************************************
void CCS811_I2C_Stop(void)
{
SDA_L;
SCL_L;
delay_us(50);
SCL_H;
delay_us(50);
SDA_H;//当SCL处于高电平期间,SDA由低电平变成高电平 //延时
}
//**************************************
//IIC发送应答信号
//入口参数:ack (0:ACK 1:NAK)
/*
应答:当从机接收到数据后,向主机发送一个低电平信号
先准备好SDA电平状态,在SCL高电平时,主机采样SDA
*/
//**************************************
void I2C_SendACK(u8 i)
{
if(1==i)
SDA_H; //准备好SDA电平状态,不应答
else
SDA_L; //准备好SDA电平状态,应答
SCL_H; //拉高时钟线
delay_us(50); //延时
SCL_L ; //拉低时钟线
delay_us(50);
}
///////等待从机应答////////
/*
当本机(主机)发送了一个数据后,等待从机应答
先释放SDA,让从机使用,然后采集SDA状态
*/
/////////////////
u8 I2C_WaitAck(void) //返回为:=1有ACK,=0无ACK
{
uint16_t i=0;
SDA_H; //释放SDA
SCL_H; //SCL拉高进行采样
while(SDA_read)//等待SDA拉低
{
i++; //等待计数
if(i==500)//超时跳出循环
break;
}
if(SDA_read)//再次判断SDA是否拉低
{
SCL_L;
return RESET;//从机应答失败,返回0
}
delay_us(50);//延时保证时钟频率低于40K,
SCL_L;
delay_us(50);//延时保证时钟频率低于40K,
return SET;//从机应答成功,返回1
}
//**************************************
//向IIC总线发送一个字节数据
/*
一个字节8bit,当SCL低电平时,准备好SDA,SCL高电平时,从机采样SDA
*/
//**************************************
void I2C_SendByte(u8 dat)
{
u8 i;
SCL_L;//SCL拉低,给SDA准备
for (i=0; i<8; i++) //8位计数器
{
if(dat&0x80)//SDA准备
SDA_H;
else
SDA_L;
SCL_H; //拉高时钟,给从机采样
delay_us(50); //延时保持IIC时钟频率,也是给从机采样有充足时间
SCL_L; //拉低时钟,给SDA准备
delay_us(50); //延时保持IIC时钟频率
dat <<= 1; //移出数据的最高位
}
}
//**************************************
//从IIC总线接收一个字节数据
//**************************************
u8 I2C_RecvByte()
{
u8 i;
u8 dat = 0;
SDA_H;//释放SDA,给从机使用
delay_us(50); //delay_1us(50); //延时给从机准备SDA时间
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1;
SCL_H; //拉高时钟线,采样从机SDA
if(SDA_read) //读数据
dat |=0x01;
delay_us(50); //延时保持IIC时钟频率
SCL_L; //拉低时钟线,处理接收到的数据
delay_us(50); //延时给从机准备SDA时间
}
return dat;
}
//**************************************
//向IIC设备写入一个字节数据
//**************************************
u8 CCS811_WriteI2C_byte(u8 Slave_Address,u8 REG_Address,u8 data)
{
if(I2C_Start()==0) //起始信号
{CCS811_I2C_Stop(); return RESET;}
I2C_SendByte(Slave_Address); //发送设备地址+写信号
if(!I2C_WaitAck()){CCS811_I2C_Stop(); return RESET;}
I2C_SendByte(REG_Address); //内部寄存器地址,
if(!I2C_WaitAck()){CCS811_I2C_Stop(); return RESET;}
I2C_SendByte(data); //内部寄存器数据,
if(!I2C_WaitAck()){CCS811_I2C_Stop(); return RESET;}
CCS811_I2C_Stop(); //发送停止信号
return SET;
}
u8 CCS811_MWriteI2C_byte(u8 Slave_Address,u8 REG_Address,u8 const *data,u8 length)
{
if(I2C_Start()==0) //起始信号
{CCS811_I2C_Stop(); return RESET;}
I2C_SendByte(Slave_Address); //发送设备地址+写信号
if(!I2C_WaitAck()){CCS811_I2C_Stop(); return RESET;}
I2C_SendByte(REG_Address); //内部寄存器地址,
if(!I2C_WaitAck()){CCS811_I2C_Stop(); return RESET;}
while(length)
{
I2C_SendByte(*data++); //内部寄存器数据,
if(!I2C_WaitAck()){CCS811_I2C_Stop(); return RESET;} //应答
length--;
}
// I2C_SendByte(*data); //内部寄存器数据,
// if(!I2C_WaitAck()){CCS811_I2C_Stop(); return RESET;}
CCS811_I2C_Stop(); //发送停止信号
return SET;
}
//**************************************
//从IIC设备读取一个字节数据
//**************************************
u8 CCS811_ReadI2C(u8 Slave_Address,u8 REG_Address,u8 *REG_data,u8 length)
{
if(I2C_Start()==0) //起始信号
{CCS811_I2C_Stop(); return RESET;}
I2C_SendByte(Slave_Address); //发送设备地址+写信号
if(!I2C_WaitAck()){CCS811_I2C_Stop(); return RESET;}
I2C_SendByte(REG_Address); //发送存储单元地址
if(!I2C_WaitAck()){CCS811_I2C_Stop(); return RESET;}
if(I2C_Start()==0) //起始信号
{CCS811_I2C_Stop(); return RESET;}
I2C_SendByte(Slave_Address+1); //发送设备地址+读信号
if(!I2C_WaitAck()){CCS811_I2C_Stop(); return RESET;}
while(length-1)
{
*REG_data++=I2C_RecvByte(); //读出寄存器数据
I2C_SendACK(0); //应答
length--;
}
*REG_data=I2C_RecvByte();
I2C_SendACK(1); //发送停止传输信号
CCS811_I2C_Stop(); //停止信号
return SET;
} |