目录
1.cubemx的IIC配置
2.SGP40的软件编写
#ifndef __SGP40_H__
#define __SGP40_H__
#include "main.h"
#define SGP40_SEIF_SUCESS 0xD4 //all tests passed successfully
#define SGP40_SEIF_FAIL 0x4B //one or more tests have failed
typedef enum{
sgp40_measure_raw_signal = 0x260F,
sgp40_execute_self_test = 0x280E, //传感器自检
sgp4x_turn_heater_off = 0x3615, //关闭加热板并进入空闲模式
sgp4x_get_serial_number = 0x3682, //获得该传感器的序列号
sgp40_soft_reset = 0x0006, //复位传感器
}SGP40Commond;
uint8_t SGP40_MeasureRaw(float humidity,float temperature);
uint8_t SGP40_MeasureVocIndex(float humidity,float temperature,float * Voc,uint16_t *Voc_AD);
void SGP40_reset(void);
uint8_t SGP40_Read_Dat(uint8_t* dat,uint8_t Size);
uint8_t SGP40_Init(void);
#endif
#include "SGP40.h"
#include "i2c.h"
#include <rtthread.h>
#include <rtdbg.h>
#define SGP40_ADDR_WRITE 0x59<<1 //10110010
#define SGP40_ADDR_READ (0x59<<1)+1 //10110011
#define SGP40_CRC8_POLYNOMIAL 0x31
static uint8_t SGP40_CheckCrc8(uint8_t* const message, uint8_t initial_value)
{
uint8_t remainder; //余数
uint8_t i = 0, j = 0; //循环变量
/* 初始化 */
remainder = initial_value;
for(j = 0; j < 2;j++)
{
remainder ^= message[j];
/* 从最高位开始依次计算 */
for (i = 0; i < 8; i++)
{
if (remainder & 0x80)
{
remainder = (remainder << 1)^SGP40_CRC8_POLYNOMIAL;
}
else
{
remainder = (remainder << 1);
}
}
}
/* 返回计算的CRC码 */
return remainder;
}
/**
* @brief 将SGP40接收的3字节数据进行CRC校验
* @param dat —— 存储接收数据的地址(3个字节数组)
* @retval 校验成功 —— 返回0
* 校验失败 —— 返回1
*/
uint8_t SGP40_Dat_CRC(uint8_t* const dat)
{
if(SGP40_CheckCrc8(dat, 0xFF) != dat[2])
return 1;
else
return 0;
}
/**
* @brief 向SGP40发送一条指令
* @param cmd —— SGP40指令(SGP40Commond中枚举定义),
* @retval 成功返回HAL_OK
*/
static uint8_t SGP40_Send_Cmd(SGP40Commond cmd)
{
uint8_t cmd_buffer[2];
cmd_buffer[0] = cmd >> 8;
cmd_buffer[1] = cmd;
return HAL_I2C_Master_Transmit(&hi2c1, SGP40_ADDR_WRITE, (uint8_t*) cmd_buffer, 2, 0x00FF);
}
/**
* @brief 向SGP40发送测量指令
* @param cmd —— SGP40指令(SGP40Commond中枚举定义),
* @retval 成功返回HAL_OK
*/
uint8_t SGP40_MeasureRaw(float humidity,float temperature)
{
uint8_t cmd_buffer[8];
uint16_t rhticks = 0;
uint16_t tempticks = 0;
cmd_buffer[0] = 0x26;
cmd_buffer[1] = 0x0F;
rhticks = (uint16_t)((humidity * 65535) / 100 + 0.5f);
cmd_buffer[2] = rhticks >> 8;
cmd_buffer[3] = rhticks & 0xFF;
cmd_buffer[4] = SGP40_CheckCrc8(cmd_buffer + 2, 0xFF);
tempticks = (uint16_t)(((temperature + 45) * 65535) / 175);
cmd_buffer[5] = tempticks >> 8;
cmd_buffer[6] = tempticks & 0xFF;
cmd_buffer[7] = SGP40_CheckCrc8(cmd_buffer + 5, 0xFF);
return HAL_I2C_Master_Transmit(&hi2c1, SGP40_ADDR_WRITE, (uint8_t*) cmd_buffer, 8, 0x00FF);
}
/**
* @brief 向SGP4获得数据
* @param
* @retval 成功返回HAL_OK
*/
uint8_t SGP40_MeasureVocIndex(float humidity,float temperature,float * Voc,uint16_t *Voc_AD)
{
uint8_t voc[3] = {0};
if(SGP40_MeasureRaw(temperature, humidity)==0)
{
rt_thread_mdelay(30);
if(SGP40_Read_Dat(voc,3) == 0)
{
if(SGP40_CheckCrc8(voc,0xff) == voc[2]) //校验正确
{
*Voc_AD = voc[0]<<8|voc[1];
* Voc = (*Voc_AD)*3.3/65535;
}
else
return 3;
}
else
{
return 2;
}
}
else
{
return 1;
}
return 0;
}
/**
* @brief 自检SGP40
* @param none
* @retval 成功返回 0
*/
uint8_t SGP40_SEIF(void)
{
uint8_t Temp[3] = {0};
SGP40_Send_Cmd(sgp40_execute_self_test); //自检
rt_thread_mdelay(320); //数据手册定义
if(SGP40_Read_Dat(Temp, 3)==HAL_OK)
{
if(SGP40_Dat_CRC(Temp)!=0) return 1;
else
{
if(Temp[0]!=SGP40_SEIF_SUCESS)
{
rt_kprintf("SGP40_SEIF_Fali\r\n");
return 1;
}
else
return 0;
}
}
else
{
rt_kprintf("SGP40_READ_DAT_FAIL\r\n");
return 1;
}
}
/**
* @brief 复位SGP40
* @param none
* @retval none
*/
void SGP40_reset(void)
{
SGP40_Send_Cmd(sgp40_soft_reset);
rt_thread_mdelay(20);
}
/**
* @brief 从SGP40读取一次数据
* @param dat —— 存储读取数据的地址(6个字节数组)
* @retval 成功 —— 返回HAL_OK
*/
uint8_t SGP40_Read_Dat(uint8_t* dat,uint8_t Size)
{
return HAL_I2C_Master_Receive(&hi2c1, SGP40_ADDR_READ, dat, Size, 0xFFFF);
}
/**
* @brief 初始化SGP40
* @param none
* @retval 成功返回HAL_OK
* @note 周期测量模式
*/
uint8_t SGP40_Init(void)
{
if(SGP40_SEIF()==0)
{
return 0;
}
else
{
rt_kprintf("SGP40_SEIF_Fali\r\n");
return HAL_ERROR;
}
}
欢迎指正