打印
[应用相关]

CCS811读出的数值不变是因为什么问题

[复制链接]
147|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jcky001|  楼主 | 2023-12-21 15:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我用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;
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1522

主题

4615

帖子

6

粉丝