完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
我用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; } |
|
相关推荐
3个回答
|
|
看状态寄存器的值,推荐一个:http://www.ruikang.net/index.php/dpjplccpld/2489.html
|
|
|
|
你调试看看IO口电平变化,用外用表查查就知道了
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
2105 浏览 1 评论
AD7686芯片不传输数据给STM32,但是手按住就会有数据。
1941 浏览 3 评论
4537 浏览 0 评论
如何解决MPU-9250与STM32通讯时,出现HAL_ERROR = 0x01U
2084 浏览 1 评论
hal库中i2c卡死在HAL_I2C_Master_Transmit
2599 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 10:01 , Processed in 0.830077 second(s), Total 52, Slave 45 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号